quickwin 2.1.1 → 2.3.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 (117) hide show
  1. package/README.en.md +9 -9
  2. package/README.md +9 -9
  3. package/constants.ts +1063 -0
  4. package/enum_map.d.ts +129 -0
  5. package/examples/PdfCanvas.js +2 -2
  6. package/examples/PdfCanvas.tsx +3 -2
  7. package/examples/{exec_server.js → execd/main.js} +1114 -287
  8. package/examples/execd/tray.js +192 -0
  9. package/examples/execd/worker.js +122 -0
  10. package/examples/pdf_preview2.js +46 -46
  11. package/examples/pdf_preview2.ts +55 -54
  12. package/examples/pdf_viewer.js +134 -130
  13. package/examples/pdf_viewer.tsx +6 -5
  14. package/examples/test_gallery.js +135 -131
  15. package/examples/test_gallery.tsx +9 -8
  16. package/examples/test_react_lazy.js +130 -128
  17. package/examples/test_react_lazy.tsx +7 -6
  18. package/examples/test_react_listbox.js +130 -128
  19. package/examples/test_react_listbox.tsx +8 -7
  20. package/examples/test_root_window.js +130 -128
  21. package/examples/test_root_window.tsx +5 -5
  22. package/examples/test_tab.js +130 -128
  23. package/examples/test_tab.tsx +7 -6
  24. package/examples/tray_demo.js +8 -8
  25. package/examples/tray_demo.tsx +9 -8
  26. package/lib/dumpRects.js +2 -2
  27. package/lib/dumpRects.ts +3 -2
  28. package/lib/fetch.js +15 -15
  29. package/lib/fetch.ts +16 -15
  30. package/lib/ffi/bind.js +3 -3
  31. package/lib/ffi/bind.ts +3 -3
  32. package/lib/ffi/ctype.ts +3 -1
  33. package/lib/ffi/struct.js +23 -7
  34. package/lib/ffi/struct.ts +50 -23
  35. package/lib/http-server.js +5 -5
  36. package/lib/http-server.ts +6 -5
  37. package/lib/react-qw/components/Button.js +2 -2
  38. package/lib/react-qw/components/CheckBox.js +4 -4
  39. package/lib/react-qw/components/ComboBox.js +10 -10
  40. package/lib/react-qw/components/DateTimePicker.js +12 -12
  41. package/lib/react-qw/components/Input.js +7 -7
  42. package/lib/react-qw/components/Link.js +4 -4
  43. package/lib/react-qw/components/ListBox.js +12 -12
  44. package/lib/react-qw/components/ListView.js +35 -35
  45. package/lib/react-qw/components/PathPicker.js +3 -3
  46. package/lib/react-qw/components/ProgressBar.js +4 -4
  47. package/lib/react-qw/components/RadioButton.js +4 -4
  48. package/lib/react-qw/components/ScrollView.js +28 -28
  49. package/lib/react-qw/components/Slider.js +11 -11
  50. package/lib/react-qw/components/Tab.js +10 -10
  51. package/lib/react-qw/components/Tooltip.js +8 -8
  52. package/lib/react-qw/components/TreeView.js +20 -20
  53. package/lib/react-qw/index.js +5 -5
  54. package/lib/react-qw/index.ts +6 -5
  55. package/lib/react-qw/props.js +4 -4
  56. package/lib/react-qw/props.ts +5 -4
  57. package/lib/react-qw/reconciler.js +10 -10
  58. package/lib/react-qw/reconciler.ts +11 -10
  59. package/lib/text-measure.js +3 -3
  60. package/lib/text-measure.ts +4 -3
  61. package/lib/websocket.js +17 -17
  62. package/lib/websocket.ts +18 -17
  63. package/lib/windows/advapi32.js +7 -7
  64. package/lib/windows/advapi32.ts +7 -7
  65. package/lib/windows/gdi32.js +17 -17
  66. package/lib/windows/gdi32.ts +17 -17
  67. package/lib/windows/kernel32.js +41 -2
  68. package/lib/windows/kernel32.ts +45 -2
  69. package/lib/windows/shell32.js +24 -3
  70. package/lib/windows/shell32.ts +27 -4
  71. package/lib/windows/structs.js +230 -92
  72. package/lib/windows/structs.ts +278 -92
  73. package/lib/windows/user32.js +18 -6
  74. package/lib/windows/user32.ts +18 -6
  75. package/lib/windows/winspool.js +3 -3
  76. package/lib/windows/winspool.ts +3 -3
  77. package/package.json +4 -3
  78. package/quickwin.d.ts +32 -10
  79. package/qwin-nowasm-x86.exe +0 -0
  80. package/qwin-nowasm.exe +0 -0
  81. package/qwin-x86.exe +0 -0
  82. package/qwin.exe +0 -0
  83. package/test/test_ffi_bind.js +12 -10
  84. package/test/test_ffi_bind.ts +14 -12
  85. package/test/test_ffi_struct.js +60 -26
  86. package/test/test_ffi_struct.ts +58 -28
  87. package/test/test_ffi_windows.js +1 -1
  88. package/test/test_ffi_windows.ts +1 -1
  89. package/test/test_files.js +7 -7
  90. package/test/test_files.ts +8 -8
  91. package/test/test_gdi_draw.js +51 -51
  92. package/test/test_gdi_draw.ts +57 -57
  93. package/test/test_http_server.js +3 -3
  94. package/test/test_http_server.ts +4 -3
  95. package/test/test_ipv6.js +3 -3
  96. package/test/test_ipv6.ts +4 -3
  97. package/test/test_net_event.js +3 -3
  98. package/test/test_net_event.ts +4 -3
  99. package/test/test_printer.js +4 -4
  100. package/test/test_printer.ts +5 -5
  101. package/test/test_react_complex.js +132 -130
  102. package/test/test_react_counter.js +130 -128
  103. package/test/test_react_flex.js +132 -130
  104. package/test/test_react_hidden.js +130 -128
  105. package/test/test_react_listview_link.js +131 -129
  106. package/test/test_react_notify.js +148 -146
  107. package/test/test_react_render.js +130 -128
  108. package/test/test_registry.js +6 -6
  109. package/test/test_registry.ts +8 -8
  110. package/test/test_wolfssl_read.js +8 -8
  111. package/test/test_wolfssl_read.ts +9 -8
  112. package/examples/exec_server.tsx +0 -488
  113. package/examples/exec_server_worker.js +0 -395
  114. package/examples/exec_server_worker.ts +0 -417
  115. package/examples/setres.js +0 -79
  116. package/examples/setres.ts +0 -86
  117. package/quickwin_const.d.ts +0 -1037
@@ -1,5 +1,6 @@
1
1
  import * as gui from 'gui'
2
2
  import * as std from 'std'
3
+ import { IDI, ImageType, LoadImageFlag, NotifyIconCmd, NotifyIconFlag, WindowStyle, WmMsg } from '../constants'
3
4
 
4
5
  const WM_TRAY = 0x8001
5
6
 
@@ -24,14 +25,14 @@ gui.RegisterClass('TrayApp', (hwnd, msg, wParam, lParam) => {
24
25
  if (cmd === 1) {
25
26
  gui.ShowWindow(hwnd, 5) // SW_SHOW
26
27
  } else if (cmd === 2) {
27
- gui.ShellNotifyIcon(gui.NotifyIconCmd.DELETE, { hwnd, uID: 1 })
28
+ gui.ShellNotifyIcon(NotifyIconCmd.DELETE, { hwnd, uID: 1 })
28
29
  gui.PostQuitMessage(0)
29
30
  }
30
31
  }
31
32
  }
32
33
  return 0
33
34
  }
34
- if (msg === gui.WmMsg.CLOSE) {
35
+ if (msg === WmMsg.CLOSE) {
35
36
  gui.ShowWindow(hwnd, 0) // SW_HIDE
36
37
  return 0
37
38
  }
@@ -43,14 +44,14 @@ const W = 500, H = 400
43
44
  const scr = gui.GetScreenSize()
44
45
  const x = (scr[0] - W) >> 1
45
46
  const y = (scr[1] - H) >> 1
46
- const hwnd = gui.CreateWindow('TrayApp', '系统托盘示例', gui.WindowStyle.OVERLAPPEDWINDOW, x, y, W, H, null, null)
47
+ const hwnd = gui.CreateWindow('TrayApp', '系统托盘示例', WindowStyle.OVERLAPPEDWINDOW, x, y, W, H, null, null)
47
48
  if (!hwnd) std.exit(0)
48
49
  gui.ShowWindow(hwnd)
49
50
 
50
51
  // 添加说明文字
51
52
  const ES_MULTILINE = 0x0004
52
53
  const ES_READONLY = 0x0800
53
- const style = gui.WindowStyle.CHILD | gui.WindowStyle.VISIBLE | ES_MULTILINE | ES_READONLY
54
+ const style = WindowStyle.CHILD | WindowStyle.VISIBLE | ES_MULTILINE | ES_READONLY
54
55
  const text = gui.CreateWindow('EDIT',
55
56
  'QuickWin 系统托盘示例\r\n'
56
57
  + '\r\n'
@@ -61,15 +62,15 @@ const text = gui.CreateWindow('EDIT',
61
62
  if (text) {
62
63
  const font = gui.CreateSystemDpiFont()
63
64
  if (font)
64
- gui.SendMessage(text, gui.WmMsg.SETFONT, font, 1)
65
+ gui.SendMessage(text, WmMsg.SETFONT, font, 1)
65
66
  }
66
67
 
67
68
  let hIcon = gui.LoadAppIcon()
68
- if (!hIcon) hIcon = gui.LoadImage(null, gui.IDI.APPLICATION, gui.ImageType.ICON, 0, 0, gui.LoadImageFlag.SHARED)
69
+ if (!hIcon) hIcon = gui.LoadImage(null, IDI.APPLICATION, ImageType.ICON, 0, 0, LoadImageFlag.SHARED)
69
70
  if (hIcon) {
70
- const ok = gui.ShellNotifyIcon(gui.NotifyIconCmd.ADD, {
71
+ const ok = gui.ShellNotifyIcon(NotifyIconCmd.ADD, {
71
72
  hwnd: hwnd, uID: 1,
72
- flags: gui.NotifyIconFlag.MESSAGE | gui.NotifyIconFlag.ICON,
73
+ flags: NotifyIconFlag.MESSAGE | NotifyIconFlag.ICON,
73
74
  callbackMessage: WM_TRAY,
74
75
  hIcon,
75
76
  })
package/lib/dumpRects.js CHANGED
@@ -2,7 +2,7 @@ import * as os from 'os';
2
2
  import * as gui from 'gui';
3
3
  export function startDumpRects(rootHwnd, intervalMs = 3000) {
4
4
  function dumpChild(parent, indent) {
5
- var ch = gui.GetWindow(parent, 5 /* gui.GetWindowCmd.CHILD */);
5
+ var ch = gui.GetWindow(parent, 5 /* GetWindowCmd.CHILD */);
6
6
  var n = 0;
7
7
  while (ch) {
8
8
  n++;
@@ -11,7 +11,7 @@ export function startDumpRects(rootHwnd, intervalMs = 3000) {
11
11
  var txt = String(gui.GetWindowText(ch) || '').slice(0, 16);
12
12
  console.log(indent + '[' + n + '] hwnd=' + String(ch) + ' txt="' + txt + '" wr=' + JSON.stringify(wr) + ' cr=' + JSON.stringify(cr));
13
13
  dumpChild(ch, indent + ' ');
14
- ch = gui.GetWindow(ch, 2 /* gui.GetWindowCmd.NEXT */);
14
+ ch = gui.GetWindow(ch, 2 /* GetWindowCmd.NEXT */);
15
15
  }
16
16
  if (n === 0)
17
17
  console.log(indent + '(no children)');
package/lib/dumpRects.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import * as os from 'os'
2
2
  import * as gui from 'gui'
3
+ import { GetWindowCmd } from '../constants'
3
4
 
4
5
  export function startDumpRects(rootHwnd: gui.HWND, intervalMs: number = 3000): void {
5
6
  function dumpChild(parent: gui.HWND, indent: string): void {
6
- var ch = gui.GetWindow(parent, gui.GetWindowCmd.CHILD)
7
+ var ch = gui.GetWindow(parent, GetWindowCmd.CHILD)
7
8
  var n = 0
8
9
  while (ch) {
9
10
  n++
@@ -12,7 +13,7 @@ export function startDumpRects(rootHwnd: gui.HWND, intervalMs: number = 3000): v
12
13
  var txt = String(gui.GetWindowText(ch) || '').slice(0, 16)
13
14
  console.log(indent + '[' + n + '] hwnd=' + String(ch) + ' txt="' + txt + '" wr=' + JSON.stringify(wr) + ' cr=' + JSON.stringify(cr))
14
15
  dumpChild(ch, indent + ' ')
15
- ch = gui.GetWindow(ch, gui.GetWindowCmd.NEXT)
16
+ ch = gui.GetWindow(ch, GetWindowCmd.NEXT)
16
17
  }
17
18
  if (n === 0) console.log(indent + '(no children)')
18
19
  }
package/lib/fetch.js CHANGED
@@ -180,7 +180,7 @@ async function fetchRequest(req) {
180
180
  sock.set_on_event(fd, (event) => {
181
181
  if (state === ST_DONE)
182
182
  return;
183
- if (event.lNetworkEvents & 16 /* sock.FdEvent.FD_CONNECT */) {
183
+ if (event.lNetworkEvents & 16 /* FdEvent.FD_CONNECT */) {
184
184
  const err = event.iErrorCode[0];
185
185
  if (err !== 0) {
186
186
  doReject(new Error('Connection failed: ' + err));
@@ -194,10 +194,10 @@ async function fetchRequest(req) {
194
194
  return;
195
195
  }
196
196
  if (req.rejectUnauthorized === false) {
197
- wolfssl.wolfSSL_CTX_set_verify(ctx, 0 /* wolfssl.VerifyMode.SSL_VERIFY_NONE */);
197
+ wolfssl.wolfSSL_CTX_set_verify(ctx, 0 /* VerifyMode.SSL_VERIFY_NONE */);
198
198
  }
199
199
  else {
200
- wolfssl.wolfSSL_CTX_set_verify(ctx, 1 /* wolfssl.VerifyMode.SSL_VERIFY_PEER */);
200
+ wolfssl.wolfSSL_CTX_set_verify(ctx, 1 /* VerifyMode.SSL_VERIFY_PEER */);
201
201
  wolfssl.loadTrustedCerts(ctx);
202
202
  }
203
203
  ssl = wolfssl.wolfSSL_new(ctx);
@@ -207,7 +207,7 @@ async function fetchRequest(req) {
207
207
  }
208
208
  wolfssl.wolfSSL_set_fd(ssl, sock.get_fd(fd));
209
209
  if (parsedUrl.hostname) {
210
- wolfssl.wolfSSL_UseSNI(ssl, 0 /* wolfssl.SniType.WOLFSSL_SNI_HOST_NAME */, parsedUrl.hostname);
210
+ wolfssl.wolfSSL_UseSNI(ssl, 0 /* SniType.WOLFSSL_SNI_HOST_NAME */, parsedUrl.hostname);
211
211
  if (req.rejectUnauthorized !== false) {
212
212
  wolfssl.wolfSSL_check_domain_name(ssl, parsedUrl.hostname);
213
213
  }
@@ -219,21 +219,21 @@ async function fetchRequest(req) {
219
219
  state = ST_RECV_HEADERS;
220
220
  }
221
221
  }
222
- if ((event.lNetworkEvents & 1 /* sock.FdEvent.FD_READ */) || (event.lNetworkEvents & 2 /* sock.FdEvent.FD_WRITE */)) {
222
+ if ((event.lNetworkEvents & 1 /* FdEvent.FD_READ */) || (event.lNetworkEvents & 2 /* FdEvent.FD_WRITE */)) {
223
223
  if (state === ST_HANDSHAKE) {
224
224
  if (!ssl) {
225
225
  doReject(new Error('TLS not initialized'));
226
226
  return;
227
227
  }
228
228
  const ret = wolfssl.wolfSSL_connect(ssl);
229
- if (ret === 1 /* wolfssl.ReturnCode.SSL_SUCCESS */) {
229
+ if (ret === 1 /* ReturnCode.SSL_SUCCESS */) {
230
230
  wolfssl.wolfSSL_write(ssl, httpRequest);
231
231
  state = ST_RECV_HEADERS;
232
232
  }
233
233
  else {
234
234
  const err = wolfssl.wolfSSL_get_error(ssl, ret);
235
- if (err !== 2 /* wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_READ */ &&
236
- err !== 3 /* wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_WRITE */) {
235
+ if (err !== 2 /* WolfsslErrorCode.WOLFSSL_ERROR_WANT_READ */ &&
236
+ err !== 3 /* WolfsslErrorCode.WOLFSSL_ERROR_WANT_WRITE */) {
237
237
  doReject(new Error('TLS handshake failed: ' + err));
238
238
  }
239
239
  }
@@ -251,10 +251,10 @@ async function fetchRequest(req) {
251
251
  }
252
252
  else {
253
253
  const err = wolfssl.wolfSSL_get_error(ssl, n);
254
- if (err === 2 /* wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_READ */ ||
255
- err === 3 /* wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_WRITE */)
254
+ if (err === 2 /* WolfsslErrorCode.WOLFSSL_ERROR_WANT_READ */ ||
255
+ err === 3 /* WolfsslErrorCode.WOLFSSL_ERROR_WANT_WRITE */)
256
256
  break;
257
- if (n === 0 || err === 6 /* wolfssl.ErrorCode.WOLFSSL_ERROR_ZERO_RETURN */)
257
+ if (n === 0 || err === 6 /* WolfsslErrorCode.WOLFSSL_ERROR_ZERO_RETURN */)
258
258
  break;
259
259
  doReject(new Error('TLS read failed: ' + err));
260
260
  return;
@@ -338,10 +338,10 @@ async function fetchRequest(req) {
338
338
  }
339
339
  else {
340
340
  const err = wolfssl.wolfSSL_get_error(ssl, n);
341
- if (err === 2 /* wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_READ */ ||
342
- err === 3 /* wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_WRITE */)
341
+ if (err === 2 /* WolfsslErrorCode.WOLFSSL_ERROR_WANT_READ */ ||
342
+ err === 3 /* WolfsslErrorCode.WOLFSSL_ERROR_WANT_WRITE */)
343
343
  break;
344
- if (n === 0 || err === 6 /* wolfssl.ErrorCode.WOLFSSL_ERROR_ZERO_RETURN */)
344
+ if (n === 0 || err === 6 /* WolfsslErrorCode.WOLFSSL_ERROR_ZERO_RETURN */)
345
345
  break;
346
346
  // Fatal TLS error mid-body: the response already
347
347
  // resolved, so fail the body stream instead of
@@ -390,7 +390,7 @@ async function fetchRequest(req) {
390
390
  }
391
391
  }
392
392
  }
393
- if (event.lNetworkEvents & 32 /* sock.FdEvent.FD_CLOSE */) {
393
+ if (event.lNetworkEvents & 32 /* FdEvent.FD_CLOSE */) {
394
394
  if (state === ST_DONE)
395
395
  return;
396
396
  if (state === ST_RECV_HEADERS) {
package/lib/fetch.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  RequestImpl,
13
13
  ResponseImpl,
14
14
  } from './http-common.js'
15
+ import { FdEvent, ReturnCode, SniType, VerifyMode, WolfsslErrorCode } from '../constants'
15
16
 
16
17
  // ── HTTP Response Parser ──
17
18
 
@@ -178,7 +179,7 @@ async function fetchRequest(req: RequestImpl): Promise<ResponseImpl> {
178
179
  sock.set_on_event(fd, (event: { lNetworkEvents: number; iErrorCode: number[] }) => {
179
180
  if (state === ST_DONE) return
180
181
 
181
- if (event.lNetworkEvents & sock.FdEvent.FD_CONNECT) {
182
+ if (event.lNetworkEvents & FdEvent.FD_CONNECT) {
182
183
  const err = event.iErrorCode[0]
183
184
  if (err !== 0) { doReject(new Error('Connection failed: ' + err)); return }
184
185
 
@@ -187,16 +188,16 @@ async function fetchRequest(req: RequestImpl): Promise<ResponseImpl> {
187
188
  ctx = wolfssl.wolfSSL_CTX_new(tlsMethod)
188
189
  if (!ctx) { doReject(new Error('SSL_CTX_new failed')); return }
189
190
  if (req.rejectUnauthorized === false) {
190
- wolfssl.wolfSSL_CTX_set_verify(ctx, wolfssl.VerifyMode.SSL_VERIFY_NONE)
191
+ wolfssl.wolfSSL_CTX_set_verify(ctx, VerifyMode.SSL_VERIFY_NONE)
191
192
  } else {
192
- wolfssl.wolfSSL_CTX_set_verify(ctx, wolfssl.VerifyMode.SSL_VERIFY_PEER)
193
+ wolfssl.wolfSSL_CTX_set_verify(ctx, VerifyMode.SSL_VERIFY_PEER)
193
194
  wolfssl.loadTrustedCerts(ctx)
194
195
  }
195
196
  ssl = wolfssl.wolfSSL_new(ctx)
196
197
  if (!ssl) { doReject(new Error('SSL_new failed')); return }
197
198
  wolfssl.wolfSSL_set_fd(ssl, sock.get_fd(fd))
198
199
  if (parsedUrl.hostname) {
199
- wolfssl.wolfSSL_UseSNI(ssl, wolfssl.SniType.WOLFSSL_SNI_HOST_NAME, parsedUrl.hostname)
200
+ wolfssl.wolfSSL_UseSNI(ssl, SniType.WOLFSSL_SNI_HOST_NAME, parsedUrl.hostname)
200
201
  if (req.rejectUnauthorized !== false) {
201
202
  wolfssl.wolfSSL_check_domain_name(ssl, parsedUrl.hostname)
202
203
  }
@@ -208,17 +209,17 @@ async function fetchRequest(req: RequestImpl): Promise<ResponseImpl> {
208
209
  }
209
210
  }
210
211
 
211
- if ((event.lNetworkEvents & sock.FdEvent.FD_READ) || (event.lNetworkEvents & sock.FdEvent.FD_WRITE)) {
212
+ if ((event.lNetworkEvents & FdEvent.FD_READ) || (event.lNetworkEvents & FdEvent.FD_WRITE)) {
212
213
  if (state === ST_HANDSHAKE) {
213
214
  if (!ssl) { doReject(new Error('TLS not initialized')); return }
214
215
  const ret = wolfssl.wolfSSL_connect(ssl)
215
- if (ret === wolfssl.ReturnCode.SSL_SUCCESS) {
216
+ if (ret === ReturnCode.SSL_SUCCESS) {
216
217
  wolfssl.wolfSSL_write(ssl, httpRequest)
217
218
  state = ST_RECV_HEADERS
218
219
  } else {
219
220
  const err = wolfssl.wolfSSL_get_error(ssl, ret)
220
- if (err !== wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_READ &&
221
- err !== wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_WRITE) {
221
+ if (err !== WolfsslErrorCode.WOLFSSL_ERROR_WANT_READ &&
222
+ err !== WolfsslErrorCode.WOLFSSL_ERROR_WANT_WRITE) {
222
223
  doReject(new Error('TLS handshake failed: ' + err))
223
224
  }
224
225
  }
@@ -234,9 +235,9 @@ async function fetchRequest(req: RequestImpl): Promise<ResponseImpl> {
234
235
  data = buf.slice(0, n)
235
236
  } else {
236
237
  const err = wolfssl.wolfSSL_get_error(ssl, n)
237
- if (err === wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_READ ||
238
- err === wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_WRITE) break
239
- if (n === 0 || err === wolfssl.ErrorCode.WOLFSSL_ERROR_ZERO_RETURN) break
238
+ if (err === WolfsslErrorCode.WOLFSSL_ERROR_WANT_READ ||
239
+ err === WolfsslErrorCode.WOLFSSL_ERROR_WANT_WRITE) break
240
+ if (n === 0 || err === WolfsslErrorCode.WOLFSSL_ERROR_ZERO_RETURN) break
240
241
  doReject(new Error('TLS read failed: ' + err))
241
242
  return
242
243
  }
@@ -315,9 +316,9 @@ async function fetchRequest(req: RequestImpl): Promise<ResponseImpl> {
315
316
  data = buf.slice(0, n)
316
317
  } else {
317
318
  const err = wolfssl.wolfSSL_get_error(ssl, n)
318
- if (err === wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_READ ||
319
- err === wolfssl.ErrorCode.WOLFSSL_ERROR_WANT_WRITE) break
320
- if (n === 0 || err === wolfssl.ErrorCode.WOLFSSL_ERROR_ZERO_RETURN) break
319
+ if (err === WolfsslErrorCode.WOLFSSL_ERROR_WANT_READ ||
320
+ err === WolfsslErrorCode.WOLFSSL_ERROR_WANT_WRITE) break
321
+ if (n === 0 || err === WolfsslErrorCode.WOLFSSL_ERROR_ZERO_RETURN) break
321
322
  // Fatal TLS error mid-body: the response already
322
323
  // resolved, so fail the body stream instead of
323
324
  // silently waiting for an FD event that never comes.
@@ -355,7 +356,7 @@ async function fetchRequest(req: RequestImpl): Promise<ResponseImpl> {
355
356
  }
356
357
  }
357
358
 
358
- if (event.lNetworkEvents & sock.FdEvent.FD_CLOSE) {
359
+ if (event.lNetworkEvents & FdEvent.FD_CLOSE) {
359
360
  if (state === ST_DONE) return
360
361
  if (state === ST_RECV_HEADERS) {
361
362
  doReject(new Error('Connection closed before response'))
package/lib/ffi/bind.js CHANGED
@@ -73,7 +73,7 @@ function makeFn(proc, sig, encoders, decoders) {
73
73
  }
74
74
  return (...a) => callPacked(proc, ps, a, encoders, decoders);
75
75
  }
76
- // 每个参数在 argFrame 里占的字节数。与 quickjs-ffi-type.h 的 qwin_ffi_arg_size[]
76
+ // 每个参数在 argFrame 里占的字节数。与 src/quickjs-ffi-type.h 的 qwin_ffi_arg_size[]
77
77
  // 保持一致(ia32:≤4B 类型进 4 字节、更大的进 8 字节;x64:恒 8 字节槽)。
78
78
  // 注意这是「槽宽」,不是类型的 sizeof——同一定义也用于返回槽。指针布局恒指针宽。
79
79
  const IA32_ARG_SIZE = {
@@ -334,7 +334,7 @@ const leakRegistry = new FinalizationRegistry((held) => {
334
334
  // args/ret 为「底档 + '!' 绑定」的记录(与 ParsedSig 同形态——修饰随 token 走,
335
335
  // 消费者要么整体拿到、要么整体拿不到)。'!' 违约(C 传入 0 / fn 返回 0)打印诊断并
336
336
  // 中止本次分发(fn 不被调用 / 结果槽保持 0),与 fn-throw 同风格:此处不 throw,
337
- // 异常通道只留给用户回调(C 桩捕获 wrapper 异常并清零,quickjs-ffi-closure.c)。
337
+ // 异常通道只留给用户回调(C 桩捕获 wrapper 异常并清零,src/quickjs-ffi-closure.c)。
338
338
  function dispatchClosure(args, ret, fn, frameBuf, retBuf, sig) {
339
339
  const dv = new DataView(retBuf);
340
340
  const is64 = os.arch === 'x64';
@@ -409,7 +409,7 @@ export function closure(sig, fn, opts) {
409
409
  const retSpec = { tok: cTokenToType(retToken), nonnull: retToken.endsWith('!') };
410
410
  const is64 = os.arch === 'x64';
411
411
  const stackCapture = argSpecs.reduce((s, x) => s + IA32_ARG_SIZE[x.tok], 0);
412
- // C 桩捕获窗定长(quickjs-ffi-closure.c:x64 栈区 96B=12 槽,第 5 参起在栈上,
412
+ // C 桩捕获窗定长(src/quickjs-ffi-closure.c:x64 栈区 96B=12 槽,第 5 参起在栈上,
413
413
  // 即至多 16 参;ia32 16×4B)——超限 dispatch 会读到捕获缓冲之外的垃圾,或
414
414
  // RangeError 被吞成返回 0,故创建期 fail-fast。扩容改 C 侧 buf 尺寸并同步放宽。
415
415
  if (is64 ? argSpecs.length > 16 : stackCapture > 64) {
package/lib/ffi/bind.ts CHANGED
@@ -123,7 +123,7 @@ function makeFn(proc: number, sig: string, encoders: CodecMap, decoders: CodecMa
123
123
  return (...a: unknown[]) => callPacked(proc, ps, a, encoders, decoders)
124
124
  }
125
125
 
126
- // 每个参数在 argFrame 里占的字节数。与 quickjs-ffi-type.h 的 qwin_ffi_arg_size[]
126
+ // 每个参数在 argFrame 里占的字节数。与 src/quickjs-ffi-type.h 的 qwin_ffi_arg_size[]
127
127
  // 保持一致(ia32:≤4B 类型进 4 字节、更大的进 8 字节;x64:恒 8 字节槽)。
128
128
  // 注意这是「槽宽」,不是类型的 sizeof——同一定义也用于返回槽。指针布局恒指针宽。
129
129
  const IA32_ARG_SIZE: Record<C_BasicType_No_Void, number> = {
@@ -429,7 +429,7 @@ const leakRegistry: FinalizationRegistry<{ sig: string, ptr: number }> =
429
429
  // args/ret 为「底档 + '!' 绑定」的记录(与 ParsedSig 同形态——修饰随 token 走,
430
430
  // 消费者要么整体拿到、要么整体拿不到)。'!' 违约(C 传入 0 / fn 返回 0)打印诊断并
431
431
  // 中止本次分发(fn 不被调用 / 结果槽保持 0),与 fn-throw 同风格:此处不 throw,
432
- // 异常通道只留给用户回调(C 桩捕获 wrapper 异常并清零,quickjs-ffi-closure.c)。
432
+ // 异常通道只留给用户回调(C 桩捕获 wrapper 异常并清零,src/quickjs-ffi-closure.c)。
433
433
  function dispatchClosure(
434
434
  args: { tok: C_BasicType_No_Void, nonnull: boolean }[],
435
435
  ret: { tok: C_BasicType, nonnull: boolean },
@@ -508,7 +508,7 @@ export function closure<S extends string>(sig: S, fn: BindFn<S, {}, {}>,
508
508
  const retSpec = { tok: cTokenToType(retToken), nonnull: retToken.endsWith('!') }
509
509
  const is64 = os.arch === 'x64'
510
510
  const stackCapture = argSpecs.reduce((s, x) => s + IA32_ARG_SIZE[x.tok], 0)
511
- // C 桩捕获窗定长(quickjs-ffi-closure.c:x64 栈区 96B=12 槽,第 5 参起在栈上,
511
+ // C 桩捕获窗定长(src/quickjs-ffi-closure.c:x64 栈区 96B=12 槽,第 5 参起在栈上,
512
512
  // 即至多 16 参;ia32 16×4B)——超限 dispatch 会读到捕获缓冲之外的垃圾,或
513
513
  // RangeError 被吞成返回 0,故创建期 fail-fast。扩容改 C 侧 buf 尺寸并同步放宽。
514
514
  if (is64 ? argSpecs.length > 16 : stackCapture > 64) {
package/lib/ffi/ctype.ts CHANGED
@@ -106,7 +106,9 @@ type First =
106
106
  // 对象值的唯一判别键是 '#'(多字段/聚合元素无法用糖表达,故保留)
107
107
  // '#' 必填(无「裸嵌套 map 默认 struct」):漏写 '#' 时 union 不会静默翻转成 struct,
108
108
  // 类型层直接报错、运行时 throw。顶层 struct()/union() 例外 —— kind 由函数名表明,
109
- // 参数是平铺字段表(不含 '#'),'#'/`#pack` 由构造器写入 __struct。
109
+ // 参数是平铺字段表(本身不含 '#';DECL 常量直传时 '#' 须与函数名 kind 一致 —— 参数
110
+ // 类型交叉 `{ '#'?: 'struct' }` / `{ '#'?: 'union' }` 编译期锁),'#'/`#pack` 由构造器
111
+ // 写入声明(buildDecl)。
110
112
  // ============================================================
111
113
 
112
114
  // token 值面:规范 token(C_Number 档)∪ 指针形(含 '!' 非空尾缀)∪ '@枚举标注形'
package/lib/ffi/struct.js CHANGED
@@ -350,7 +350,7 @@ function doEncode(dv, base, fields, v) {
350
350
  function createStruct(t) {
351
351
  const { fields, size, maxEffectiveAlign } = computeStructLayout(t);
352
352
  return {
353
- __struct: t,
353
+ fields,
354
354
  size,
355
355
  structAlign: maxEffectiveAlign,
356
356
  decode: (p) => {
@@ -389,10 +389,26 @@ function createStruct(t) {
389
389
  },
390
390
  };
391
391
  }
392
- /** 平铺字段表 → '#' 声明:'#'/`#pack` 由构造器写入(顶层 kind 由函数名表明,字段表本身
393
- * 不收指令键)。member 里混进的 '#' 前缀键在此剔除 —— 类型层已禁(fresh literal excess
394
- * check),这里运行时兜底,避免用户键覆盖构造器写入的 '#'/`#pack`。 */
392
+ /** 平铺字段表 → '#' 声明:'#'/`#pack` 由构造器写入(顶层 kind 由函数名表明)。
393
+ * member 里混进的其他 '#' 前缀键在此剔除 —— fresh literal 由 excess check 拒,这里
394
+ * 运行时兜底,避免用户键覆盖构造器写入的 '#'/`#pack`。
395
+ * 两处守卫(DECL 常量直传形态,`struct('X', X_DECL)`):
396
+ * - member 自带 '#' 时须与函数名 kind 一致,否则 throw。TS 侧 overload 参数收
397
+ * `M & { '#'?: 'struct' }`(union 镜像),'#' 与函数名 kind 不符在编译期就交叉成
398
+ * never 报错;此 throw 是 JS / `as any` / 动态构造 DECL 调用方的运行时兜底 ——
399
+ * union DECL 误传 struct() 会静默翻转成 struct 布局,是最难查的一类错;
400
+ * - '#pack' 透传(剥键即丢,pack 布局静默变自然对齐):opts.pack 未给时取 member 的,
401
+ * 两者都给且不等则 throw —— 跨参数的相等约束类型层表达不了,只能运行时校。 */
395
402
  function buildDecl(kind, member, pack) {
403
+ const declKind = member['#'];
404
+ if (declKind !== undefined && declKind !== kind)
405
+ throw new Error(`ffi-struct: ${kind}() received a '${String(declKind)}' declaration ` +
406
+ `(kind mismatch — use ${declKind}() for it)`);
407
+ const declPack = member['#pack'];
408
+ if (pack === undefined && declPack !== undefined)
409
+ pack = declPack;
410
+ else if (pack !== undefined && declPack !== undefined && pack !== declPack)
411
+ throw new Error(`ffi-struct: #pack conflict: opts.pack=${pack} vs declaration ${String(declPack)}`);
396
412
  const decl = { '#': kind };
397
413
  if (pack !== undefined)
398
414
  decl['#pack'] = pack;
@@ -418,10 +434,10 @@ function buildDecl(kind, member, pack) {
418
434
  * - 裸地址形:count 必填(地址无长度信息),逐字节拷读(def.decode 的 number 形
419
435
  * 同机制);长度不可校 → 信任 C 的 count。
420
436
  * - count = 0 → [](读 0 个真空安全,与 encode 禁空的 PAB(0) 理由刻意不对称)。
421
- * 实现:encode 走纯公开 API(alloc + encode offset 循环);decode 在本文件内复用
422
- * computeStructLayout/doDecode。 */
437
+ * 实现:encode 走纯公开 API(alloc + encode offset 循环);decode 直接读 def.fields
438
+ * (createStruct 暴露的布局 IR,与 def.decode 同一份,无需重算)。 */
423
439
  export function structArray(def) {
424
- const { fields, size } = computeStructLayout(def.__struct);
440
+ const { fields, size } = def;
425
441
  const readN = (dv, n) => {
426
442
  const out = [];
427
443
  for (let i = 0; i < n; i++)
package/lib/ffi/struct.ts CHANGED
@@ -204,7 +204,10 @@ export type Fields = Field[]
204
204
  // N = 布局品牌(struct(name, …) 传入):decode 入参与 alloc().ptr 同品牌。默认 '' ——
205
205
  // `Ptr<''>` 归一裸 number(与旧 never 守卫结果相同),品牌化 def 未来收窄时签名不用再动。
206
206
  export type StructDef<T extends { '#': 'struct' | 'union' }, N extends string = ''> = {
207
- readonly __struct: T
207
+ // 布局 IR 直接暴露(原 __struct 成员读已删:成员读是可观察副作用,esbuild 无法把
208
+ // 「PURE 调用 + X.__struct 实参」与 X 的定义一起摇掉 —— DECL 常量(对象字面量)走
209
+ // 标识符引用则整链可摇。T 只活在 decode/encode 的类型签名里,运行时不挂成员)。
210
+ readonly fields: Fields
208
211
  readonly size: number
209
212
  readonly structAlign: number
210
213
  decode(buf: ArrayBuffer | Ptr<N>): ShapeOfC<T>
@@ -593,7 +596,7 @@ function doEncode(dv: DataView, base: number, fields: Fields, v: Record<string,
593
596
  function createStruct(t: C_Struct | C_Union): any {
594
597
  const { fields, size, maxEffectiveAlign } = computeStructLayout(t)
595
598
  return {
596
- __struct: t,
599
+ fields,
597
600
  size,
598
601
  structAlign: maxEffectiveAlign,
599
602
  decode: (p: ArrayBuffer | number) => {
@@ -638,10 +641,25 @@ function createStruct(t: C_Struct | C_Union): any {
638
641
  /** 聚合对齐上限(pack 压 maxAlign,语义同 MSVC #pragma pack)。 */
639
642
  export type AggOpts = { pack?: number }
640
643
 
641
- /** 平铺字段表 → '#' 声明:'#'/`#pack` 由构造器写入(顶层 kind 由函数名表明,字段表本身
642
- * 不收指令键)。member 里混进的 '#' 前缀键在此剔除 —— 类型层已禁(fresh literal excess
643
- * check),这里运行时兜底,避免用户键覆盖构造器写入的 '#'/`#pack`。 */
644
+ /** 平铺字段表 → '#' 声明:'#'/`#pack` 由构造器写入(顶层 kind 由函数名表明)。
645
+ * member 里混进的其他 '#' 前缀键在此剔除 —— fresh literal 由 excess check 拒,这里
646
+ * 运行时兜底,避免用户键覆盖构造器写入的 '#'/`#pack`。
647
+ * 两处守卫(DECL 常量直传形态,`struct('X', X_DECL)`):
648
+ * - member 自带 '#' 时须与函数名 kind 一致,否则 throw。TS 侧 overload 参数收
649
+ * `M & { '#'?: 'struct' }`(union 镜像),'#' 与函数名 kind 不符在编译期就交叉成
650
+ * never 报错;此 throw 是 JS / `as any` / 动态构造 DECL 调用方的运行时兜底 ——
651
+ * union DECL 误传 struct() 会静默翻转成 struct 布局,是最难查的一类错;
652
+ * - '#pack' 透传(剥键即丢,pack 布局静默变自然对齐):opts.pack 未给时取 member 的,
653
+ * 两者都给且不等则 throw —— 跨参数的相等约束类型层表达不了,只能运行时校。 */
644
654
  function buildDecl(kind: 'struct' | 'union', member: Record<string, unknown>, pack?: number): C_Struct | C_Union {
655
+ const declKind = member['#']
656
+ if (declKind !== undefined && declKind !== kind)
657
+ throw new Error(`ffi-struct: ${kind}() received a '${String(declKind)}' declaration ` +
658
+ `(kind mismatch — use ${declKind}() for it)`)
659
+ const declPack = member['#pack']
660
+ if (pack === undefined && declPack !== undefined) pack = declPack as number
661
+ else if (pack !== undefined && declPack !== undefined && pack !== declPack)
662
+ throw new Error(`ffi-struct: #pack conflict: opts.pack=${pack} vs declaration ${String(declPack)}`)
645
663
  const decl: Record<string, unknown> = { '#': kind }
646
664
  if (pack !== undefined) decl['#pack'] = pack
647
665
  for (const [k, v] of Object.entries(member))
@@ -649,11 +667,19 @@ function buildDecl(kind: 'struct' | 'union', member: Record<string, unknown>, pa
649
667
  return decl as unknown as C_Struct | C_Union
650
668
  }
651
669
 
670
+ /** def 的类型经方法签名索引提取(StructDef 不再挂 __struct 成员 —— T 只活在签名里):
671
+ * encode 重载末条首参 = EncodeIn<T>、decode 返回 = ShapeOfC<T>、alloc 返回 = PAB<N>、
672
+ * decode 首参剥 ArrayBuffer = Ptr<N>(裸地址形)。 */
673
+ type EncInOf<D extends StructDef<any, any>> = Parameters<D['encode']>[0]
674
+ type DecOf<D extends StructDef<any, any>> = ReturnType<D['decode']>
675
+ type PABOf<D extends StructDef<any, any>> = ReturnType<D['alloc']>
676
+ type AddrOf<D extends StructDef<any, any>> = Exclude<Parameters<D['decode']>[0], ArrayBuffer>
677
+
652
678
  /** decode 双态重载:有 byteLength 的 buffer 形 count 可缺省(自算);裸地址无长度
653
679
  * 信息,count 必填(类型层拦,缺省调用编译红)。 */
654
- type StructArrayDecode<T extends { '#': 'struct' | 'union' }, N extends string> = {
655
- (p: ArrayBuffer, count?: number): ShapeOfC<T>[]
656
- (p: Ptr<N>, count: number): ShapeOfC<T>[]
680
+ type StructArrayDecode<D extends StructDef<any, any>> = {
681
+ (p: ArrayBuffer, count?: number): DecOf<D>[]
682
+ (p: AddrOf<D>, count: number): DecOf<D>[]
657
683
  }
658
684
 
659
685
  /** 结构/联合体的数组编解码对工厂:返回 `{ encode, decode }`。
@@ -673,25 +699,23 @@ type StructArrayDecode<T extends { '#': 'struct' | 'union' }, N extends string>
673
699
  * - 裸地址形:count 必填(地址无长度信息),逐字节拷读(def.decode 的 number 形
674
700
  * 同机制);长度不可校 → 信任 C 的 count。
675
701
  * - count = 0 → [](读 0 个真空安全,与 encode 禁空的 PAB(0) 理由刻意不对称)。
676
- * 实现:encode 走纯公开 API(alloc + encode offset 循环);decode 在本文件内复用
677
- * computeStructLayout/doDecode。 */
678
- export function structArray<T extends { '#': 'struct' | 'union' }, N extends string = ''>(
679
- def: StructDef<T, N>,
680
- ) {
681
- const { fields, size } = computeStructLayout(def.__struct)
702
+ * 实现:encode 走纯公开 API(alloc + encode offset 循环);decode 直接读 def.fields
703
+ * (createStruct 暴露的布局 IR,与 def.decode 同一份,无需重算)。 */
704
+ export function structArray<D extends StructDef<any, any>>(def: D) {
705
+ const { fields, size } = def
682
706
  const readN = (dv: DataView, n: number): unknown[] => {
683
707
  const out: unknown[] = []
684
708
  for (let i = 0; i < n; i++) out.push(doDecode(dv, i * size, fields))
685
709
  return out
686
710
  }
687
711
  return {
688
- encode: (els: readonly EncodeIn<T>[]): PtrArrayBuffer<N> => {
712
+ encode: (els: readonly EncInOf<D>[]): PABOf<D> => {
689
713
  if (!Array.isArray(els) || els.length === 0)
690
714
  throw new Error(`ffi-struct: structArray(def).encode(els) requires a ` +
691
715
  `non-empty element array (pass NULL for an empty pointer position)`)
692
716
  const out = def.alloc(els.length)
693
717
  for (let i = 0; i < els.length; i++) def.encode(els[i], out, i * def.size)
694
- return out
718
+ return out as PABOf<D>
695
719
  },
696
720
  decode: ((p: ArrayBuffer | number, count?: number): unknown[] => {
697
721
  // fail-loud 校验矩阵(见 JSDoc):显式 count 信调用方但拦越界;缺省只对
@@ -725,16 +749,18 @@ export function structArray<T extends { '#': 'struct' | 'union' }, N extends str
725
749
  }
726
750
  if (n === 0) return []
727
751
  return readN(new DataView(p), n)
728
- }) as StructArrayDecode<T, N>,
752
+ }) as StructArrayDecode<D>,
729
753
  }
730
754
  }
731
755
 
732
756
  /** 平铺字段表定义结构体(token/`X[n]`/`unit:width`/`'#'` 声明均可,见 ctype.ts §4)。
733
- * 给 name 则 alloc().ptr 与 decode 入参带 Ptr<name> 品牌。 */
757
+ * 给 name 则 alloc().ptr 与 decode 入参带 Ptr<name> 品牌。DECL 常量可直传(
758
+ * `struct('X', X_DECL)`)—— 参数交叉 `{ '#'?: 'struct' }` 锁 kind:传 union/array
759
+ * DECL 时 '#' 字面类型交叉成 never,编译期即报错。 */
734
760
  type StructOf<M, N extends string = ''> = StructDef<{ '#': 'struct', '#pack'?: number } & M, N>
735
761
  type UnionOf<M, N extends string = ''> = StructDef<{ '#': 'union', '#pack'?: number } & M, N>
736
- export function struct<const M extends SimpleMember>(member: M, opts?: AggOpts): StructOf<M>
737
- export function struct<const N extends string, const M extends SimpleMember>(name: N, member: M, opts?: AggOpts): StructOf<M, N>
762
+ export function struct<const M extends SimpleMember>(member: M & { '#'?: 'struct' }, opts?: AggOpts): StructOf<M>
763
+ export function struct<const N extends string, const M extends SimpleMember>(name: N, member: M & { '#'?: 'struct' }, opts?: AggOpts): StructOf<M, N>
738
764
  export function struct(a: string | SimpleMember, b?: SimpleMember | AggOpts, c?: AggOpts): any {
739
765
  const isNamed = typeof a === 'string'
740
766
  const raw = (isNamed ? b : a) as Record<string, unknown>
@@ -742,9 +768,10 @@ export function struct(a: string | SimpleMember, b?: SimpleMember | AggOpts, c?:
742
768
  return createStruct(buildDecl('struct', raw, opts?.pack))
743
769
  }
744
770
 
745
- /** 平铺字段表定义联合体;布局/读写与 struct 相同,仅成员偏移重叠。 */
746
- export function union<const M extends SimpleMember>(member: M, opts?: AggOpts): UnionOf<M>
747
- export function union<const N extends string, const M extends SimpleMember>(name: N, member: M, opts?: AggOpts): UnionOf<M, N>
771
+ /** 平铺字段表定义联合体;布局/读写与 struct 相同,仅成员偏移重叠。DECL 常量可直传,
772
+ * 参数交叉 `{ '#'?: 'union' }` 锁 kind(struct 侧镜像,理由见上)。 */
773
+ export function union<const M extends SimpleMember>(member: M & { '#'?: 'union' }, opts?: AggOpts): UnionOf<M>
774
+ export function union<const N extends string, const M extends SimpleMember>(name: N, member: M & { '#'?: 'union' }, opts?: AggOpts): UnionOf<M, N>
748
775
  export function union(a: string | SimpleMember, b?: SimpleMember | AggOpts, c?: AggOpts): any {
749
776
  const isNamed = typeof a === 'string'
750
777
  const raw = (isNamed ? b : a) as Record<string, unknown>
@@ -163,7 +163,7 @@ export class HttpServer {
163
163
  }
164
164
  this.serverSock = s;
165
165
  sock.set_on_event(s, (event) => {
166
- if (event.lNetworkEvents & 8 /* sock.FdEvent.FD_ACCEPT */)
166
+ if (event.lNetworkEvents & 8 /* FdEvent.FD_ACCEPT */)
167
167
  this.acceptLoop();
168
168
  });
169
169
  return 0;
@@ -207,11 +207,11 @@ export class HttpServer {
207
207
  onConnEvent(c, event) {
208
208
  if (c.closed)
209
209
  return;
210
- if (event.lNetworkEvents & 1 /* sock.FdEvent.FD_READ */)
210
+ if (event.lNetworkEvents & 1 /* FdEvent.FD_READ */)
211
211
  onRead(c);
212
- if (event.lNetworkEvents & 2 /* sock.FdEvent.FD_WRITE */)
212
+ if (event.lNetworkEvents & 2 /* FdEvent.FD_WRITE */)
213
213
  flushQueue(c);
214
- if (event.lNetworkEvents & 32 /* sock.FdEvent.FD_CLOSE */) {
214
+ if (event.lNetworkEvents & 32 /* FdEvent.FD_CLOSE */) {
215
215
  onRead(c);
216
216
  abortConn(c);
217
217
  closeConn(c);
@@ -342,7 +342,7 @@ async function writeStreamingBody(c, body, chunked, trailer) {
342
342
  }
343
343
  if (c.closed) {
344
344
  // 客户端断开(FD_CLOSE / send 失败):取消响应体,让 producer 感知
345
- //(exec_server 借此 kill 子进程),而不是干等它自然结束。
345
+ //(execd 借此 kill 子进程),而不是干等它自然结束。
346
346
  try {
347
347
  await reader.cancel();
348
348
  }
@@ -2,6 +2,7 @@ import './polyfill.js'
2
2
  import * as sock from 'sock'
3
3
  import { HeadersImpl, RequestImpl, ResponseImpl, _readStream } from './http-common.js'
4
4
  import { AbortController } from './abort.js'
5
+ import { FdEvent } from '../constants'
5
6
 
6
7
  type SockHandle = import('sock').SockHandle
7
8
 
@@ -191,7 +192,7 @@ export class HttpServer {
191
192
  if (sock.listen(s, backlog ?? 64) !== 0) { sock.closesocket(s); return -1 }
192
193
  this.serverSock = s
193
194
  sock.set_on_event(s, (event: NetEvent) => {
194
- if (event.lNetworkEvents & sock.FdEvent.FD_ACCEPT) this.acceptLoop()
195
+ if (event.lNetworkEvents & FdEvent.FD_ACCEPT) this.acceptLoop()
195
196
  })
196
197
  return 0
197
198
  }
@@ -229,9 +230,9 @@ export class HttpServer {
229
230
 
230
231
  private onConnEvent(c: Conn, event: NetEvent): void {
231
232
  if (c.closed) return
232
- if (event.lNetworkEvents & sock.FdEvent.FD_READ) onRead(c)
233
- if (event.lNetworkEvents & sock.FdEvent.FD_WRITE) flushQueue(c)
234
- if (event.lNetworkEvents & sock.FdEvent.FD_CLOSE) {
233
+ if (event.lNetworkEvents & FdEvent.FD_READ) onRead(c)
234
+ if (event.lNetworkEvents & FdEvent.FD_WRITE) flushQueue(c)
235
+ if (event.lNetworkEvents & FdEvent.FD_CLOSE) {
235
236
  onRead(c)
236
237
  abortConn(c)
237
238
  closeConn(c)
@@ -357,7 +358,7 @@ async function writeStreamingBody(c: Conn, body: ReadableStream<Uint8Array> | nu
357
358
  }
358
359
  if (c.closed) {
359
360
  // 客户端断开(FD_CLOSE / send 失败):取消响应体,让 producer 感知
360
- //(exec_server 借此 kill 子进程),而不是干等它自然结束。
361
+ //(execd 借此 kill 子进程),而不是干等它自然结束。
361
362
  try { await reader.cancel() } catch (e) {
362
363
  console.error('[http-server] body cancel error:', e)
363
364
  }