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.
- package/README.en.md +8 -8
- package/README.md +6 -7
- package/examples/{exec_server.js → execd.js} +618 -228
- package/examples/execd.tsx +798 -0
- package/examples/execd_worker.js +122 -0
- package/examples/execd_worker.ts +127 -0
- package/examples/pdf_viewer.js +100 -111
- package/examples/test_gallery.js +100 -111
- package/examples/test_react_lazy.js +96 -109
- package/examples/test_react_listbox.js +96 -109
- package/examples/test_root_window.js +96 -109
- package/examples/test_tab.js +96 -109
- package/lib/ffi/ctype.ts +3 -1
- package/lib/ffi/struct.js +23 -7
- package/lib/ffi/struct.ts +50 -23
- package/lib/http-server.js +1 -1
- package/lib/http-server.ts +1 -1
- package/lib/windows/gdi32.js +1 -1
- package/lib/windows/gdi32.ts +1 -1
- package/lib/windows/structs.js +176 -92
- package/lib/windows/structs.ts +216 -92
- package/package.json +1 -1
- package/quickwin_const.d.ts +26 -0
- package/qwin-nowasm-x86.exe +0 -0
- package/qwin-nowasm.exe +0 -0
- package/qwin-x86.exe +0 -0
- package/qwin.exe +0 -0
- package/test/test_ffi_bind.js +5 -3
- package/test/test_ffi_bind.ts +6 -4
- package/test/test_ffi_struct.js +58 -24
- package/test/test_ffi_struct.ts +55 -25
- package/test/test_gdi_draw.js +1 -1
- package/test/test_gdi_draw.ts +1 -1
- package/test/test_react_complex.js +96 -109
- package/test/test_react_counter.js +96 -109
- package/test/test_react_flex.js +96 -109
- package/test/test_react_hidden.js +96 -109
- package/test/test_react_listview_link.js +96 -109
- package/test/test_react_notify.js +96 -109
- package/test/test_react_render.js +96 -109
- package/examples/exec_server.tsx +0 -489
- package/examples/exec_server_worker.js +0 -395
- package/examples/exec_server_worker.ts +0 -417
- package/examples/setres.js +0 -79
- 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
|
+
}
|
package/examples/pdf_viewer.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
16465
|
-
|
|
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:
|
|
16468
|
-
}
|
|
16469
|
-
var
|
|
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
|
|
16478
|
-
|
|
16479
|
-
|
|
16480
|
-
|
|
16481
|
-
|
|
16482
|
-
|
|
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
|
|
16491
|
-
|
|
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
|
|
16504
|
-
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
16538
|
-
}
|
|
16539
|
-
var
|
|
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
|
|
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
|
|
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
|
|
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 });
|