quickwin 2.2.0 → 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.
- package/README.en.md +7 -7
- package/README.md +7 -7
- package/constants.ts +1063 -0
- package/enum_map.d.ts +129 -0
- package/examples/PdfCanvas.js +2 -2
- package/examples/PdfCanvas.tsx +3 -2
- package/examples/{execd.js → execd/main.js} +563 -122
- package/examples/execd/tray.js +192 -0
- package/examples/{execd_worker.js → execd/worker.js} +7 -7
- package/examples/pdf_preview2.js +46 -46
- package/examples/pdf_preview2.ts +55 -54
- package/examples/pdf_viewer.js +34 -19
- package/examples/pdf_viewer.tsx +6 -5
- package/examples/test_gallery.js +35 -20
- package/examples/test_gallery.tsx +9 -8
- package/examples/test_react_lazy.js +34 -19
- package/examples/test_react_lazy.tsx +7 -6
- package/examples/test_react_listbox.js +34 -19
- package/examples/test_react_listbox.tsx +8 -7
- package/examples/test_root_window.js +34 -19
- package/examples/test_root_window.tsx +5 -5
- package/examples/test_tab.js +34 -19
- package/examples/test_tab.tsx +7 -6
- package/examples/tray_demo.js +8 -8
- package/examples/tray_demo.tsx +9 -8
- package/lib/dumpRects.js +2 -2
- package/lib/dumpRects.ts +3 -2
- package/lib/fetch.js +15 -15
- package/lib/fetch.ts +16 -15
- package/lib/ffi/bind.js +3 -3
- package/lib/ffi/bind.ts +3 -3
- package/lib/http-server.js +4 -4
- package/lib/http-server.ts +5 -4
- package/lib/react-qw/components/Button.js +2 -2
- package/lib/react-qw/components/CheckBox.js +4 -4
- package/lib/react-qw/components/ComboBox.js +10 -10
- package/lib/react-qw/components/DateTimePicker.js +12 -12
- package/lib/react-qw/components/Input.js +7 -7
- package/lib/react-qw/components/Link.js +4 -4
- package/lib/react-qw/components/ListBox.js +12 -12
- package/lib/react-qw/components/ListView.js +35 -35
- package/lib/react-qw/components/PathPicker.js +3 -3
- package/lib/react-qw/components/ProgressBar.js +4 -4
- package/lib/react-qw/components/RadioButton.js +4 -4
- package/lib/react-qw/components/ScrollView.js +28 -28
- package/lib/react-qw/components/Slider.js +11 -11
- package/lib/react-qw/components/Tab.js +10 -10
- package/lib/react-qw/components/Tooltip.js +8 -8
- package/lib/react-qw/components/TreeView.js +20 -20
- package/lib/react-qw/index.js +5 -5
- package/lib/react-qw/index.ts +6 -5
- package/lib/react-qw/props.js +4 -4
- package/lib/react-qw/props.ts +5 -4
- package/lib/react-qw/reconciler.js +10 -10
- package/lib/react-qw/reconciler.ts +11 -10
- package/lib/text-measure.js +3 -3
- package/lib/text-measure.ts +4 -3
- package/lib/websocket.js +17 -17
- package/lib/websocket.ts +18 -17
- package/lib/windows/advapi32.js +7 -7
- package/lib/windows/advapi32.ts +7 -7
- package/lib/windows/gdi32.js +16 -16
- package/lib/windows/gdi32.ts +16 -16
- package/lib/windows/kernel32.js +41 -2
- package/lib/windows/kernel32.ts +45 -2
- package/lib/windows/shell32.js +24 -3
- package/lib/windows/shell32.ts +27 -4
- package/lib/windows/structs.js +54 -0
- package/lib/windows/structs.ts +63 -1
- package/lib/windows/user32.js +18 -6
- package/lib/windows/user32.ts +18 -6
- package/lib/windows/winspool.js +3 -3
- package/lib/windows/winspool.ts +3 -3
- package/package.json +4 -3
- package/quickwin.d.ts +32 -10
- 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 +7 -7
- package/test/test_ffi_bind.ts +8 -8
- package/test/test_ffi_struct.js +2 -2
- package/test/test_ffi_struct.ts +3 -3
- package/test/test_ffi_windows.js +1 -1
- package/test/test_ffi_windows.ts +1 -1
- package/test/test_files.js +7 -7
- package/test/test_files.ts +8 -8
- package/test/test_gdi_draw.js +51 -51
- package/test/test_gdi_draw.ts +57 -57
- package/test/test_http_server.js +3 -3
- package/test/test_http_server.ts +4 -3
- package/test/test_ipv6.js +3 -3
- package/test/test_ipv6.ts +4 -3
- package/test/test_net_event.js +3 -3
- package/test/test_net_event.ts +4 -3
- package/test/test_printer.js +4 -4
- package/test/test_printer.ts +5 -5
- package/test/test_react_complex.js +36 -21
- package/test/test_react_counter.js +34 -19
- package/test/test_react_flex.js +36 -21
- package/test/test_react_hidden.js +34 -19
- package/test/test_react_listview_link.js +35 -20
- package/test/test_react_notify.js +52 -37
- package/test/test_react_render.js +34 -19
- package/test/test_registry.js +6 -6
- package/test/test_registry.ts +8 -8
- package/test/test_wolfssl_read.js +8 -8
- package/test/test_wolfssl_read.ts +9 -8
- package/examples/execd.tsx +0 -798
- package/examples/execd_worker.ts +0 -127
- package/quickwin_const.d.ts +0 -1063
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 /*
|
|
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 /*
|
|
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 /*
|
|
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 /*
|
|
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 /*
|
|
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 /*
|
|
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 /*
|
|
236
|
-
err !== 3 /*
|
|
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 /*
|
|
255
|
-
err === 3 /*
|
|
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 /*
|
|
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 /*
|
|
342
|
-
err === 3 /*
|
|
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 /*
|
|
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 /*
|
|
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 &
|
|
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,
|
|
191
|
+
wolfssl.wolfSSL_CTX_set_verify(ctx, VerifyMode.SSL_VERIFY_NONE)
|
|
191
192
|
} else {
|
|
192
|
-
wolfssl.wolfSSL_CTX_set_verify(ctx,
|
|
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,
|
|
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 &
|
|
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 ===
|
|
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 !==
|
|
221
|
-
err !==
|
|
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 ===
|
|
238
|
-
err ===
|
|
239
|
-
if (n === 0 || err ===
|
|
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 ===
|
|
319
|
-
err ===
|
|
320
|
-
if (n === 0 || err ===
|
|
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 &
|
|
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/http-server.js
CHANGED
|
@@ -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 /*
|
|
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 /*
|
|
210
|
+
if (event.lNetworkEvents & 1 /* FdEvent.FD_READ */)
|
|
211
211
|
onRead(c);
|
|
212
|
-
if (event.lNetworkEvents & 2 /*
|
|
212
|
+
if (event.lNetworkEvents & 2 /* FdEvent.FD_WRITE */)
|
|
213
213
|
flushQueue(c);
|
|
214
|
-
if (event.lNetworkEvents & 32 /*
|
|
214
|
+
if (event.lNetworkEvents & 32 /* FdEvent.FD_CLOSE */) {
|
|
215
215
|
onRead(c);
|
|
216
216
|
abortConn(c);
|
|
217
217
|
closeConn(c);
|
package/lib/http-server.ts
CHANGED
|
@@ -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 &
|
|
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 &
|
|
233
|
-
if (event.lNetworkEvents &
|
|
234
|
-
if (event.lNetworkEvents &
|
|
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)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from 'react';
|
|
3
3
|
export const Button = forwardRef(({ children, onClick, style, disabled }, ref) => {
|
|
4
|
-
return (_jsx("w", { type: "BUTTON", text: children != null ? (Array.isArray(children) ? children.join('') : String(children)) : '', ws: 268435456 /*
|
|
5
|
-
if (e.msg === 514 /*
|
|
4
|
+
return (_jsx("w", { type: "BUTTON", text: children != null ? (Array.isArray(children) ? children.join('') : String(children)) : '', ws: 268435456 /* WindowStyle.VISIBLE */, style: style, disabled: disabled, ref: ref, onEvent: (e) => {
|
|
5
|
+
if (e.msg === 514 /* WmMsg.LBUTTONUP */)
|
|
6
6
|
onClick?.();
|
|
7
7
|
} }));
|
|
8
8
|
});
|
|
@@ -10,17 +10,17 @@ export const CheckBox = forwardRef(({ checked: controlledChecked, defaultChecked
|
|
|
10
10
|
const h = cbRef.current;
|
|
11
11
|
if (!h)
|
|
12
12
|
return;
|
|
13
|
-
gui.SendMessage(h, 241 /*
|
|
13
|
+
gui.SendMessage(h, 241 /* ButtonMsg.SETCHECK */, displayChecked ? 1 /* ButtonCheckState.CHECKED */ : 0 /* ButtonCheckState.UNCHECKED */, 0);
|
|
14
14
|
}, [displayChecked]);
|
|
15
|
-
return (_jsx("w", { type: "BUTTON", text: label ?? '', ws: 268435456 /*
|
|
15
|
+
return (_jsx("w", { type: "BUTTON", text: label ?? '', ws: 268435456 /* WindowStyle.VISIBLE */ | 3 /* ButtonStyle.AUTOCHECKBOX */, style: style, disabled: disabled, ref: (h) => {
|
|
16
16
|
cbRef.current = h;
|
|
17
17
|
if (typeof ref === 'function')
|
|
18
18
|
ref(h);
|
|
19
19
|
else if (ref)
|
|
20
20
|
ref.current = h;
|
|
21
21
|
}, onEvent: (e) => {
|
|
22
|
-
if (e.msg === 514 /*
|
|
23
|
-
const newChecked = gui.SendMessage(e.hwnd, 240 /*
|
|
22
|
+
if (e.msg === 514 /* WmMsg.LBUTTONUP */) {
|
|
23
|
+
const newChecked = gui.SendMessage(e.hwnd, 240 /* ButtonMsg.GETCHECK */, 0, 0) !== 0;
|
|
24
24
|
if (newChecked !== displayChecked) {
|
|
25
25
|
if (!isControlled)
|
|
26
26
|
setInternalChecked(newChecked);
|
|
@@ -6,32 +6,32 @@ export const ComboBox = forwardRef(({ items, selectedIndex: controlledIndex, def
|
|
|
6
6
|
const isControlled = controlledIndex !== undefined;
|
|
7
7
|
const sel = isControlled ? controlledIndex : internalIndex;
|
|
8
8
|
const cbRef = useRef(null);
|
|
9
|
-
const cbWs = 268435456 /*
|
|
10
|
-
| 3 /*
|
|
9
|
+
const cbWs = 268435456 /* WindowStyle.VISIBLE */ | 8388608 /* WindowStyle.BORDER */
|
|
10
|
+
| 3 /* ComboBoxStyle.DROPDOWNLIST */ | 512 /* ComboBoxStyle.HASSTRINGS */;
|
|
11
11
|
useEffect(() => {
|
|
12
12
|
const h = cbRef.current;
|
|
13
13
|
if (!h)
|
|
14
14
|
return;
|
|
15
|
-
gui.SendMessage(h, 331 /*
|
|
15
|
+
gui.SendMessage(h, 331 /* ComboBoxMsg.RESETCONTENT */, 0, 0);
|
|
16
16
|
for (const item of items)
|
|
17
|
-
gui.SendMessage(h, 323 /*
|
|
17
|
+
gui.SendMessage(h, 323 /* ComboBoxMsg.ADDSTRING */, 0, item);
|
|
18
18
|
if (sel >= 0 && sel < items.length)
|
|
19
|
-
gui.SendMessage(h, 334 /*
|
|
19
|
+
gui.SendMessage(h, 334 /* ComboBoxMsg.SETCURSEL */, sel, 0);
|
|
20
20
|
}, [items]);
|
|
21
21
|
useEffect(() => {
|
|
22
22
|
const h = cbRef.current;
|
|
23
23
|
if (h)
|
|
24
|
-
gui.SendMessage(h, 334 /*
|
|
24
|
+
gui.SendMessage(h, 334 /* ComboBoxMsg.SETCURSEL */, sel, 0);
|
|
25
25
|
}, [sel]);
|
|
26
|
-
return (_jsx("w", { type: "STATIC", ws: 268435456 /*
|
|
27
|
-
if (e.msg !== 273 /*
|
|
26
|
+
return (_jsx("w", { type: "STATIC", ws: 268435456 /* WindowStyle.VISIBLE */ | 33554432 /* WindowStyle.CLIPCHILDREN */, style: { ...style, flexDirection: 'column', alignItems: 'stretch' }, ref: ref, onEvent: (e) => {
|
|
27
|
+
if (e.msg !== 273 /* WmMsg.COMMAND */)
|
|
28
28
|
return;
|
|
29
29
|
const code = (e.wParam >> 16) & 0xFFFF;
|
|
30
|
-
if (code === 1 /*
|
|
30
|
+
if (code === 1 /* CbnCode.SELCHANGE */) {
|
|
31
31
|
const h = cbRef.current;
|
|
32
32
|
if (!h)
|
|
33
33
|
return;
|
|
34
|
-
const newSel = gui.SendMessage(h, 327 /*
|
|
34
|
+
const newSel = gui.SendMessage(h, 327 /* ComboBoxMsg.GETCURSEL */, 0, 0);
|
|
35
35
|
if (newSel !== sel && newSel >= 0) {
|
|
36
36
|
if (!isControlled)
|
|
37
37
|
setInternalIndex(newSel);
|
|
@@ -24,15 +24,15 @@ const DateTimePicker = forwardRef(function DateTimePicker({ value, onChange, def
|
|
|
24
24
|
const dpRef = useRef(null);
|
|
25
25
|
const onChangeRef = useRef(onChange);
|
|
26
26
|
onChangeRef.current = onChange;
|
|
27
|
-
let dpStyle = 268435456 /*
|
|
27
|
+
let dpStyle = 268435456 /* WindowStyle.VISIBLE */ | 8388608 /* WindowStyle.BORDER */;
|
|
28
28
|
if (format === 'long')
|
|
29
|
-
dpStyle |= 4 /*
|
|
29
|
+
dpStyle |= 4 /* DtStyle.LONGDATEFORMAT */;
|
|
30
30
|
else if (format === 'time')
|
|
31
|
-
dpStyle |= 9 /*
|
|
31
|
+
dpStyle |= 9 /* DtStyle.TIMEFORMAT */;
|
|
32
32
|
if (updown)
|
|
33
|
-
dpStyle |= 1 /*
|
|
33
|
+
dpStyle |= 1 /* DtStyle.UPDOWN */;
|
|
34
34
|
if (allowNone)
|
|
35
|
-
dpStyle |= 2 /*
|
|
35
|
+
dpStyle |= 2 /* DtStyle.SHOWNONE */;
|
|
36
36
|
useEffect(() => {
|
|
37
37
|
const h = dpRef.current;
|
|
38
38
|
if (!h)
|
|
@@ -40,10 +40,10 @@ const DateTimePicker = forwardRef(function DateTimePicker({ value, onChange, def
|
|
|
40
40
|
const d = effectiveDate;
|
|
41
41
|
if (d) {
|
|
42
42
|
const buf = dateToSysTimeBuf(d);
|
|
43
|
-
gui.SendMessage(h, 4098 /*
|
|
43
|
+
gui.SendMessage(h, 4098 /* DtMsg.SETSYSTEMTIME */, 0 /* DtFlag.GDT_VALID */, buf.ptr);
|
|
44
44
|
}
|
|
45
45
|
else {
|
|
46
|
-
gui.SendMessage(h, 4098 /*
|
|
46
|
+
gui.SendMessage(h, 4098 /* DtMsg.SETSYSTEMTIME */, 1 /* DtFlag.GDT_NONE */, 0);
|
|
47
47
|
}
|
|
48
48
|
}, [effectiveDate]);
|
|
49
49
|
useEffect(() => {
|
|
@@ -56,16 +56,16 @@ const DateTimePicker = forwardRef(function DateTimePicker({ value, onChange, def
|
|
|
56
56
|
if (cr) {
|
|
57
57
|
const w = cr.right - cr.left;
|
|
58
58
|
const hh = cr.bottom - cr.top;
|
|
59
|
-
gui.SendMessage(h, 5 /*
|
|
59
|
+
gui.SendMessage(h, 5 /* WmMsg.SIZE */, 0, (hh << 16) | w);
|
|
60
60
|
}
|
|
61
61
|
}, []);
|
|
62
|
-
return (_jsx("w", { type: "STATIC", ws: 268435456 /*
|
|
63
|
-
if (e.msg === 78 /*
|
|
62
|
+
return (_jsx("w", { type: "STATIC", ws: 268435456 /* WindowStyle.VISIBLE */ | 33554432 /* WindowStyle.CLIPCHILDREN */, style: { ...style, flexDirection: 'column', alignItems: 'stretch' }, ref: ref, onEvent: (e) => {
|
|
63
|
+
if (e.msg === 78 /* WmMsg.NOTIFY */) {
|
|
64
64
|
const code = nmCode(e.lParam);
|
|
65
|
-
if (code === -759 /*
|
|
65
|
+
if (code === -759 /* DtNotifyCode.DATETIMECHANGE */) {
|
|
66
66
|
// NMDATETIMECHANGE: NMHDR + DWORD dwFlags + SYSTEMTIME st
|
|
67
67
|
const { dwFlags, st } = NMDATETIMECHANGE.decode(e.lParam);
|
|
68
|
-
if (dwFlags === 1 /*
|
|
68
|
+
if (dwFlags === 1 /* DtFlag.GDT_NONE */) {
|
|
69
69
|
if (!isControlled)
|
|
70
70
|
setInternalDate(null);
|
|
71
71
|
onChangeRef.current?.(null);
|
|
@@ -7,21 +7,21 @@ export const Input = forwardRef(({ value: controlledValue, defaultValue = '', on
|
|
|
7
7
|
const isControlled = controlledValue !== undefined;
|
|
8
8
|
const displayValue = isControlled ? controlledValue : internalValue;
|
|
9
9
|
const inputRef = useRef(null);
|
|
10
|
-
let ws = 268435456 /*
|
|
10
|
+
let ws = 268435456 /* WindowStyle.VISIBLE */ | 8388608 /* WindowStyle.BORDER */;
|
|
11
11
|
if (multiline)
|
|
12
|
-
ws |= 4 /*
|
|
12
|
+
ws |= 4 /* EditStyle.MULTILINE */ | 64 /* EditStyle.AUTOVSCROLL */ | 2097152 /* WindowStyle.VSCROLL */;
|
|
13
13
|
if (readonly)
|
|
14
|
-
ws |= 2048 /*
|
|
14
|
+
ws |= 2048 /* EditStyle.READONLY */;
|
|
15
15
|
if (number)
|
|
16
|
-
ws |= 8192 /*
|
|
16
|
+
ws |= 8192 /* EditStyle.NUMBER */;
|
|
17
17
|
if (password)
|
|
18
|
-
ws |= 32 /*
|
|
18
|
+
ws |= 32 /* EditStyle.PASSWORD */ | 128 /* EditStyle.AUTOHSCROLL */;
|
|
19
19
|
useEffect(() => {
|
|
20
20
|
const h = inputRef.current;
|
|
21
21
|
if (!h || !placeholder)
|
|
22
22
|
return;
|
|
23
23
|
const buf = WCHAR.encode(placeholder);
|
|
24
|
-
gui.SendMessage(h, 5377 /*
|
|
24
|
+
gui.SendMessage(h, 5377 /* EditMsg.SETCUEBANNER */, 1, buf.ptr);
|
|
25
25
|
}, [placeholder]);
|
|
26
26
|
return (_jsx("w", { type: "EDIT", text: displayValue, ws: ws, style: style, disabled: disabled, ref: (h) => {
|
|
27
27
|
inputRef.current = h;
|
|
@@ -30,7 +30,7 @@ export const Input = forwardRef(({ value: controlledValue, defaultValue = '', on
|
|
|
30
30
|
else if (ref)
|
|
31
31
|
ref.current = h;
|
|
32
32
|
}, onEvent: (e) => {
|
|
33
|
-
if (e.msg === 258 /*
|
|
33
|
+
if (e.msg === 258 /* WmMsg.CHAR */) {
|
|
34
34
|
const h = inputRef.current;
|
|
35
35
|
if (!h)
|
|
36
36
|
return;
|
|
@@ -16,13 +16,13 @@ const Link = forwardRef(function Link({ href, children, onClick, style }, ref) {
|
|
|
16
16
|
return;
|
|
17
17
|
InvalidateRect(h, NULL, 1);
|
|
18
18
|
}, [linkText]);
|
|
19
|
-
return (_jsx("w", { type: "STATIC", ws: 268435456 /*
|
|
20
|
-
if (e.msg === 78 /*
|
|
19
|
+
return (_jsx("w", { type: "STATIC", ws: 268435456 /* WindowStyle.VISIBLE */ | 33554432 /* WindowStyle.CLIPCHILDREN */, style: { ...style, flexDirection: 'column', alignItems: 'stretch' }, ref: ref, onEvent: (e) => {
|
|
20
|
+
if (e.msg === 78 /* WmMsg.NOTIFY */) {
|
|
21
21
|
const code = nmCode(e.lParam);
|
|
22
|
-
if (code === -2 /*
|
|
22
|
+
if (code === -2 /* SysLinkNotifyCode.CLICK */ || code === -4 /* SysLinkNotifyCode.RETURN */) {
|
|
23
23
|
onClickRef.current?.(NMLINK.decode(e.lParam).item.szUrl);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
}, children: _jsx("w", { type: "SysLink", ws: 268435456 /*
|
|
26
|
+
}, children: _jsx("w", { type: "SysLink", ws: 268435456 /* WindowStyle.VISIBLE */ | 65536 /* WindowStyle.TABSTOP */, text: linkText, style: { flexGrow: 1 }, ref: (h) => { linkRef.current = h; } }) }));
|
|
27
27
|
});
|
|
28
28
|
export { Link };
|
|
@@ -7,35 +7,35 @@ export const ListBox = forwardRef(({ items, selectedIndex: controlledIndex, defa
|
|
|
7
7
|
const sel = isControlled ? controlledIndex : internalIndex;
|
|
8
8
|
const lbRef = useRef(null);
|
|
9
9
|
useImperativeHandle(ref, () => lbRef.current);
|
|
10
|
-
const lbWs = 268435456 /*
|
|
11
|
-
| 64 /*
|
|
12
|
-
| (sort ? 2 /*
|
|
10
|
+
const lbWs = 268435456 /* WindowStyle.VISIBLE */ | 8388608 /* WindowStyle.BORDER */ | 2097152 /* WindowStyle.VSCROLL */
|
|
11
|
+
| 64 /* ListBoxStyle.HASSTRINGS */ | 1 /* ListBoxStyle.NOTIFY */ | 256 /* ListBoxStyle.NOINTEGRALHEIGHT */
|
|
12
|
+
| (sort ? 2 /* ListBoxStyle.SORT */ : 0);
|
|
13
13
|
useEffect(() => {
|
|
14
14
|
const h = lbRef.current;
|
|
15
15
|
if (!h)
|
|
16
16
|
return;
|
|
17
|
-
gui.SendMessage(h, 388 /*
|
|
17
|
+
gui.SendMessage(h, 388 /* LbMsg.RESETCONTENT */, 0, 0);
|
|
18
18
|
for (const item of items)
|
|
19
|
-
gui.SendMessage(h, 384 /*
|
|
19
|
+
gui.SendMessage(h, 384 /* LbMsg.ADDSTRING */, 0, item);
|
|
20
20
|
if (sel >= 0 && sel < items.length)
|
|
21
|
-
gui.SendMessage(h, 390 /*
|
|
21
|
+
gui.SendMessage(h, 390 /* LbMsg.SETCURSEL */, sel, 0);
|
|
22
22
|
if (scrollToBottom && items.length > 0)
|
|
23
|
-
gui.SendMessage(h, 407 /*
|
|
23
|
+
gui.SendMessage(h, 407 /* LbMsg.SETTOPINDEX */, items.length - 1, 0);
|
|
24
24
|
}, [items]);
|
|
25
25
|
useEffect(() => {
|
|
26
26
|
const h = lbRef.current;
|
|
27
27
|
if (h)
|
|
28
|
-
gui.SendMessage(h, 390 /*
|
|
28
|
+
gui.SendMessage(h, 390 /* LbMsg.SETCURSEL */, sel, 0);
|
|
29
29
|
}, [sel]);
|
|
30
|
-
return (_jsx("w", { type: "STATIC", ws: 268435456 /*
|
|
31
|
-
if (e.msg !== 273 /*
|
|
30
|
+
return (_jsx("w", { type: "STATIC", ws: 268435456 /* WindowStyle.VISIBLE */ | 33554432 /* WindowStyle.CLIPCHILDREN */, style: { ...style, flexDirection: 'column', alignItems: 'stretch' }, onEvent: (e) => {
|
|
31
|
+
if (e.msg !== 273 /* WmMsg.COMMAND */)
|
|
32
32
|
return;
|
|
33
33
|
const code = (e.wParam >> 16) & 0xFFFF;
|
|
34
|
-
if (code === 1 /*
|
|
34
|
+
if (code === 1 /* LbnCode.SELCHANGE */) {
|
|
35
35
|
const h = lbRef.current;
|
|
36
36
|
if (!h)
|
|
37
37
|
return;
|
|
38
|
-
const newSel = gui.SendMessage(h, 392 /*
|
|
38
|
+
const newSel = gui.SendMessage(h, 392 /* LbMsg.GETCURSEL */, 0, 0);
|
|
39
39
|
if (newSel !== sel && newSel >= 0) {
|
|
40
40
|
if (!isControlled)
|
|
41
41
|
setInternalIndex(newSel);
|