quickwin 2.1.0 → 2.2.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 (45) hide show
  1. package/README.en.md +8 -8
  2. package/README.md +6 -7
  3. package/examples/{exec_server.js → execd.js} +618 -228
  4. package/examples/execd.tsx +798 -0
  5. package/examples/execd_worker.js +122 -0
  6. package/examples/execd_worker.ts +127 -0
  7. package/examples/pdf_viewer.js +100 -111
  8. package/examples/test_gallery.js +100 -111
  9. package/examples/test_react_lazy.js +96 -109
  10. package/examples/test_react_listbox.js +96 -109
  11. package/examples/test_root_window.js +96 -109
  12. package/examples/test_tab.js +96 -109
  13. package/lib/ffi/ctype.ts +3 -1
  14. package/lib/ffi/struct.js +23 -7
  15. package/lib/ffi/struct.ts +50 -23
  16. package/lib/http-server.js +1 -1
  17. package/lib/http-server.ts +1 -1
  18. package/lib/windows/gdi32.js +1 -1
  19. package/lib/windows/gdi32.ts +1 -1
  20. package/lib/windows/structs.js +176 -92
  21. package/lib/windows/structs.ts +216 -92
  22. package/package.json +1 -1
  23. package/quickwin_const.d.ts +26 -0
  24. package/qwin-nowasm-x86.exe +0 -0
  25. package/qwin-nowasm.exe +0 -0
  26. package/qwin-x86.exe +0 -0
  27. package/qwin.exe +0 -0
  28. package/test/test_ffi_bind.js +5 -3
  29. package/test/test_ffi_bind.ts +6 -4
  30. package/test/test_ffi_struct.js +58 -24
  31. package/test/test_ffi_struct.ts +55 -25
  32. package/test/test_gdi_draw.js +1 -1
  33. package/test/test_gdi_draw.ts +1 -1
  34. package/test/test_react_complex.js +96 -109
  35. package/test/test_react_counter.js +96 -109
  36. package/test/test_react_flex.js +96 -109
  37. package/test/test_react_hidden.js +96 -109
  38. package/test/test_react_listview_link.js +96 -109
  39. package/test/test_react_notify.js +96 -109
  40. package/test/test_react_render.js +96 -109
  41. package/examples/exec_server.tsx +0 -489
  42. package/examples/exec_server_worker.js +0 -395
  43. package/examples/exec_server_worker.ts +0 -417
  44. package/examples/setres.js +0 -79
  45. package/examples/setres.ts +0 -86
@@ -854,6 +854,32 @@ declare module "gui" {
854
854
  BITSPIXEL = 12, // 0xC
855
855
  }
856
856
 
857
+ // Display mode (ChangeDisplaySettings)
858
+ export const enum DevModeField {
859
+ PELSWIDTH = 524288, // 0x80000
860
+ PELSHEIGHT = 1048576, // 0x100000
861
+ }
862
+
863
+ export const enum ChangeDisplayFlag {
864
+ UPDATEREGISTRY = 1, // 0x1
865
+ TEST = 2, // 0x2
866
+ }
867
+
868
+ export const enum EnumDisplaySetting {
869
+ CURRENT_SETTINGS = -1, // 0xFFFFFFFF
870
+ }
871
+
872
+ export const enum DisplayChangeResult {
873
+ SUCCESSFUL = 0, // 0x0
874
+ RESTART = 1, // 0x1
875
+ FAILED = -1, // 0xFFFFFFFF
876
+ BADMODE = -2, // 0xFFFFFFFE
877
+ NOTUPDATED = -3, // 0xFFFFFFFD
878
+ BADFLAGS = -4, // 0xFFFFFFFC
879
+ BADPARAM = -5, // 0xFFFFFFFB
880
+ BADDUALVIEW = -6, // 0xFFFFFFFA
881
+ }
882
+
857
883
  // Static controls
858
884
  export const enum StaticMsg {
859
885
  SETICON = 368, // 0x170
Binary file
package/qwin-nowasm.exe CHANGED
Binary file
package/qwin-x86.exe CHANGED
Binary file
package/qwin.exe CHANGED
Binary file
@@ -238,13 +238,15 @@ export const suite = {
238
238
  if (brushL)
239
239
  t.checkTrue('bindLib DeleteObject succeeds', gdi32Lib.DeleteObject(brushL) !== 0);
240
240
  // 嵌套 struct(LOGPEN 内含 POINT)验证 ShapeOf 递归 + 子结构写入
241
- const POINT = struct('POINT', {
241
+ const POINT_DECL = {
242
+ '#': 'struct',
242
243
  x: 'i32',
243
244
  y: 'i32',
244
- });
245
+ };
246
+ const POINT = /* @__PURE__ */ struct('POINT', POINT_DECL);
245
247
  const LOGPEN = struct('LOGPEN', {
246
248
  lopnStyle: 'u32',
247
- lopnWidth: POINT.__struct,
249
+ lopnWidth: POINT_DECL,
248
250
  lopnColor: 'u32',
249
251
  });
250
252
  const createPenIndirect = bind('gdi32.dll', 'CreatePenIndirect', '<LOGPEN>ptr -> <>ptr', { LOGPEN });
@@ -5,7 +5,7 @@ import * as os from 'os'
5
5
  import { Tester } from './test_helper.js'
6
6
  import { bind, bindLib, closure, WCHAR, BYTE, type CodecMap } from '../lib/ffi/bind.js'
7
7
  import { struct } from '../lib/ffi/struct.js'
8
- import { NULL, type MaybePtr, Ptr, PtrArrayBuffer, readScalar, writeScalar, PTR_SIZE, normToken } from '../lib/ffi/ctype.js'
8
+ import { NULL, type C_Struct, type MaybePtr, Ptr, PtrArrayBuffer, readScalar, writeScalar, PTR_SIZE, normToken } from '../lib/ffi/ctype.js'
9
9
 
10
10
  // 编译期断言工具(仅类型层,运行时无开销)
11
11
  type Equal<A, B> = (<G>() => G extends A ? 1 : 2) extends (<G>() => G extends B ? 1 : 2) ? true : false
@@ -238,13 +238,15 @@ export const suite = {
238
238
  if (brushL) t.checkTrue('bindLib DeleteObject succeeds', gdi32Lib.DeleteObject(brushL) !== 0)
239
239
 
240
240
  // 嵌套 struct(LOGPEN 内含 POINT)验证 ShapeOf 递归 + 子结构写入
241
- const POINT = struct('POINT', {
241
+ const POINT_DECL = {
242
+ '#': 'struct',
242
243
  x: 'i32',
243
244
  y: 'i32',
244
- })
245
+ } satisfies C_Struct
246
+ const POINT = /* @__PURE__ */ struct('POINT', POINT_DECL)
245
247
  const LOGPEN = struct('LOGPEN', {
246
248
  lopnStyle: 'u32',
247
- lopnWidth: POINT.__struct,
249
+ lopnWidth: POINT_DECL,
248
250
  lopnColor: 'u32',
249
251
  })
250
252
  const createPenIndirect = bind('gdi32.dll', 'CreatePenIndirect', '<LOGPEN>ptr -> <>ptr', { LOGPEN })
@@ -13,7 +13,8 @@ const RECT = /* @__PURE__ */ struct('RECT', {
13
13
  right: 'i32',
14
14
  bottom: 'i32',
15
15
  });
16
- const TVITEM = /* @__PURE__ */ struct('TVITEM', {
16
+ const TVITEM_DECL = {
17
+ '#': 'struct',
17
18
  mask: 'u32',
18
19
  hItem: '<>ptr',
19
20
  state: 'u32',
@@ -24,11 +25,12 @@ const TVITEM = /* @__PURE__ */ struct('TVITEM', {
24
25
  iSelectedImage: 'i32',
25
26
  cChildren: 'i32',
26
27
  lParam: '<>ptr',
27
- });
28
+ };
29
+ const TVITEM = /* @__PURE__ */ struct('TVITEM', TVITEM_DECL);
28
30
  const TVINSERTSTRUCT = /* @__PURE__ */ struct('TVINSERTSTRUCT', {
29
31
  hParent: '<>ptr',
30
32
  hInsertAfter: '<>ptr',
31
- item: TVITEM.__struct,
33
+ item: TVITEM_DECL,
32
34
  });
33
35
  export const suite = {
34
36
  name: 'ffi-struct',
@@ -228,13 +230,15 @@ export const suite = {
228
230
  t.check('length 1', 1, one.v.length);
229
231
  t.check('[0]', 42, one.v[0]);
230
232
  t.section('array of struct roundtrip (stride = child size)');
231
- const PT = struct('PT', {
233
+ const PT_DECL = {
234
+ '#': 'struct',
232
235
  x: 'i32',
233
236
  y: 'i32',
234
- });
237
+ };
238
+ const PT = /* @__PURE__ */ struct('PT', PT_DECL);
235
239
  const POLY = struct('POLY', {
236
240
  count: 'u32',
237
- pts: { '#': 'array', element: PT.__struct, length: 3 },
241
+ pts: { '#': 'array', element: PT_DECL, length: 3 },
238
242
  });
239
243
  t.check('POLY.size == 28', 28, POLY.size);
240
244
  t.check('POLY.offsetOf pts', 4, POLY.offsetOf('pts'));
@@ -274,9 +278,28 @@ export const suite = {
274
278
  rejectedMap = true;
275
279
  }
276
280
  t.check('bare nested map rejected(漏写 #)', true, rejectedMap);
277
- // 顶层 '#' 由构造器写入:字段表混入的 '#' 指令键被剔除(运行时兜底,类型层已禁)
278
- const H = struct({ '#': 'union', a: 'u8', b: 'u32' });
279
- t.check('top-level # stripped(仍按函数名 struct 布局)', 8, H.size);
281
+ // 顶层 '#' 与函数名 kind 不符 → throw(union DECL 误传 struct() 防线);
282
+ // 一致('#': 'struct' 的 DECL 直传形态)→ 按 kind 正常布局
283
+ let rejectedKind = false;
284
+ try {
285
+ struct({ '#': 'union', a: 'u8', b: 'u32' });
286
+ }
287
+ catch {
288
+ rejectedKind = true;
289
+ }
290
+ t.check('top-level # kind mismatch rejected', true, rejectedKind);
291
+ const H = struct('H', { '#': 'struct', a: 'u8', b: 'u32' });
292
+ t.check('top-level # matching kind accepted(DECL 直传)', 8, H.size);
293
+ // 类型层 kind 锁(参数交叉 `{ '#'?: 'struct' }` / `{ '#'?: 'union' }`):DECL 的
294
+ // '#' 字面与函数名 kind 不符 → 交叉 never,编译期报错。@ts-expect-error 断言该
295
+ // 报错存在(锁失效则指令未使用、tsc 报错);仅类型期检查,函数不调用
296
+ const _kindLock = () => {
297
+ // @ts-expect-error —— union DECL 传 struct()
298
+ struct('BAD_U', { '#': 'union', a: 'u8', b: 'u32' });
299
+ // @ts-expect-error —— struct DECL 传 union()
300
+ union('BAD_S', { '#': 'struct', a: 'u8', b: 'u32' });
301
+ };
302
+ void _kindLock;
280
303
  t.section("pointer member '<>ptr' raw vs '<T>ptr' branded");
281
304
  const PTR = struct('PTR', {
282
305
  raw: '<>ptr',
@@ -376,16 +399,18 @@ export const suite = {
376
399
  t.check('BROWSEINFOW.offsetOf lpszTitle', is64 ? 24 : 12, BROWSEINFOW.offsetOf('lpszTitle'));
377
400
  t.check('BROWSEINFOW.offsetOf ulFlags', is64 ? 32 : 16, BROWSEINFOW.offsetOf('ulFlags'));
378
401
  t.section('NMHDR(嵌套时 MSVC 尾 padding 传染)');
379
- const NMHDR = struct('NMHDR', {
402
+ const NMHDR_DECL = {
403
+ '#': 'struct',
380
404
  hwndFrom: '<>ptr',
381
405
  idFrom: '<>ptr',
382
406
  code: 'i32',
383
- });
407
+ };
408
+ const NMHDR = /* @__PURE__ */ struct('NMHDR', NMHDR_DECL);
384
409
  t.check('NMHDR.size', is64 ? 24 : 12, NMHDR.size);
385
410
  t.check('NMHDR.offsetOf code', is64 ? 16 : 8, NMHDR.offsetOf('code'));
386
411
  t.section('NMCUSTOMDRAW / NMLVCUSTOMDRAW (ListView custom draw)');
387
412
  const NMCUSTOMDRAW = struct('NMCUSTOMDRAW', {
388
- hdr: NMHDR.__struct,
413
+ hdr: NMHDR_DECL,
389
414
  dwDrawStage: 'u32',
390
415
  hdc: '<>ptr',
391
416
  rc: 'i32[4]',
@@ -398,7 +423,7 @@ export const suite = {
398
423
  t.check('NMCUSTOMDRAW.offsetOf hdc', is64 ? 32 : 16, NMCUSTOMDRAW.offsetOf('hdc'));
399
424
  t.check('NMCUSTOMDRAW.offsetOf dwItemSpec', is64 ? 56 : 36, NMCUSTOMDRAW.offsetOf('dwItemSpec'));
400
425
  const NMLVCUSTOMDRAW = struct('NMLVCUSTOMDRAW', {
401
- hdr: NMHDR.__struct,
426
+ hdr: NMHDR_DECL,
402
427
  dwDrawStage: 'u32',
403
428
  hdc: '<>ptr',
404
429
  rc: 'i32[4]',
@@ -416,7 +441,7 @@ export const suite = {
416
441
  t.check('NMLVCUSTOMDRAW.offsetOf iSubItem', is64 ? 88 : 56, NMLVCUSTOMDRAW.offsetOf('iSubItem'));
417
442
  t.section('NMLISTVIEW / NMITEMACTIVATE');
418
443
  const NMLISTVIEW = struct('NMLISTVIEW', {
419
- hdr: NMHDR.__struct,
444
+ hdr: NMHDR_DECL,
420
445
  iItem: 'i32',
421
446
  iSubItem: 'i32',
422
447
  uNewState: 'u32',
@@ -471,7 +496,8 @@ export const suite = {
471
496
  t.check('LVCOLUMNW.offsetOf iSubItem', is64 ? 28 : 20, LVCOLUMNW.offsetOf('iSubItem'));
472
497
  t.check('LVCOLUMNW.offsetOf iOrder', is64 ? 36 : 28, LVCOLUMNW.offsetOf('iOrder'));
473
498
  t.section('NMDATETIMECHANGE');
474
- const SYSTEMTIME = struct('SYSTEMTIME', {
499
+ const SYSTEMTIME_DECL = {
500
+ '#': 'struct',
475
501
  wYear: 'u16',
476
502
  wMonth: 'u16',
477
503
  wDayOfWeek: 'u16',
@@ -480,26 +506,28 @@ export const suite = {
480
506
  wMinute: 'u16',
481
507
  wSecond: 'u16',
482
508
  wMilliseconds: 'u16',
483
- });
509
+ };
484
510
  const NMDATETIMECHANGE = struct('NMDATETIMECHANGE', {
485
- hdr: NMHDR.__struct,
511
+ hdr: NMHDR_DECL,
486
512
  dwFlags: 'u32',
487
- st: SYSTEMTIME.__struct,
513
+ st: SYSTEMTIME_DECL,
488
514
  });
489
515
  t.check('NMDATETIMECHANGE.size', is64 ? 48 : 32, NMDATETIMECHANGE.size);
490
516
  t.check('NMDATETIMECHANGE.offsetOf dwFlags', is64 ? 24 : 12, NMDATETIMECHANGE.offsetOf('dwFlags'));
491
517
  t.check('NMDATETIMECHANGE.offsetOf st', is64 ? 28 : 16, NMDATETIMECHANGE.offsetOf('st'));
492
518
  t.section('NMLINK szUrl offset');
493
- const LITEM = struct('LITEM', {
519
+ const LITEM_DECL = {
520
+ '#': 'struct',
494
521
  mask: 'u32',
495
522
  iLink: 'i32',
496
523
  state: 'u32',
497
524
  stateMask: 'u32',
498
525
  szID: 'u16[48]@utf-16le',
499
- });
526
+ };
527
+ const LITEM = /* @__PURE__ */ struct('LITEM', LITEM_DECL);
500
528
  const NMLINK = struct('NMLINK', {
501
- hdr: NMHDR.__struct,
502
- item: LITEM.__struct,
529
+ hdr: NMHDR_DECL,
530
+ item: LITEM_DECL,
503
531
  szUrl: 'u16[2084]@utf-16le',
504
532
  });
505
533
  t.check('LITEM.offsetOf szID', 16, LITEM.offsetOf('szID'));
@@ -715,8 +743,14 @@ export const suite = {
715
743
  t.section('EncodeIn DFS 后序:子树含必填 ⇒ 键必填;值后序合成(非必填兄弟可省)');
716
744
  {
717
745
  // 嵌套子结构含 '!'(内层强制)+ 标量/字符串糖(内层可省:''/0 是合法零值)
718
- const NSUB = struct('NSUB', { hp: '<X>ptr!', rest: 'u32', s: 'u16[4]@utf-8' });
719
- const NOUT = struct('NOUT', { top: 'u32', sub: NSUB.__struct });
746
+ const NSUB_DECL = {
747
+ '#': 'struct',
748
+ hp: '<X>ptr!',
749
+ rest: 'u32',
750
+ s: 'u16[4]@utf-8',
751
+ };
752
+ const NSUB = /* @__PURE__ */ struct('NSUB', NSUB_DECL);
753
+ const NOUT = struct('NOUT', { top: 'u32', sub: NSUB_DECL });
720
754
  // decode 造全量对象(hp 槽预填非零,绕 '!' 的 decode 0 断言)
721
755
  const nbuf = new PtrArrayBuffer(NOUT.size);
722
756
  new DataView(nbuf).setUint32(NOUT.offsetOf('sub') + NSUB.offsetOf('hp'), 0x1234, true);
@@ -4,7 +4,7 @@ import { Tester } from './test_helper.js'
4
4
  import { struct, union } from '../lib/ffi/struct.js'
5
5
  import { bind, } from '../lib/ffi/bind.js'
6
6
  import { type MaybePtr, Ptr, PtrArrayBuffer } from '../lib/ffi/ctype.js'
7
- import type { C_Union } from '../lib/ffi/ctype.js'
7
+ import type { C_Struct, C_Union } from '../lib/ffi/ctype.js'
8
8
 
9
9
  // 编译期断言工具(仅类型层,运行时无开销)
10
10
  type Equal<A, B> = (<G>() => G extends A ? 1 : 2) extends (<G>() => G extends B ? 1 : 2) ? true : false
@@ -22,7 +22,8 @@ const RECT = /* @__PURE__ */ struct('RECT', {
22
22
  bottom: 'i32',
23
23
  })
24
24
 
25
- const TVITEM = /* @__PURE__ */ struct('TVITEM', {
25
+ const TVITEM_DECL = {
26
+ '#': 'struct',
26
27
  mask: 'u32',
27
28
  hItem: '<>ptr',
28
29
  state: 'u32',
@@ -33,11 +34,12 @@ const TVITEM = /* @__PURE__ */ struct('TVITEM', {
33
34
  iSelectedImage: 'i32',
34
35
  cChildren: 'i32',
35
36
  lParam: '<>ptr',
36
- })
37
+ } satisfies C_Struct
38
+ const TVITEM = /* @__PURE__ */ struct('TVITEM', TVITEM_DECL)
37
39
  const TVINSERTSTRUCT = /* @__PURE__ */ struct('TVINSERTSTRUCT', {
38
40
  hParent: '<>ptr',
39
41
  hInsertAfter: '<>ptr',
40
- item: TVITEM.__struct,
42
+ item: TVITEM_DECL,
41
43
  })
42
44
 
43
45
  export const suite = {
@@ -260,13 +262,15 @@ export const suite = {
260
262
  t.check('[0]', 42, one.v[0])
261
263
 
262
264
  t.section('array of struct roundtrip (stride = child size)')
263
- const PT = struct('PT', {
265
+ const PT_DECL = {
266
+ '#': 'struct',
264
267
  x: 'i32',
265
268
  y: 'i32',
266
- })
269
+ } satisfies C_Struct
270
+ const PT = /* @__PURE__ */ struct('PT', PT_DECL)
267
271
  const POLY = struct('POLY', {
268
272
  count: 'u32',
269
- pts: { '#': 'array', element: PT.__struct, length: 3 },
273
+ pts: { '#': 'array', element: PT_DECL, length: 3 },
270
274
  })
271
275
  t.check('POLY.size == 28', 28, POLY.size)
272
276
  t.check('POLY.offsetOf pts', 4, POLY.offsetOf('pts'))
@@ -296,9 +300,24 @@ export const suite = {
296
300
  try { (struct as any)({ outer: { inner: 'u32' } }) } catch { rejectedMap = true }
297
301
  t.check('bare nested map rejected(漏写 #)', true, rejectedMap)
298
302
 
299
- // 顶层 '#' 由构造器写入:字段表混入的 '#' 指令键被剔除(运行时兜底,类型层已禁)
300
- const H = (struct as any)({ '#': 'union', a: 'u8', b: 'u32' })
301
- t.check('top-level # stripped(仍按函数名 struct 布局)', 8, H.size)
303
+ // 顶层 '#' 与函数名 kind 不符 → throw(union DECL 误传 struct() 防线);
304
+ // 一致('#': 'struct' 的 DECL 直传形态)→ 按 kind 正常布局
305
+ let rejectedKind = false
306
+ try { (struct as any)({ '#': 'union', a: 'u8', b: 'u32' }) } catch { rejectedKind = true }
307
+ t.check('top-level # kind mismatch rejected', true, rejectedKind)
308
+ const H = (struct as any)('H', { '#': 'struct', a: 'u8', b: 'u32' })
309
+ t.check('top-level # matching kind accepted(DECL 直传)', 8, H.size)
310
+
311
+ // 类型层 kind 锁(参数交叉 `{ '#'?: 'struct' }` / `{ '#'?: 'union' }`):DECL 的
312
+ // '#' 字面与函数名 kind 不符 → 交叉 never,编译期报错。@ts-expect-error 断言该
313
+ // 报错存在(锁失效则指令未使用、tsc 报错);仅类型期检查,函数不调用
314
+ const _kindLock = () => {
315
+ // @ts-expect-error —— union DECL 传 struct()
316
+ struct('BAD_U', { '#': 'union', a: 'u8', b: 'u32' })
317
+ // @ts-expect-error —— struct DECL 传 union()
318
+ union('BAD_S', { '#': 'struct', a: 'u8', b: 'u32' })
319
+ }
320
+ void _kindLock
302
321
 
303
322
  t.section("pointer member '<>ptr' raw vs '<T>ptr' branded")
304
323
  const PTR = struct('PTR', {
@@ -405,17 +424,19 @@ export const suite = {
405
424
  t.check('BROWSEINFOW.offsetOf ulFlags', is64 ? 32 : 16, BROWSEINFOW.offsetOf('ulFlags'))
406
425
 
407
426
  t.section('NMHDR(嵌套时 MSVC 尾 padding 传染)')
408
- const NMHDR = struct('NMHDR', {
427
+ const NMHDR_DECL = {
428
+ '#': 'struct',
409
429
  hwndFrom: '<>ptr',
410
430
  idFrom: '<>ptr',
411
431
  code: 'i32',
412
- })
432
+ } satisfies C_Struct
433
+ const NMHDR = /* @__PURE__ */ struct('NMHDR', NMHDR_DECL)
413
434
  t.check('NMHDR.size', is64 ? 24 : 12, NMHDR.size)
414
435
  t.check('NMHDR.offsetOf code', is64 ? 16 : 8, NMHDR.offsetOf('code'))
415
436
 
416
437
  t.section('NMCUSTOMDRAW / NMLVCUSTOMDRAW (ListView custom draw)')
417
438
  const NMCUSTOMDRAW = struct('NMCUSTOMDRAW', {
418
- hdr: NMHDR.__struct,
439
+ hdr: NMHDR_DECL,
419
440
  dwDrawStage: 'u32',
420
441
  hdc: '<>ptr',
421
442
  rc: 'i32[4]',
@@ -428,7 +449,7 @@ export const suite = {
428
449
  t.check('NMCUSTOMDRAW.offsetOf hdc', is64 ? 32 : 16, NMCUSTOMDRAW.offsetOf('hdc'))
429
450
  t.check('NMCUSTOMDRAW.offsetOf dwItemSpec', is64 ? 56 : 36, NMCUSTOMDRAW.offsetOf('dwItemSpec'))
430
451
  const NMLVCUSTOMDRAW = struct('NMLVCUSTOMDRAW', {
431
- hdr: NMHDR.__struct,
452
+ hdr: NMHDR_DECL,
432
453
  dwDrawStage: 'u32',
433
454
  hdc: '<>ptr',
434
455
  rc: 'i32[4]',
@@ -447,7 +468,7 @@ export const suite = {
447
468
 
448
469
  t.section('NMLISTVIEW / NMITEMACTIVATE')
449
470
  const NMLISTVIEW = struct('NMLISTVIEW', {
450
- hdr: NMHDR.__struct,
471
+ hdr: NMHDR_DECL,
451
472
  iItem: 'i32',
452
473
  iSubItem: 'i32',
453
474
  uNewState: 'u32',
@@ -504,7 +525,8 @@ export const suite = {
504
525
  t.check('LVCOLUMNW.offsetOf iOrder', is64 ? 36 : 28, LVCOLUMNW.offsetOf('iOrder'))
505
526
 
506
527
  t.section('NMDATETIMECHANGE')
507
- const SYSTEMTIME = struct('SYSTEMTIME', {
528
+ const SYSTEMTIME_DECL = {
529
+ '#': 'struct',
508
530
  wYear: 'u16',
509
531
  wMonth: 'u16',
510
532
  wDayOfWeek: 'u16',
@@ -513,27 +535,29 @@ export const suite = {
513
535
  wMinute: 'u16',
514
536
  wSecond: 'u16',
515
537
  wMilliseconds: 'u16',
516
- })
538
+ } satisfies C_Struct
517
539
  const NMDATETIMECHANGE = struct('NMDATETIMECHANGE', {
518
- hdr: NMHDR.__struct,
540
+ hdr: NMHDR_DECL,
519
541
  dwFlags: 'u32',
520
- st: SYSTEMTIME.__struct,
542
+ st: SYSTEMTIME_DECL,
521
543
  })
522
544
  t.check('NMDATETIMECHANGE.size', is64 ? 48 : 32, NMDATETIMECHANGE.size)
523
545
  t.check('NMDATETIMECHANGE.offsetOf dwFlags', is64 ? 24 : 12, NMDATETIMECHANGE.offsetOf('dwFlags'))
524
546
  t.check('NMDATETIMECHANGE.offsetOf st', is64 ? 28 : 16, NMDATETIMECHANGE.offsetOf('st'))
525
547
 
526
548
  t.section('NMLINK szUrl offset')
527
- const LITEM = struct('LITEM', {
549
+ const LITEM_DECL = {
550
+ '#': 'struct',
528
551
  mask: 'u32',
529
552
  iLink: 'i32',
530
553
  state: 'u32',
531
554
  stateMask: 'u32',
532
555
  szID: 'u16[48]@utf-16le',
533
- })
556
+ } satisfies C_Struct
557
+ const LITEM = /* @__PURE__ */ struct('LITEM', LITEM_DECL)
534
558
  const NMLINK = struct('NMLINK', {
535
- hdr: NMHDR.__struct,
536
- item: LITEM.__struct,
559
+ hdr: NMHDR_DECL,
560
+ item: LITEM_DECL,
537
561
  szUrl: 'u16[2084]@utf-16le',
538
562
  })
539
563
  t.check('LITEM.offsetOf szID', 16, LITEM.offsetOf('szID'))
@@ -766,8 +790,14 @@ export const suite = {
766
790
  t.section('EncodeIn DFS 后序:子树含必填 ⇒ 键必填;值后序合成(非必填兄弟可省)')
767
791
  {
768
792
  // 嵌套子结构含 '!'(内层强制)+ 标量/字符串糖(内层可省:''/0 是合法零值)
769
- const NSUB = struct('NSUB', { hp: '<X>ptr!', rest: 'u32', s: 'u16[4]@utf-8' })
770
- const NOUT = struct('NOUT', { top: 'u32', sub: NSUB.__struct })
793
+ const NSUB_DECL = {
794
+ '#': 'struct',
795
+ hp: '<X>ptr!',
796
+ rest: 'u32',
797
+ s: 'u16[4]@utf-8',
798
+ } satisfies C_Struct
799
+ const NSUB = /* @__PURE__ */ struct('NSUB', NSUB_DECL)
800
+ const NOUT = struct('NOUT', { top: 'u32', sub: NSUB_DECL })
771
801
  // decode 造全量对象(hp 槽预填非零,绕 '!' 的 decode 0 断言)
772
802
  const nbuf = new PtrArrayBuffer(NOUT.size)
773
803
  new DataView(nbuf).setUint32(NOUT.offsetOf('sub') + NSUB.offsetOf('hp'), 0x1234, true)
@@ -14,7 +14,7 @@ const H = 240;
14
14
  export const suite = {
15
15
  name: 'gdi-draw',
16
16
  run: (t) => {
17
- // —— 基座:屏幕 DC → 内存 DC + 32bpp 位图(与 exec_server_worker 截屏同型)——
17
+ // —— 基座:屏幕 DC → 内存 DC + 32bpp 位图(与 execd_worker 截屏同型)——
18
18
  t.section('setup: memory DC + 32bpp bitmap');
19
19
  const screen = GetDC(NULL);
20
20
  const mem = CreateCompatibleDC(screen);
@@ -27,7 +27,7 @@ const H = 240
27
27
  export const suite = {
28
28
  name: 'gdi-draw',
29
29
  run: (t: Tester) => {
30
- // —— 基座:屏幕 DC → 内存 DC + 32bpp 位图(与 exec_server_worker 截屏同型)——
30
+ // —— 基座:屏幕 DC → 内存 DC + 32bpp 位图(与 execd_worker 截屏同型)——
31
31
  t.section('setup: memory DC + 32bpp bitmap')
32
32
  const screen = GetDC(NULL)
33
33
  const mem = CreateCompatibleDC(screen)