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
@@ -0,0 +1,122 @@
1
+ import * as os from 'os';
2
+ import * as std from 'std';
3
+ import { WCHAR } from '../lib/ffi/bind.js';
4
+ import { NULL, PtrArrayBuffer } from '../lib/ffi/ctype.js';
5
+ import { struct } from '../lib/ffi/struct.js';
6
+ import { CloseHandle, CreatePipe, CreateProcess, GetExitCodeProcess, GetLastError, GetSystemDirectory, ReadFile, SetHandleInformation, WaitForSingleObject, } from '../lib/windows/kernel32.js';
7
+ import { PROCESS_INFORMATION, STARTUPINFOW } from '../lib/windows/structs.js';
8
+ // worker 没有可观测的输出通道:绑定失败会静默中断 worker 脚本,主线程永远等不到消息。
9
+ // 失败原因落盘 diag.log 以便定位(典型:DLL 位数与进程不匹配 -> ERROR_BAD_EXE_FORMAT 193)。
10
+ const diagFile = (stage) => {
11
+ try {
12
+ const f = std.open('diag.log', 'a');
13
+ if (f) {
14
+ f.puts(`${Date.now()} ${stage}\n`);
15
+ f.close();
16
+ }
17
+ }
18
+ catch (ex) { /* best effort */ }
19
+ };
20
+ const HANDLE_FLAG_INHERIT = 0x1;
21
+ const STARTF_USESTDHANDLES = 0x100;
22
+ const WAIT_INFINITE = 0xffffffff;
23
+ // STARTUPINFOW / PROCESS_INFORMATION 的布局随进程位宽(x86 68B / x64 104B),由 struct 按 os.arch 推。
24
+ // os.arch 是编译期的进程指针宽度(quickjs-libc.c OS_ARCH),WOW64 下的 32 位进程得 ia32 布局——
25
+ // 本地 win7 VM 上的 execd 就是 32 位进程跑在 64 位系统上。
26
+ const parent = os.Worker.parent;
27
+ // GetSystemDirectoryW 拼 cmd.exe 全路径。
28
+ // 探针实测(XP/Win7 均如此):CreateProcessW 的 lpCommandLine 第一个 token 若是
29
+ // 裸 "cmd.exe",PATH 解析在本环境失败(err 267 ERROR_DIRECTORY / 123 ERROR_INVALID_NAME),
30
+ // 用全路径即正常。cmd 内部再解析 ping/dir 等用自己的 PATH,无此问题。
31
+ let sysDir = 'C:\\Windows\\System32';
32
+ try {
33
+ const out = WCHAR.alloc(256);
34
+ const n = GetSystemDirectory(out, 256);
35
+ const s = n > 0 ? WCHAR.decode(out) : '';
36
+ if (s)
37
+ sysDir = s;
38
+ }
39
+ catch (ex) {
40
+ diagFile('SYS-DIR-FAIL: ' + String(ex));
41
+ }
42
+ // 用 CreateProcessW + CreatePipe 直接捕获子进程 stdout(替代 winpty)。
43
+ // 纯捕获场景(/exec 从不交互),管道方案比 winpty 少一层 agent 中转:
44
+ // - 流式粒度更好:探针实测 XP 上逐行实时到达(winpty 攒批 ~4s)
45
+ // - 无 winpty.dll / winpty-agent.exe 依赖,纯 kernel32
46
+ // 编码:无统一代码页转换——cmd 内置经 /u 恒为 UTF-16LE,外部程序各自原生
47
+ // (qwin= UTF-8、中文系统工具= GBK),客户端按来源分别解码。
48
+ // 同步阻塞读循环(worker 线程自转),主线程事件循环不受影响。
49
+ // CreatePipe 的两个 HANDLE 出参槽:一个结构两个指针字段,读回走 decode
50
+ // CreatePipe 成功后两端句柄必非零(失败已在下方 throw)——字段标 '!',decode 直出 Ptr
51
+ const PIPE_HANDLES = /* @__PURE__ */ struct('PIPE_HANDLES', { hRead: '<HFILE>ptr!', hWrite: '<HFILE>ptr!' });
52
+ function runCmd(id, cmd) {
53
+ // —— 管道 + 继承设置(读端不可继承,否则 EOF 永不触发)——
54
+ const pipe = PIPE_HANDLES.alloc();
55
+ if (!CreatePipe(pipe.ptr, pipe.ptr + PIPE_HANDLES.offsetOf('hWrite'), NULL, 0)) {
56
+ throw new Error('CreatePipe err=' + GetLastError());
57
+ }
58
+ const { hRead, hWrite } = PIPE_HANDLES.decode(pipe);
59
+ SetHandleInformation(hWrite, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
60
+ SetHandleInformation(hRead, HANDLE_FLAG_INHERIT, 0);
61
+ // —— STARTUPINFO(写端作为子进程 stdout/stderr)——
62
+ const pi = PROCESS_INFORMATION.alloc();
63
+ // 恒加 /u:cmd 内置输出(echo/dir/type 与 cmd 自身报错)直接写 UTF-16LE,绕开「按代码页
64
+ // 编码成字节」这一步(Tiny11 缺 NLS 时中文变 ?;win7/XP 的 GBK 无损只是 ACP=936 的 locale 巧合)。
65
+ // /u 在所有 Win 版本行为一致,故不分版本——早期用 RtlGetVersion 判 NT>=10 只对 win11 加 /u,已删。
66
+ // 外部程序(qwin/ping 等)输出仍为各自原生编码,/u 不参与(实测 ping 仍透传 GBK)。见 .agents/CMD_ENCODING_ACP_NLS.md §8。
67
+ const cmdline = `${sysDir}\\cmd.exe /u /c ${cmd}`;
68
+ if (!CreateProcess(NULL, cmdline, NULL, NULL, 1, 0, NULL, NULL, { cb: STARTUPINFOW.size, dwFlags: STARTF_USESTDHANDLES, hStdOutput: hWrite, hStdError: hWrite }, pi.ptr)) {
69
+ CloseHandle(hRead);
70
+ CloseHandle(hWrite);
71
+ throw new Error('CreateProcessW err=' + GetLastError() + ' cmd=' + cmdline);
72
+ }
73
+ const { hProcess, hThread, dwProcessId } = PROCESS_INFORMATION.decode(pi);
74
+ CloseHandle(hThread);
75
+ CloseHandle(hWrite);
76
+ parent.postMessage({ type: 'info', id, pid: dwProcessId });
77
+ // —— 同步阻塞读循环(子进程树全退出、写端全关 -> EOF -> 收尾)——
78
+ const bufB = new PtrArrayBuffer(4096);
79
+ const buf = new Uint8Array(bufB);
80
+ const nReadB = new PtrArrayBuffer(4);
81
+ const nRead = new Uint32Array(nReadB);
82
+ for (;;) {
83
+ nRead[0] = 0;
84
+ if (!ReadFile(hRead, bufB, 4096, nReadB, NULL))
85
+ break;
86
+ const n = nRead[0];
87
+ if (n === 0)
88
+ break;
89
+ parent.postMessage({ type: 'data', id, chunk: buf.slice(0, n) });
90
+ }
91
+ WaitForSingleObject(hProcess, WAIT_INFINITE);
92
+ const ecB = new PtrArrayBuffer(4);
93
+ const ec = new Int32Array(ecB);
94
+ GetExitCodeProcess(hProcess, ecB);
95
+ const code = ec[0];
96
+ CloseHandle(hRead);
97
+ CloseHandle(hProcess);
98
+ return code;
99
+ }
100
+ parent.onmessage = (e) => {
101
+ // worker 只剩 /exec 一个租客:外部命令不可控,必须与主进程隔离(长阻塞无上界)。
102
+ // 内置端点(截屏/窗口列表/改分辨率)全部在主进程同步跑——bug 当场 throw → 500,
103
+ // 而不是在 worker 里静默挂掉等 timer 兜底成 504。
104
+ const msg = e.data;
105
+ if (msg.type === 'run' && typeof msg.cmd === 'string') {
106
+ let code = -1;
107
+ let error = null;
108
+ try {
109
+ code = runCmd(msg.id, msg.cmd);
110
+ }
111
+ catch (ex) {
112
+ error = String(ex);
113
+ }
114
+ parent.postMessage({ type: 'result', id: msg.id, code, error });
115
+ }
116
+ // 父侧每个请求起一个新 worker,一次只处理一个请求,处理完立刻释放自己的 port:
117
+ // port_list 清空后 js_os_poll 返回 -1(quickjs-libc.c:2506)→ 本线程退出,
118
+ // JSRuntime 随之释放。不设 null 的话线程常驻(实测 win7 30 次请求线程 4→35)。
119
+ // 注意父侧 `worker.onmessage = null` 只释放父侧 port,对本线程无效——必须在这里设。
120
+ // 消息已在 js_post_message_pipe 进队列,父侧读的是同一份 refcount 共享管道,线程退出不影响。
121
+ parent.onmessage = null;
122
+ };
@@ -0,0 +1,127 @@
1
+ import * as os from 'os'
2
+ import * as std from 'std'
3
+ import { WCHAR } from '../lib/ffi/bind.js'
4
+ import { NULL, PtrArrayBuffer } from '../lib/ffi/ctype.js'
5
+ import { struct } from '../lib/ffi/struct.js'
6
+ import {
7
+ CloseHandle, CreatePipe, CreateProcess, GetExitCodeProcess, GetLastError, GetSystemDirectory,
8
+ ReadFile, SetHandleInformation, WaitForSingleObject,
9
+ } from '../lib/windows/kernel32.js'
10
+ import { PROCESS_INFORMATION, STARTUPINFOW } from '../lib/windows/structs.js'
11
+
12
+ // worker 没有可观测的输出通道:绑定失败会静默中断 worker 脚本,主线程永远等不到消息。
13
+ // 失败原因落盘 diag.log 以便定位(典型:DLL 位数与进程不匹配 -> ERROR_BAD_EXE_FORMAT 193)。
14
+ const diagFile = (stage: string): void => {
15
+ try {
16
+ const f = std.open('diag.log', 'a')
17
+ if (f) { f.puts(`${Date.now()} ${stage}\n`); f.close() }
18
+ } catch (ex) { /* best effort */ }
19
+ }
20
+
21
+ const HANDLE_FLAG_INHERIT = 0x1
22
+ const STARTF_USESTDHANDLES = 0x100
23
+ const WAIT_INFINITE = 0xffffffff
24
+ // STARTUPINFOW / PROCESS_INFORMATION 的布局随进程位宽(x86 68B / x64 104B),由 struct 按 os.arch 推。
25
+ // os.arch 是编译期的进程指针宽度(quickjs-libc.c OS_ARCH),WOW64 下的 32 位进程得 ia32 布局——
26
+ // 本地 win7 VM 上的 execd 就是 32 位进程跑在 64 位系统上。
27
+
28
+ const parent = os.Worker.parent
29
+
30
+ // GetSystemDirectoryW 拼 cmd.exe 全路径。
31
+ // 探针实测(XP/Win7 均如此):CreateProcessW 的 lpCommandLine 第一个 token 若是
32
+ // 裸 "cmd.exe",PATH 解析在本环境失败(err 267 ERROR_DIRECTORY / 123 ERROR_INVALID_NAME),
33
+ // 用全路径即正常。cmd 内部再解析 ping/dir 等用自己的 PATH,无此问题。
34
+ let sysDir = 'C:\\Windows\\System32'
35
+ try {
36
+ const out = WCHAR.alloc(256)
37
+ const n = GetSystemDirectory(out, 256)
38
+ const s = n > 0 ? WCHAR.decode(out) : ''
39
+ if (s) sysDir = s
40
+ } catch (ex) {
41
+ diagFile('SYS-DIR-FAIL: ' + String(ex))
42
+ }
43
+
44
+ // 用 CreateProcessW + CreatePipe 直接捕获子进程 stdout(替代 winpty)。
45
+ // 纯捕获场景(/exec 从不交互),管道方案比 winpty 少一层 agent 中转:
46
+ // - 流式粒度更好:探针实测 XP 上逐行实时到达(winpty 攒批 ~4s)
47
+ // - 无 winpty.dll / winpty-agent.exe 依赖,纯 kernel32
48
+ // 编码:无统一代码页转换——cmd 内置经 /u 恒为 UTF-16LE,外部程序各自原生
49
+ // (qwin= UTF-8、中文系统工具= GBK),客户端按来源分别解码。
50
+ // 同步阻塞读循环(worker 线程自转),主线程事件循环不受影响。
51
+ // CreatePipe 的两个 HANDLE 出参槽:一个结构两个指针字段,读回走 decode
52
+ // CreatePipe 成功后两端句柄必非零(失败已在下方 throw)——字段标 '!',decode 直出 Ptr
53
+ const PIPE_HANDLES = /* @__PURE__ */ struct('PIPE_HANDLES', { hRead: '<HFILE>ptr!', hWrite: '<HFILE>ptr!' })
54
+
55
+ function runCmd(id: number, cmd: string): number {
56
+ // —— 管道 + 继承设置(读端不可继承,否则 EOF 永不触发)——
57
+ const pipe = PIPE_HANDLES.alloc()
58
+ if (!CreatePipe(pipe.ptr, pipe.ptr + PIPE_HANDLES.offsetOf('hWrite'), NULL, 0)) {
59
+ throw new Error('CreatePipe err=' + GetLastError())
60
+ }
61
+ const { hRead, hWrite } = PIPE_HANDLES.decode(pipe)
62
+ SetHandleInformation(hWrite, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)
63
+ SetHandleInformation(hRead, HANDLE_FLAG_INHERIT, 0)
64
+
65
+ // —— STARTUPINFO(写端作为子进程 stdout/stderr)——
66
+ const pi = PROCESS_INFORMATION.alloc()
67
+ // 恒加 /u:cmd 内置输出(echo/dir/type 与 cmd 自身报错)直接写 UTF-16LE,绕开「按代码页
68
+ // 编码成字节」这一步(Tiny11 缺 NLS 时中文变 ?;win7/XP 的 GBK 无损只是 ACP=936 的 locale 巧合)。
69
+ // /u 在所有 Win 版本行为一致,故不分版本——早期用 RtlGetVersion 判 NT>=10 只对 win11 加 /u,已删。
70
+ // 外部程序(qwin/ping 等)输出仍为各自原生编码,/u 不参与(实测 ping 仍透传 GBK)。见 .agents/CMD_ENCODING_ACP_NLS.md §8。
71
+ const cmdline = `${sysDir}\\cmd.exe /u /c ${cmd}`
72
+ if (!CreateProcess(NULL, cmdline, NULL, NULL, 1, 0, NULL, NULL,
73
+ { cb: STARTUPINFOW.size, dwFlags: STARTF_USESTDHANDLES, hStdOutput: hWrite, hStdError: hWrite }, pi.ptr)) {
74
+ CloseHandle(hRead)
75
+ CloseHandle(hWrite)
76
+ throw new Error('CreateProcessW err=' + GetLastError() + ' cmd=' + cmdline)
77
+ }
78
+ const { hProcess, hThread, dwProcessId } = PROCESS_INFORMATION.decode(pi)
79
+ CloseHandle(hThread)
80
+ CloseHandle(hWrite)
81
+ parent.postMessage({ type: 'info', id, pid: dwProcessId })
82
+
83
+ // —— 同步阻塞读循环(子进程树全退出、写端全关 -> EOF -> 收尾)——
84
+ const bufB = new PtrArrayBuffer(4096)
85
+ const buf = new Uint8Array(bufB)
86
+ const nReadB = new PtrArrayBuffer(4)
87
+ const nRead = new Uint32Array(nReadB)
88
+ for (;;) {
89
+ nRead[0] = 0
90
+ if (!ReadFile(hRead, bufB, 4096, nReadB, NULL)) break
91
+ const n = nRead[0]!
92
+ if (n === 0) break
93
+ parent.postMessage({ type: 'data', id, chunk: buf.slice(0, n) })
94
+ }
95
+
96
+ WaitForSingleObject(hProcess, WAIT_INFINITE)
97
+ const ecB = new PtrArrayBuffer(4)
98
+ const ec = new Int32Array(ecB)
99
+ GetExitCodeProcess(hProcess, ecB)
100
+ const code = ec[0]!
101
+ CloseHandle(hRead)
102
+ CloseHandle(hProcess)
103
+ return code
104
+ }
105
+
106
+ parent.onmessage = (e) => {
107
+ // worker 只剩 /exec 一个租客:外部命令不可控,必须与主进程隔离(长阻塞无上界)。
108
+ // 内置端点(截屏/窗口列表/改分辨率)全部在主进程同步跑——bug 当场 throw → 500,
109
+ // 而不是在 worker 里静默挂掉等 timer 兜底成 504。
110
+ const msg = e.data as { type: string; id: number; cmd?: string }
111
+ if (msg.type === 'run' && typeof msg.cmd === 'string') {
112
+ let code = -1
113
+ let error: string | null = null
114
+ try {
115
+ code = runCmd(msg.id, msg.cmd)
116
+ } catch (ex) {
117
+ error = String(ex)
118
+ }
119
+ parent.postMessage({ type: 'result', id: msg.id, code, error })
120
+ }
121
+ // 父侧每个请求起一个新 worker,一次只处理一个请求,处理完立刻释放自己的 port:
122
+ // port_list 清空后 js_os_poll 返回 -1(quickjs-libc.c:2506)→ 本线程退出,
123
+ // JSRuntime 随之释放。不设 null 的话线程常驻(实测 win7 30 次请求线程 4→35)。
124
+ // 注意父侧 `worker.onmessage = null` 只释放父侧 port,对本线程无效——必须在这里设。
125
+ // 消息已在 js_post_message_pipe 进队列,父侧读的是同一份 refcount 共享管道,线程退出不影响。
126
+ parent.onmessage = null
127
+ }
@@ -16280,7 +16280,7 @@ function doEncode(dv, base, fields, v) {
16280
16280
  function createStruct(t) {
16281
16281
  const { fields, size, maxEffectiveAlign } = computeStructLayout(t);
16282
16282
  return {
16283
- __struct: t,
16283
+ fields,
16284
16284
  size,
16285
16285
  structAlign: maxEffectiveAlign,
16286
16286
  decode: (p) => {
@@ -16309,6 +16309,14 @@ function createStruct(t) {
16309
16309
  };
16310
16310
  }
16311
16311
  function buildDecl(kind, member, pack) {
16312
+ const declKind = member["#"];
16313
+ if (declKind !== void 0 && declKind !== kind)
16314
+ throw new Error(`ffi-struct: ${kind}() received a '${String(declKind)}' declaration (kind mismatch \u2014 use ${declKind}() for it)`);
16315
+ const declPack = member["#pack"];
16316
+ if (pack === void 0 && declPack !== void 0)
16317
+ pack = declPack;
16318
+ else if (pack !== void 0 && declPack !== void 0 && pack !== declPack)
16319
+ throw new Error(`ffi-struct: #pack conflict: opts.pack=${pack} vs declaration ${String(declPack)}`);
16312
16320
  const decl = { "#": kind };
16313
16321
  if (pack !== void 0)
16314
16322
  decl["#pack"] = pack;
@@ -16317,49 +16325,6 @@ function buildDecl(kind, member, pack) {
16317
16325
  decl[k] = v;
16318
16326
  return decl;
16319
16327
  }
16320
- function structArray(def) {
16321
- const { fields, size } = computeStructLayout(def.__struct);
16322
- const readN = (dv, n) => {
16323
- const out = [];
16324
- for (let i = 0; i < n; i++)
16325
- out.push(doDecode(dv, i * size, fields));
16326
- return out;
16327
- };
16328
- return {
16329
- encode: (els) => {
16330
- if (!Array.isArray(els) || els.length === 0)
16331
- throw new Error(`ffi-struct: structArray(def).encode(els) requires a non-empty element array (pass NULL for an empty pointer position)`);
16332
- const out = def.alloc(els.length);
16333
- for (let i = 0; i < els.length; i++)
16334
- def.encode(els[i], out, i * def.size);
16335
- return out;
16336
- },
16337
- decode: ((p, count) => {
16338
- if (count !== void 0 && (!Number.isInteger(count) || count < 0))
16339
- throw new Error(`ffi-struct: structArray.decode(p, count) requires a non-negative integer count, got ${count}`);
16340
- if (typeof p === "number") {
16341
- if (count === void 0)
16342
- throw new Error(`ffi-struct: structArray.decode(address, count) requires an explicit count (a bare address carries no length)`);
16343
- if (count === 0)
16344
- return [];
16345
- return readN(new DataView(ffi2.readBytes(p, count * size)), count);
16346
- }
16347
- let n;
16348
- if (count !== void 0) {
16349
- n = count;
16350
- if (n * size > p.byteLength)
16351
- throw new Error(`ffi-struct: structArray.decode: count ${n} \xD7 size ${size} = ${n * size} exceeds buffer byteLength ${p.byteLength}`);
16352
- } else {
16353
- if (p.byteLength % size !== 0)
16354
- throw new Error(`ffi-struct: structArray.decode: byteLength ${p.byteLength} is not a multiple of size ${size} (mixed buffer? pass count explicitly)`);
16355
- n = p.byteLength / size;
16356
- }
16357
- if (n === 0)
16358
- return [];
16359
- return readN(new DataView(p), n);
16360
- })
16361
- };
16362
- }
16363
16328
  function struct(a, b6, c) {
16364
16329
  const isNamed = typeof a === "string";
16365
16330
  const raw = isNamed ? b6 : a;
@@ -16368,21 +16333,28 @@ function struct(a, b6, c) {
16368
16333
  }
16369
16334
 
16370
16335
  // _build/lib/windows/structs.js
16371
- var RECT = /* @__PURE__ */ struct("RECT", {
16336
+ var RECT_DECL = {
16337
+ "#": "struct",
16372
16338
  left: "i32",
16373
16339
  top: "i32",
16374
16340
  right: "i32",
16375
16341
  bottom: "i32"
16376
- });
16377
- var POINT = /* @__PURE__ */ struct("POINT", {
16342
+ };
16343
+ var RECT = /* @__PURE__ */ struct("RECT", RECT_DECL);
16344
+ var POINT_DECL = {
16345
+ "#": "struct",
16378
16346
  x: "i32",
16379
16347
  y: "i32"
16380
- });
16381
- var SIZE = /* @__PURE__ */ struct("SIZE", {
16348
+ };
16349
+ var POINT = /* @__PURE__ */ struct("POINT", POINT_DECL);
16350
+ var SIZE_DECL = {
16351
+ "#": "struct",
16382
16352
  cx: "i32",
16383
16353
  cy: "i32"
16384
- });
16385
- var LOGFONTW = /* @__PURE__ */ struct("LOGFONTW", {
16354
+ };
16355
+ var SIZE = /* @__PURE__ */ struct("SIZE", SIZE_DECL);
16356
+ var LOGFONTW_DECL = {
16357
+ "#": "struct",
16386
16358
  lfHeight: "i32",
16387
16359
  lfWidth: "i32",
16388
16360
  lfEscapement: "i32",
@@ -16397,8 +16369,10 @@ var LOGFONTW = /* @__PURE__ */ struct("LOGFONTW", {
16397
16369
  lfQuality: "u8",
16398
16370
  lfPitchAndFamily: "u8",
16399
16371
  lfFaceName: "u16[32]@utf-16le"
16400
- });
16401
- var BITMAPINFOHEADER = /* @__PURE__ */ struct("BITMAPINFOHEADER", {
16372
+ };
16373
+ var LOGFONTW = /* @__PURE__ */ struct("LOGFONTW", LOGFONTW_DECL);
16374
+ var BITMAPINFOHEADER_DECL = {
16375
+ "#": "struct",
16402
16376
  biSize: "u32",
16403
16377
  biWidth: "i32",
16404
16378
  biHeight: "i32",
@@ -16410,8 +16384,10 @@ var BITMAPINFOHEADER = /* @__PURE__ */ struct("BITMAPINFOHEADER", {
16410
16384
  biYPelsPerMeter: "i32",
16411
16385
  biClrUsed: "u32",
16412
16386
  biClrImportant: "u32"
16413
- });
16414
- var OPENFILENAMEW = /* @__PURE__ */ struct("OPENFILENAMEW", {
16387
+ };
16388
+ var BITMAPINFOHEADER = /* @__PURE__ */ struct("BITMAPINFOHEADER", BITMAPINFOHEADER_DECL);
16389
+ var OPENFILENAMEW_DECL = {
16390
+ "#": "struct",
16415
16391
  lStructSize: "u32",
16416
16392
  hwndOwner: "<HWND>ptr",
16417
16393
  hInstance: "<HMODULE>ptr",
@@ -16435,8 +16411,10 @@ var OPENFILENAMEW = /* @__PURE__ */ struct("OPENFILENAMEW", {
16435
16411
  pvReserved: "<>ptr",
16436
16412
  dwReserved: "u32",
16437
16413
  FlagsEx: "u32"
16438
- });
16439
- var BROWSEINFOW = /* @__PURE__ */ struct("BROWSEINFOW", {
16414
+ };
16415
+ var OPENFILENAMEW = /* @__PURE__ */ struct("OPENFILENAMEW", OPENFILENAMEW_DECL);
16416
+ var BROWSEINFOW_DECL = {
16417
+ "#": "struct",
16440
16418
  hwndOwner: "<HWND>ptr",
16441
16419
  pidlRoot: "<>ptr",
16442
16420
  pszDisplayName: "<>ptr",
@@ -16445,13 +16423,17 @@ var BROWSEINFOW = /* @__PURE__ */ struct("BROWSEINFOW", {
16445
16423
  lpfn: "<>ptr",
16446
16424
  lParam: "<>ptr",
16447
16425
  iImage: "i32"
16448
- });
16449
- var NMHDR = /* @__PURE__ */ struct("NMHDR", {
16426
+ };
16427
+ var BROWSEINFOW = /* @__PURE__ */ struct("BROWSEINFOW", BROWSEINFOW_DECL);
16428
+ var NMHDR_DECL = {
16429
+ "#": "struct",
16450
16430
  hwndFrom: "<HWND>ptr",
16451
16431
  idFrom: "<>ptr",
16452
16432
  code: "i32"
16453
- });
16454
- var SYSTEMTIME = /* @__PURE__ */ struct("SYSTEMTIME", {
16433
+ };
16434
+ var NMHDR = /* @__PURE__ */ struct("NMHDR", NMHDR_DECL);
16435
+ var SYSTEMTIME_DECL = {
16436
+ "#": "struct",
16455
16437
  wYear: "u16",
16456
16438
  wMonth: "u16",
16457
16439
  wDayOfWeek: "u16",
@@ -16460,35 +16442,44 @@ var SYSTEMTIME = /* @__PURE__ */ struct("SYSTEMTIME", {
16460
16442
  wMinute: "u16",
16461
16443
  wSecond: "u16",
16462
16444
  wMilliseconds: "u16"
16463
- });
16464
- var NMDATETIMECHANGE = /* @__PURE__ */ struct("NMDATETIMECHANGE", {
16465
- hdr: NMHDR.__struct,
16445
+ };
16446
+ var SYSTEMTIME = /* @__PURE__ */ struct("SYSTEMTIME", SYSTEMTIME_DECL);
16447
+ var NMDATETIMECHANGE_DECL = {
16448
+ "#": "struct",
16449
+ hdr: NMHDR_DECL,
16466
16450
  dwFlags: "u32",
16467
- st: SYSTEMTIME.__struct
16468
- });
16469
- var LITEM = /* @__PURE__ */ struct("LITEM", {
16451
+ st: SYSTEMTIME_DECL
16452
+ };
16453
+ var NMDATETIMECHANGE = /* @__PURE__ */ struct("NMDATETIMECHANGE", NMDATETIMECHANGE_DECL);
16454
+ var LITEM_DECL = {
16455
+ "#": "struct",
16470
16456
  mask: "u32",
16471
16457
  iLink: "i32",
16472
16458
  state: "u32",
16473
16459
  stateMask: "u32",
16474
16460
  szID: "u16[48]@utf-16le",
16475
16461
  szUrl: "u16[2084]@utf-16le"
16476
- });
16477
- var NMLINK = /* @__PURE__ */ struct("NMLINK", {
16478
- hdr: NMHDR.__struct,
16479
- item: LITEM.__struct
16480
- });
16481
- var NMCUSTOMDRAW = /* @__PURE__ */ struct("NMCUSTOMDRAW", {
16482
- hdr: NMHDR.__struct,
16462
+ };
16463
+ var NMLINK_DECL = {
16464
+ "#": "struct",
16465
+ hdr: NMHDR_DECL,
16466
+ item: LITEM_DECL
16467
+ };
16468
+ var NMLINK = /* @__PURE__ */ struct("NMLINK", NMLINK_DECL);
16469
+ var NMCUSTOMDRAW_DECL = {
16470
+ "#": "struct",
16471
+ hdr: NMHDR_DECL,
16483
16472
  dwDrawStage: "u32",
16484
16473
  hdc: "<HDC>ptr",
16485
16474
  rc: "i32[4]",
16486
16475
  dwItemSpec: "<>ptr",
16487
16476
  uItemState: "u32",
16488
16477
  lItemlParam: "<>ptr"
16489
- });
16490
- var NMLVCUSTOMDRAW = /* @__PURE__ */ struct("NMLVCUSTOMDRAW", {
16491
- hdr: NMHDR.__struct,
16478
+ };
16479
+ var NMCUSTOMDRAW = /* @__PURE__ */ struct("NMCUSTOMDRAW", NMCUSTOMDRAW_DECL);
16480
+ var NMLVCUSTOMDRAW_DECL = {
16481
+ "#": "struct",
16482
+ hdr: NMHDR_DECL,
16492
16483
  dwDrawStage: "u32",
16493
16484
  hdc: "<HDC>ptr",
16494
16485
  rc: "i32[4]",
@@ -16499,9 +16490,11 @@ var NMLVCUSTOMDRAW = /* @__PURE__ */ struct("NMLVCUSTOMDRAW", {
16499
16490
  clrTextBk: "u32",
16500
16491
  iSubItem: "i32",
16501
16492
  dwItemType: "u32"
16502
- });
16503
- var NMLISTVIEW = /* @__PURE__ */ struct("NMLISTVIEW", {
16504
- hdr: NMHDR.__struct,
16493
+ };
16494
+ var NMLVCUSTOMDRAW = /* @__PURE__ */ struct("NMLVCUSTOMDRAW", NMLVCUSTOMDRAW_DECL);
16495
+ var NMLISTVIEW_DECL = {
16496
+ "#": "struct",
16497
+ hdr: NMHDR_DECL,
16505
16498
  iItem: "i32",
16506
16499
  iSubItem: "i32",
16507
16500
  uNewState: "u32",
@@ -16509,8 +16502,10 @@ var NMLISTVIEW = /* @__PURE__ */ struct("NMLISTVIEW", {
16509
16502
  uChanged: "u32",
16510
16503
  ptAction: "i32[2]",
16511
16504
  lParam: "<>ptr"
16512
- });
16513
- var TCITEMW = /* @__PURE__ */ struct("TCITEMW", {
16505
+ };
16506
+ var NMLISTVIEW = /* @__PURE__ */ struct("NMLISTVIEW", NMLISTVIEW_DECL);
16507
+ var TCITEMW_DECL = {
16508
+ "#": "struct",
16514
16509
  mask: "u32",
16515
16510
  dwState: "u32",
16516
16511
  dwStateMask: "u32",
@@ -16518,8 +16513,10 @@ var TCITEMW = /* @__PURE__ */ struct("TCITEMW", {
16518
16513
  cchTextMax: "i32",
16519
16514
  iImage: "i32",
16520
16515
  lParam: "<>ptr"
16521
- });
16522
- var TVITEM = /* @__PURE__ */ struct("TVITEM", {
16516
+ };
16517
+ var TCITEMW = /* @__PURE__ */ struct("TCITEMW", TCITEMW_DECL);
16518
+ var TVITEM_DECL = {
16519
+ "#": "struct",
16523
16520
  mask: "u32",
16524
16521
  hItem: "<>ptr",
16525
16522
  state: "u32",
@@ -16530,20 +16527,26 @@ var TVITEM = /* @__PURE__ */ struct("TVITEM", {
16530
16527
  iSelectedImage: "i32",
16531
16528
  cChildren: "i32",
16532
16529
  lParam: "<>ptr"
16533
- });
16534
- var TVINSERTSTRUCT = /* @__PURE__ */ struct("TVINSERTSTRUCT", {
16530
+ };
16531
+ var TVITEM = /* @__PURE__ */ struct("TVITEM", TVITEM_DECL);
16532
+ var TVINSERTSTRUCT_DECL = {
16533
+ "#": "struct",
16535
16534
  hParent: "<>ptr",
16536
16535
  hInsertAfter: "<>ptr",
16537
- item: TVITEM.__struct
16538
- });
16539
- var LVHITTESTINFO = /* @__PURE__ */ struct("LVHITTESTINFO", {
16536
+ item: TVITEM_DECL
16537
+ };
16538
+ var TVINSERTSTRUCT = /* @__PURE__ */ struct("TVINSERTSTRUCT", TVINSERTSTRUCT_DECL);
16539
+ var LVHITTESTINFO_DECL = {
16540
+ "#": "struct",
16540
16541
  pt: "i32[2]",
16541
16542
  flags: "u32",
16542
16543
  iItem: "i32",
16543
16544
  iSubItem: "i32",
16544
16545
  iGroup: "i32"
16545
- });
16546
- var LVITEMW = /* @__PURE__ */ struct("LVITEMW", {
16546
+ };
16547
+ var LVHITTESTINFO = /* @__PURE__ */ struct("LVHITTESTINFO", LVHITTESTINFO_DECL);
16548
+ var LVITEMW_DECL = {
16549
+ "#": "struct",
16547
16550
  mask: "u32",
16548
16551
  iItem: "i32",
16549
16552
  iSubItem: "i32",
@@ -16559,8 +16562,10 @@ var LVITEMW = /* @__PURE__ */ struct("LVITEMW", {
16559
16562
  puColumns: "<>ptr",
16560
16563
  piColFmt: "<>ptr",
16561
16564
  iGroup: "i32"
16562
- });
16563
- var LVCOLUMNW = /* @__PURE__ */ struct("LVCOLUMNW", {
16565
+ };
16566
+ var LVITEMW = /* @__PURE__ */ struct("LVITEMW", LVITEMW_DECL);
16567
+ var LVCOLUMNW_DECL = {
16568
+ "#": "struct",
16564
16569
  mask: "u32",
16565
16570
  fmt: "i32",
16566
16571
  cx: "i32",
@@ -16572,23 +16577,8 @@ var LVCOLUMNW = /* @__PURE__ */ struct("LVCOLUMNW", {
16572
16577
  cxMin: "i32",
16573
16578
  cxDefault: "i32",
16574
16579
  cxIdeal: "i32"
16575
- });
16576
- var MSG = /* @__PURE__ */ struct("MSG", {
16577
- hwnd: "<HWND>ptr",
16578
- message: "u32",
16579
- wParam: "<>ptr",
16580
- lParam: "<>ptr",
16581
- time: "u32",
16582
- pt: POINT.__struct
16583
- });
16584
- var PAINTSTRUCT = /* @__PURE__ */ struct("PAINTSTRUCT", {
16585
- hdc: "<HDC>ptr",
16586
- fErase: "i32",
16587
- rcPaint: RECT.__struct,
16588
- fRestore: "i32",
16589
- fIncUpdate: "i32",
16590
- rgbReserved: "u8[32]"
16591
- });
16580
+ };
16581
+ var LVCOLUMNW = /* @__PURE__ */ struct("LVCOLUMNW", LVCOLUMNW_DECL);
16592
16582
 
16593
16583
  // _build/lib/windows/user32.js
16594
16584
  var b = (name, sig, encoders) => bind("user32.dll", name, sig, encoders);
@@ -16622,7 +16612,6 @@ import * as os4 from "os";
16622
16612
 
16623
16613
  // _build/lib/windows/gdi32.js
16624
16614
  var b2 = (name, sig, encoders) => bind("gdi32.dll", name, sig, encoders);
16625
- var POINTArr = structArray(POINT);
16626
16615
  var DeleteObject = /* @__PURE__ */ b2("DeleteObject", "<HGDIOBJ>ptr -> i32");
16627
16616
  var GetDeviceCaps = /* @__PURE__ */ b2("GetDeviceCaps", "<HDC>ptr! i32@DeviceCap -> i32");
16628
16617
  var CreateFontIndirect = /* @__PURE__ */ b2("CreateFontIndirectW", "<LOGFONTW>ptr -> <HGDIOBJ>ptr", { LOGFONTW });