quickwin 1.2.1 → 2.0.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 +3 -3
- package/README.md +21 -24
- package/examples/PdfCanvas.js +8 -37
- package/examples/PdfCanvas.tsx +11 -41
- package/examples/exec_server.js +20054 -1423
- package/examples/exec_server.tsx +489 -0
- package/examples/exec_server_worker.js +383 -33
- package/examples/exec_server_worker.ts +408 -30
- package/examples/pdf_preview2.js +31 -73
- package/examples/pdf_preview2.ts +33 -76
- package/examples/pdf_viewer.js +1496 -616
- package/examples/pdf_viewer.tsx +23 -64
- package/examples/setres.js +22 -47
- package/examples/setres.ts +23 -57
- package/examples/test_gallery.js +1491 -525
- package/examples/test_react_lazy.js +1455 -500
- package/examples/test_react_listbox.js +1454 -499
- package/examples/test_root_window.js +1450 -495
- package/examples/test_tab.js +1455 -500
- package/lib/abort.js +70 -0
- package/lib/abort.ts +69 -0
- package/lib/certs.js +214 -0
- package/lib/certs.ts +224 -0
- package/lib/exec-log.js +15 -0
- package/lib/exec-log.ts +30 -0
- package/lib/fetch.js +37 -4
- package/lib/fetch.ts +35 -4
- package/lib/ffi/bind.js +352 -0
- package/lib/ffi/bind.ts +442 -0
- package/lib/ffi/ctype.js +168 -0
- package/lib/ffi/ctype.ts +331 -0
- package/lib/ffi/index.js +6 -0
- package/lib/ffi/index.ts +6 -0
- package/lib/ffi/struct.js +412 -0
- package/lib/ffi/struct.ts +664 -0
- package/lib/http-common.js +43 -5
- package/lib/http-common.ts +48 -6
- package/lib/http-server.js +187 -29
- package/lib/http-server.ts +177 -26
- package/lib/react-qw/components/DateTimePicker.js +20 -33
- package/lib/react-qw/components/Input.js +3 -10
- package/lib/react-qw/components/Link.js +7 -22
- package/lib/react-qw/components/ListView.js +80 -141
- package/lib/react-qw/components/PathPicker.js +36 -80
- package/lib/react-qw/components/ScrollView.js +15 -8
- package/lib/react-qw/components/Slider.js +2 -1
- package/lib/react-qw/components/Tab.js +15 -20
- package/lib/react-qw/components/Tooltip.js +21 -20
- package/lib/react-qw/components/TreeView.js +14 -47
- package/lib/react-qw/index.js +4 -2
- package/lib/react-qw/index.ts +4 -2
- package/lib/react-qw/nmhdr.js +5 -0
- package/lib/react-qw/nmhdr.ts +7 -0
- package/lib/react-qw/props.js +7 -2
- package/lib/react-qw/props.ts +7 -3
- package/lib/react-qw/reconciler.js +23 -13
- package/lib/react-qw/reconciler.ts +22 -13
- package/lib/text-measure.js +18 -35
- package/lib/text-measure.ts +20 -37
- package/lib/websocket.js +12 -2
- package/lib/websocket.ts +15 -2
- package/lib/windows/comctl32.js +18 -0
- package/lib/windows/comctl32.ts +20 -0
- package/lib/windows/comdlg32.js +7 -0
- package/lib/windows/comdlg32.ts +9 -0
- package/lib/windows/gdi32.js +90 -0
- package/lib/windows/gdi32.ts +97 -0
- package/lib/windows/kernel32.js +66 -0
- package/lib/windows/kernel32.ts +76 -0
- package/lib/windows/ntdll.js +8 -0
- package/lib/windows/ntdll.ts +10 -0
- package/lib/windows/ole32.js +7 -0
- package/lib/windows/ole32.ts +9 -0
- package/lib/windows/shell32.js +11 -0
- package/lib/windows/shell32.ts +14 -0
- package/lib/windows/structs.js +384 -0
- package/lib/windows/structs.ts +422 -0
- package/lib/windows/user32.js +469 -0
- package/lib/windows/user32.ts +502 -0
- package/package.json +1 -1
- package/quickwin.d.ts +22 -33
- package/quickwin_const.d.ts +1 -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/bench_ffi_callraw.js +236 -0
- package/test/bench_ffi_callraw.ts +236 -0
- package/test/bench_ffi_overhead.js +139 -0
- package/test/bench_ffi_overhead.ts +141 -0
- package/test/bench_sendmessage.js +104 -0
- package/test/bench_sendmessage.ts +100 -0
- package/test/bench_sendmessage_nonnull.js +187 -0
- package/test/bench_sendmessage_nonnull.ts +188 -0
- package/test/run.js +14 -4
- package/test/run.ts +15 -5
- package/test/test_basic_fetch.js +8 -0
- package/test/test_basic_fetch.ts +9 -0
- package/test/test_ffi.js +33 -47
- package/test/test_ffi.ts +41 -60
- package/test/test_ffi_abi.js +235 -0
- package/test/test_ffi_abi.ts +218 -0
- package/test/test_ffi_bind.js +572 -0
- package/test/test_ffi_bind.ts +597 -0
- package/test/test_ffi_struct.js +745 -0
- package/test/test_ffi_struct.ts +798 -0
- package/test/test_ffi_struct_layout.js +495 -0
- package/test/test_ffi_struct_layout.ts +543 -0
- package/test/test_ffi_user32.js +103 -0
- package/test/test_ffi_user32.ts +113 -0
- package/test/test_ffi_windows.js +101 -0
- package/test/test_ffi_windows.ts +113 -0
- package/test/test_helper.js +8 -1
- package/test/test_helper.ts +9 -1
- package/test/test_http_import.js +18 -0
- package/test/test_http_import.ts +19 -0
- package/test/test_http_server.js +73 -1
- package/test/test_http_server.ts +75 -1
- package/test/test_ipv6.js +2 -2
- package/test/test_ipv6.ts +2 -2
- package/test/test_net_fetch.js +70 -8
- package/test/test_net_fetch.ts +69 -7
- package/test/test_net_websocket.js +1 -1
- package/test/test_net_websocket.ts +1 -1
- package/test/test_react_complex.js +1465 -510
- package/test/test_react_counter.js +1455 -500
- package/test/test_react_flex.js +1475 -513
- package/test/test_react_hidden.js +1458 -503
- package/test/test_react_listview_link.js +1455 -500
- package/test/test_react_notify.js +18534 -0
- package/test/test_react_render.js +1455 -500
- package/test/test_wolfssl_read.js +3 -2
- package/test/test_wolfssl_read.ts +3 -1
- package/test/test_worker_net.js +35 -17
- package/test/test_worker_net.ts +27 -15
- package/tsconfig.json +1 -1
- package/examples/exec_server.ts +0 -80
|
@@ -104,8 +104,9 @@ export const suite = {
|
|
|
104
104
|
if (d instanceof ArrayBuffer) {
|
|
105
105
|
sawArray = true;
|
|
106
106
|
total += d.byteLength;
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
// Keep draining after the body is complete: the point of
|
|
108
|
+
// this suite is the no-data/EOF contract, so a full body
|
|
109
|
+
// must not short-circuit the read that would observe null.
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
if (total >= EXPECTED)
|
|
@@ -99,7 +99,9 @@ export const suite = {
|
|
|
99
99
|
if (d instanceof ArrayBuffer) {
|
|
100
100
|
sawArray = true
|
|
101
101
|
total += d.byteLength
|
|
102
|
-
|
|
102
|
+
// Keep draining after the body is complete: the point of
|
|
103
|
+
// this suite is the no-data/EOF contract, so a full body
|
|
104
|
+
// must not short-circuit the read that would observe null.
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
if (total >= EXPECTED) finish()
|
package/test/test_worker_net.js
CHANGED
|
@@ -27,25 +27,43 @@ export const suite = {
|
|
|
27
27
|
catch (e) {
|
|
28
28
|
t.checkTrue('worker creation failed: ' + e, false);
|
|
29
29
|
}
|
|
30
|
+
// Retry across jsdelivr's official CDN hosts: a dropped connection
|
|
31
|
+
// on a slow CI network must not be reported as a TLS regression.
|
|
30
32
|
t.section('npm-package');
|
|
31
33
|
let worker3;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
34
|
+
const NPM_HOSTS = ['cdn.jsdelivr.net', 'fastly.jsdelivr.net', 'gcore.jsdelivr.net'];
|
|
35
|
+
let workerOk = false;
|
|
36
|
+
for (const host of NPM_HOSTS) {
|
|
37
|
+
for (let attempt = 0; attempt < 3 && !workerOk; attempt++) {
|
|
38
|
+
try {
|
|
39
|
+
const { data: r3 } = await new Promise((resolve, reject) => {
|
|
40
|
+
worker3 = new os.Worker('https://' + host + '/npm/quickwin/test/worker_module.js');
|
|
41
|
+
const timer = os.setTimeout(() => reject(new Error('timeout')), 15000);
|
|
42
|
+
worker3.onmessage = (e) => {
|
|
43
|
+
os.clearTimeout(timer);
|
|
44
|
+
resolve({ worker: worker3, data: e.data });
|
|
45
|
+
};
|
|
46
|
+
worker3.postMessage({ type: 'start' });
|
|
47
|
+
});
|
|
48
|
+
t.check('npm worker message type', 'result', r3.type);
|
|
49
|
+
t.check('npm worker imported value', 42, r3.value);
|
|
50
|
+
worker3.postMessage({ type: 'done' });
|
|
51
|
+
worker3.onmessage = null;
|
|
52
|
+
workerOk = true;
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
if (worker3) {
|
|
56
|
+
worker3.onmessage = null;
|
|
57
|
+
worker3 = null;
|
|
58
|
+
}
|
|
59
|
+
if (attempt === 2 && host === NPM_HOSTS[NPM_HOSTS.length - 1])
|
|
60
|
+
t.checkTrue('npm worker failed: ' + e, false);
|
|
61
|
+
else
|
|
62
|
+
os.sleep(500);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (workerOk)
|
|
66
|
+
break;
|
|
49
67
|
}
|
|
50
68
|
}
|
|
51
69
|
};
|
package/test/test_worker_net.ts
CHANGED
|
@@ -31,24 +31,36 @@ export const suite = {
|
|
|
31
31
|
t.checkTrue('worker creation failed: ' + e, false)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// Retry across jsdelivr's official CDN hosts: a dropped connection
|
|
35
|
+
// on a slow CI network must not be reported as a TLS regression.
|
|
34
36
|
t.section('npm-package')
|
|
35
37
|
let worker3: any
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
const NPM_HOSTS = ['cdn.jsdelivr.net', 'fastly.jsdelivr.net', 'gcore.jsdelivr.net']
|
|
39
|
+
let workerOk = false
|
|
40
|
+
for (const host of NPM_HOSTS) {
|
|
41
|
+
for (let attempt = 0; attempt < 3 && !workerOk; attempt++) {
|
|
42
|
+
try {
|
|
43
|
+
const { data: r3 } = await new Promise<any>((resolve, reject) => {
|
|
44
|
+
worker3 = new os.Worker('https://' + host + '/npm/quickwin/test/worker_module.js')
|
|
45
|
+
const timer = os.setTimeout(() => reject(new Error('timeout')), 15000)
|
|
46
|
+
worker3.onmessage = (e: any) => {
|
|
47
|
+
os.clearTimeout(timer)
|
|
48
|
+
resolve({ worker: worker3, data: e.data })
|
|
49
|
+
}
|
|
50
|
+
worker3.postMessage({ type: 'start' })
|
|
51
|
+
})
|
|
52
|
+
t.check('npm worker message type', 'result', r3.type)
|
|
53
|
+
t.check('npm worker imported value', 42, r3.value)
|
|
54
|
+
worker3.postMessage({ type: 'done' })
|
|
55
|
+
worker3.onmessage = null
|
|
56
|
+
workerOk = true
|
|
57
|
+
} catch (e) {
|
|
58
|
+
if (worker3) { worker3.onmessage = null; worker3 = null }
|
|
59
|
+
if (attempt === 2 && host === NPM_HOSTS[NPM_HOSTS.length - 1]) t.checkTrue('npm worker failed: ' + e, false)
|
|
60
|
+
else os.sleep(500)
|
|
43
61
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
t.check('npm worker message type', 'result', r3.type)
|
|
47
|
-
t.check('npm worker imported value', 42, r3.value)
|
|
48
|
-
worker3.postMessage({ type: 'done' })
|
|
49
|
-
worker3.onmessage = null
|
|
50
|
-
} catch (e) {
|
|
51
|
-
t.checkTrue('npm worker failed: ' + e, false)
|
|
62
|
+
}
|
|
63
|
+
if (workerOk) break
|
|
52
64
|
}
|
|
53
65
|
}
|
|
54
66
|
}
|
package/tsconfig.json
CHANGED
package/examples/exec_server.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { createServer } from '../lib/http-server.js'
|
|
2
|
-
import * as os from 'os'
|
|
3
|
-
|
|
4
|
-
// WORKER_DATA_URL 由 esbuild --define 在 build.ts 中注入(base64 data: URL)
|
|
5
|
-
declare const WORKER_DATA_URL: string
|
|
6
|
-
|
|
7
|
-
const EXEC_TIMEOUT_MS = 60_000
|
|
8
|
-
|
|
9
|
-
interface ExecResult {
|
|
10
|
-
out: Uint8Array
|
|
11
|
-
code: number
|
|
12
|
-
error: string | null
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function runInWorker(cmd: string): Promise<ExecResult> {
|
|
16
|
-
return new Promise((resolve, reject) => {
|
|
17
|
-
const worker = new os.Worker(WORKER_DATA_URL)
|
|
18
|
-
const id = 1
|
|
19
|
-
let settled = false
|
|
20
|
-
let timer: ReturnType<typeof os.setTimeout>
|
|
21
|
-
|
|
22
|
-
const finish = (fn: () => void) => {
|
|
23
|
-
if (settled) return
|
|
24
|
-
settled = true
|
|
25
|
-
os.clearTimeout(timer)
|
|
26
|
-
worker.onmessage = null
|
|
27
|
-
fn()
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
timer = os.setTimeout(() => {
|
|
31
|
-
finish(() => reject(new Error('exec timeout')))
|
|
32
|
-
}, EXEC_TIMEOUT_MS)
|
|
33
|
-
|
|
34
|
-
worker.onmessage = (e) => {
|
|
35
|
-
const msg = e.data as { type: string; id: number; out?: Uint8Array; code?: number; error?: string | null }
|
|
36
|
-
if (msg.type !== 'result' || msg.id !== id) return
|
|
37
|
-
finish(() => resolve({ out: msg.out ?? new Uint8Array(0), code: msg.code ?? -1, error: msg.error ?? null }))
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
worker.postMessage({ type: 'run', id, cmd })
|
|
42
|
-
} catch (ex) {
|
|
43
|
-
finish(() => reject(ex instanceof Error ? ex : new Error(String(ex))))
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const server = createServer(async (req) => {
|
|
49
|
-
const path = new URL(req.url).pathname
|
|
50
|
-
if (req.method === 'GET' && (path === '/' || path === '/health')) {
|
|
51
|
-
return new Response('ok', { headers: { 'Content-Type': 'text/plain' } })
|
|
52
|
-
}
|
|
53
|
-
if (req.method === 'POST' && path === '/exec') {
|
|
54
|
-
const body = await req.json() as { cmd: string }
|
|
55
|
-
try {
|
|
56
|
-
const { out, code, error } = await runInWorker(body.cmd)
|
|
57
|
-
if (error) {
|
|
58
|
-
return new Response(JSON.stringify({ error }), {
|
|
59
|
-
status: 500,
|
|
60
|
-
headers: { 'Content-Type': 'application/json' }
|
|
61
|
-
})
|
|
62
|
-
}
|
|
63
|
-
return new Response(out, {
|
|
64
|
-
headers: {
|
|
65
|
-
'Content-Type': 'application/octet-stream',
|
|
66
|
-
'X-Exit-Code': String(code),
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
} catch (ex) {
|
|
70
|
-
return new Response(JSON.stringify({ error: String(ex) }), {
|
|
71
|
-
status: 504,
|
|
72
|
-
headers: { 'Content-Type': 'application/json' }
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return new Response('Not Found', { status: 404 })
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
const rc = server.listen(8080, '0.0.0.0')
|
|
80
|
-
console.log('listen rc=' + rc + ' addr=' + JSON.stringify(server.address()))
|