quickwin 3.0.0 → 3.0.2
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 -0
- package/README.md +2 -0
- package/lib/abort.d.ts +21 -0
- package/lib/assert.d.ts +2 -0
- package/lib/bitmap.d.ts +7 -0
- package/lib/cache-utils.d.ts +6 -0
- package/lib/certs.d.ts +1 -0
- package/lib/dpi.d.ts +9 -0
- package/lib/dumpRects.d.ts +2 -0
- package/lib/exec-log.d.ts +23 -0
- package/lib/fetch.d.ts +4 -0
- package/lib/ffi/bind.d.ts +70 -0
- package/lib/ffi/ctype.d.ts +117 -0
- package/lib/ffi/index.d.ts +2 -0
- package/lib/ffi/struct.d.ts +174 -0
- package/lib/http-common.d.ts +143 -0
- package/lib/http-server.d.ts +59 -0
- package/lib/polyfill.d.ts +22 -0
- package/lib/react-qw/components/Button.d.ts +9 -0
- package/lib/react-qw/components/CheckBox.d.ts +11 -0
- package/lib/react-qw/components/ComboBox.d.ts +11 -0
- package/lib/react-qw/components/DateTimePicker.d.ts +15 -0
- package/lib/react-qw/components/Input.d.ts +15 -0
- package/lib/react-qw/components/Link.d.ts +12 -0
- package/lib/react-qw/components/ListBox.d.ts +13 -0
- package/lib/react-qw/components/ListView.d.ts +37 -0
- package/lib/react-qw/components/PathPicker.d.ts +23 -0
- package/lib/react-qw/components/ProgressBar.d.ts +9 -0
- package/lib/react-qw/components/RadioButton.d.ts +11 -0
- package/lib/react-qw/components/ScrollView.d.ts +9 -0
- package/lib/react-qw/components/Slider.d.ts +12 -0
- package/lib/react-qw/components/Tab.d.ts +14 -0
- package/lib/react-qw/components/Tooltip.d.ts +7 -0
- package/lib/react-qw/components/TreeView.d.ts +18 -0
- package/lib/react-qw/components/index.d.ts +16 -0
- package/lib/react-qw/index.d.ts +24 -0
- package/lib/react-qw/layout.d.ts +29 -0
- package/lib/react-qw/nmhdr.d.ts +1 -0
- package/lib/react-qw/props.d.ts +2 -0
- package/lib/react-qw/reconciler.d.ts +21 -0
- package/lib/stream.d.ts +20 -0
- package/lib/text-codec.d.ts +39 -0
- package/lib/text-measure.d.ts +14 -0
- package/lib/url.d.ts +54 -0
- package/lib/websocket.d.ts +73 -0
- package/lib/windows/{advapi32.ts → advapi32.d.ts} +6 -21
- package/lib/windows/comctl32.d.ts +14 -0
- package/lib/windows/comdlg32.d.ts +4 -0
- package/lib/windows/{gdi32.ts → gdi32.d.ts} +161 -98
- package/lib/windows/{kernel32.ts → kernel32.d.ts} +138 -115
- package/lib/windows/{msimg32.ts → msimg32.d.ts} +11 -14
- package/lib/windows/ntdll.d.ts +5 -0
- package/lib/windows/ole32.d.ts +3 -0
- package/lib/windows/{psapi.ts → psapi.d.ts} +9 -18
- package/lib/windows/{shell32.ts → shell32.d.ts} +25 -24
- package/lib/windows/structs.d.ts +3141 -0
- package/lib/windows/{user32.ts → user32.d.ts} +196 -193
- package/lib/windows/version.d.ts +27 -0
- package/lib/windows/{winspool.ts → winspool.d.ts} +18 -32
- package/package.json +15 -8
- 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/examples/PdfCanvas.js +0 -38
- package/examples/PdfCanvas.tsx +0 -54
- package/examples/execd/main.js +0 -23379
- package/examples/execd/tray.js +0 -192
- package/examples/execd/worker.js +0 -122
- package/examples/pdf_preview2.js +0 -398
- package/examples/pdf_preview2.ts +0 -353
- package/examples/pdf_viewer.js +0 -22515
- package/examples/pdf_viewer.tsx +0 -228
- package/examples/test_gallery.js +0 -18692
- package/examples/test_gallery.tsx +0 -291
- package/examples/test_react_lazy.js +0 -18560
- package/examples/test_react_lazy.tsx +0 -65
- package/examples/test_react_listbox.js +0 -18562
- package/examples/test_react_listbox.tsx +0 -73
- package/examples/test_root_window.js +0 -18532
- package/examples/test_root_window.tsx +0 -41
- package/examples/test_tab.js +0 -18563
- package/examples/test_tab.tsx +0 -77
- package/examples/tray_demo.js +0 -86
- package/examples/tray_demo.tsx +0 -89
- package/lib/abort.ts +0 -69
- package/lib/assert.ts +0 -7
- package/lib/bitmap.ts +0 -39
- package/lib/cache-utils.ts +0 -40
- package/lib/certs.ts +0 -258
- package/lib/dpi.ts +0 -31
- package/lib/dumpRects.ts +0 -34
- package/lib/exec-log.ts +0 -30
- package/lib/fetch.ts +0 -589
- package/lib/ffi/bind.ts +0 -540
- package/lib/ffi/ctype.ts +0 -371
- package/lib/ffi/index.ts +0 -6
- package/lib/ffi/struct.ts +0 -780
- package/lib/http-common.ts +0 -441
- package/lib/http-server.ts +0 -604
- package/lib/polyfill.ts +0 -171
- package/lib/react-qw/components/index.ts +0 -17
- package/lib/react-qw/index.ts +0 -96
- package/lib/react-qw/layout.ts +0 -111
- package/lib/react-qw/nmhdr.ts +0 -7
- package/lib/react-qw/props.ts +0 -41
- package/lib/react-qw/reconciler.ts +0 -379
- package/lib/stream.ts +0 -22
- package/lib/text-codec.ts +0 -171
- package/lib/text-measure.ts +0 -44
- package/lib/url.ts +0 -201
- package/lib/websocket.ts +0 -600
- package/lib/windows/comctl32.ts +0 -20
- package/lib/windows/comdlg32.ts +0 -10
- package/lib/windows/ntdll.ts +0 -11
- package/lib/windows/ole32.ts +0 -9
- package/lib/windows/structs.ts +0 -807
- package/lib/windows/version.ts +0 -35
- package/test/add.wasm +0 -0
- package/test/bench_ffi_callraw.js +0 -235
- package/test/bench_ffi_callraw.ts +0 -235
- package/test/bench_ffi_overhead.js +0 -139
- package/test/bench_ffi_overhead.ts +0 -141
- package/test/bench_sendmessage.js +0 -104
- package/test/bench_sendmessage.ts +0 -100
- package/test/bench_sendmessage_nonnull.js +0 -187
- package/test/bench_sendmessage_nonnull.ts +0 -188
- package/test/complex.wasm +0 -0
- package/test/complex_imports.wasm +0 -0
- package/test/debug/http_server_e2e.js +0 -31
- package/test/debug/minwasm.js +0 -52
- package/test/debug/mupdf_debug.js +0 -86
- package/test/debug/wasm.js +0 -122
- package/test/debug/wasm_export_debug.js +0 -54
- package/test/debug/wasm_names.js +0 -36
- package/test/example.pdf +0 -0
- package/test/global_imports.wasm +0 -0
- package/test/import_func.wasm +0 -0
- package/test/imports.wasm +0 -0
- package/test/mupdf-cdn.js +0 -40
- package/test/mupdf-cdn.ts +0 -43
- package/test/run.js +0 -111
- package/test/run.ts +0 -116
- package/test/sjlj.wasm +0 -0
- package/test/test_basic.js +0 -7
- package/test/test_basic.ts +0 -9
- package/test/test_basic_fetch.js +0 -63
- package/test/test_basic_fetch.ts +0 -59
- package/test/test_brotli.js +0 -48
- package/test/test_brotli.ts +0 -52
- package/test/test_fetch_cache.js +0 -169
- package/test/test_fetch_cache.ts +0 -187
- package/test/test_ffi.js +0 -157
- package/test/test_ffi.ts +0 -170
- package/test/test_ffi_abi.js +0 -290
- package/test/test_ffi_abi.ts +0 -274
- package/test/test_ffi_array.js +0 -116
- package/test/test_ffi_array.ts +0 -141
- package/test/test_ffi_bind.js +0 -656
- package/test/test_ffi_bind.ts +0 -670
- package/test/test_ffi_struct.js +0 -779
- package/test/test_ffi_struct.ts +0 -828
- package/test/test_ffi_struct_layout.js +0 -495
- package/test/test_ffi_struct_layout.ts +0 -543
- package/test/test_ffi_user32.js +0 -103
- package/test/test_ffi_user32.ts +0 -113
- package/test/test_ffi_windows.js +0 -172
- package/test/test_ffi_windows.ts +0 -187
- package/test/test_files.js +0 -102
- package/test/test_files.ts +0 -121
- package/test/test_frame_encoding.js +0 -128
- package/test/test_frame_encoding.ts +0 -132
- package/test/test_gdi_draw.js +0 -681
- package/test/test_gdi_draw.ts +0 -725
- package/test/test_helper.js +0 -91
- package/test/test_helper.ts +0 -88
- package/test/test_http_import.js +0 -96
- package/test/test_http_import.ts +0 -93
- package/test/test_http_server.js +0 -214
- package/test/test_http_server.ts +0 -211
- package/test/test_import_dir.js +0 -4
- package/test/test_import_dir.ts +0 -5
- package/test/test_ipv6.js +0 -134
- package/test/test_ipv6.ts +0 -130
- package/test/test_jsx.js +0 -1314
- package/test/test_meta_url.js +0 -3
- package/test/test_meta_url.ts +0 -4
- package/test/test_mupdf_render.js +0 -51
- package/test/test_mupdf_render.ts +0 -55
- package/test/test_mupdf_twice.js +0 -62
- package/test/test_mupdf_twice.ts +0 -65
- package/test/test_mupdf_wasm.js +0 -39
- package/test/test_mupdf_wasm.ts +0 -32
- package/test/test_net_event.js +0 -57
- package/test/test_net_event.ts +0 -56
- package/test/test_net_fetch.js +0 -384
- package/test/test_net_fetch.ts +0 -373
- package/test/test_net_websocket.js +0 -180
- package/test/test_net_websocket.ts +0 -164
- package/test/test_polyfill.js +0 -144
- package/test/test_polyfill.ts +0 -159
- package/test/test_printer.js +0 -137
- package/test/test_printer.ts +0 -148
- package/test/test_proc.js +0 -141
- package/test/test_proc.ts +0 -163
- package/test/test_react_complex.js +0 -18678
- package/test/test_react_counter.js +0 -18555
- package/test/test_react_flex.js +0 -18871
- package/test/test_react_hidden.js +0 -18560
- package/test/test_react_listview_link.js +0 -18590
- package/test/test_react_notify.js +0 -18797
- package/test/test_react_render.js +0 -18550
- package/test/test_registry.js +0 -74
- package/test/test_registry.ts +0 -95
- package/test/test_sysinfo.js +0 -122
- package/test/test_sysinfo.ts +0 -141
- package/test/test_url.js +0 -173
- package/test/test_url.ts +0 -183
- package/test/test_wasm_basic.js +0 -85
- package/test/test_wasm_basic.ts +0 -73
- package/test/test_wasm_import_global.js +0 -41
- package/test/test_wasm_import_global.ts +0 -45
- package/test/test_wasm_sjlj.js +0 -145
- package/test/test_wasm_sjlj.ts +0 -125
- package/test/test_wasm_types.js +0 -97
- package/test/test_wasm_types.ts +0 -124
- package/test/test_wolfssl_read.js +0 -203
- package/test/test_wolfssl_read.ts +0 -184
- package/test/test_worker.js +0 -21
- package/test/test_worker.ts +0 -24
- package/test/test_worker_concurrent.js +0 -45
- package/test/test_worker_concurrent.ts +0 -56
- package/test/test_worker_data_url.js +0 -46
- package/test/test_worker_data_url.ts +0 -51
- package/test/test_worker_fetch.js +0 -26
- package/test/test_worker_fetch.ts +0 -27
- package/test/test_worker_net.js +0 -69
- package/test/test_worker_net.ts +0 -66
- package/test/test_worker_wasm_concurrent.js +0 -44
- package/test/test_worker_wasm_concurrent.ts +0 -45
- package/test/types.wasm +0 -0
- package/test/worker_fetch.js +0 -13
- package/test/worker_fetch.ts +0 -13
- package/test/worker_helper.js +0 -1
- package/test/worker_helper.ts +0 -1
- package/test/worker_http.js +0 -18
- package/test/worker_http.ts +0 -20
- package/test/worker_import_lib.js +0 -12
- package/test/worker_import_lib.ts +0 -13
- package/test/worker_module.js +0 -16
- package/test/worker_module.ts +0 -17
- package/test/worker_wasm_concurrent.js +0 -22
- package/test/worker_wasm_concurrent.ts +0 -22
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
// 一次性性能 bench:FFI 签名 '!' 标注的调用时 0 检验成本(同函数多臂对照 + A/A 噪声底)
|
|
2
|
-
// 不入 CI。用法:make js 后 POST /exec {"cmd":"qwin.exe test/bench_sendmessage_nonnull.js"}
|
|
3
|
-
// 臂(同一 proc 各自 bind,唯一变量是 '!'):
|
|
4
|
-
// A1 base '<HWND>ptr u32 <>ptr <>ptr -> <>ptr' 基线
|
|
5
|
-
// A2 ctrl '<HWND>ptr u32 <>ptr <>ptr -> <>ptr' 与 A1 完全同签名——两臂差值 = 机器噪声底
|
|
6
|
-
// B arg! '<HWND>ptr! u32 <>ptr <>ptr -> <>ptr' + 参数位 arg#1 0 检查
|
|
7
|
-
// C ret! '<HWND>ptr! u32 <>ptr <>ptr -> <>ptr!' + 返回位 0 检查(仅非零返回场景)
|
|
8
|
-
// 方法学(前两轮教训):批量缩到 50k/样本 → 臂序每 ~650ms 轮转一次,抵消 QEMU 调度抖动;
|
|
9
|
-
// S1/S3 各臂 30 样本取 median(对 GC/调度离群稳健);A2-A1 是效应检验的参照带——
|
|
10
|
-
// B/A 落在 A2/A 带内即「低于噪声底,不可测」。'!' 边际 = 每标注位 1 次整数 === 比较
|
|
11
|
-
// (endsWith 无条件跑、所有臂共模),理论 ≪ 轮噪声。
|
|
12
|
-
// C 臂标了返回 '!',撞真实 0 即 throw —— 先用 A1 探各场景原始返回值,非零才让 C 进。
|
|
13
|
-
// 全部消息发自有窗口(直调 wndproc)。结束必须 DestroyWindow + std.exit。
|
|
14
|
-
import * as std from 'std'
|
|
15
|
-
import * as gui from 'gui'
|
|
16
|
-
import { bind, WCHAR } from '../lib/ffi/bind.js'
|
|
17
|
-
import { PtrArrayBuffer } from '../lib/ffi/ctype.js'
|
|
18
|
-
|
|
19
|
-
const BATCH = 50_000 // 每样本批量(~650ms)——小批量快轮转,去相关调度抖动
|
|
20
|
-
const ROUNDS = 30 // S1/S3 每臂样本数(30 × 3-4 臂 ≈ 60-80s/suite)
|
|
21
|
-
const N_S2 = 50_000
|
|
22
|
-
const ROUNDS_S2 = 7
|
|
23
|
-
const WM_NULL = 0x0000
|
|
24
|
-
const WM_SETTEXT = 0x000c
|
|
25
|
-
const WM_GETTEXT = 0x000d
|
|
26
|
-
|
|
27
|
-
// median(离群稳健)供 micro 与 suite 共用
|
|
28
|
-
const med = (t: number[]): number => {
|
|
29
|
-
const s = [...t].sort((x, y) => x - y)
|
|
30
|
-
const m = s.length >> 1
|
|
31
|
-
return s.length % 2 ? s[m]! : (s[m - 1]! + s[m]!) / 2
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// S0:'!' 边际操作本身(1 次整数 === 比较 + 分支)的解释器成本——FFI 层噪声
|
|
35
|
-
// ±400~900ns/call 盖住了 12.5μs 调用上的 ns 级效应,这里绕开 ffiCall 直接量单检查。
|
|
36
|
-
// flag 必须是模块级可变量:QuickJS 编译期会常量折叠字面量,折叠掉就测不到了。
|
|
37
|
-
let microFlag = true
|
|
38
|
-
const MICRO_N = 100_000_000
|
|
39
|
-
function microLoop(): number {
|
|
40
|
-
const t0 = Date.now()
|
|
41
|
-
let hits = 0
|
|
42
|
-
for (let i = 0; i < MICRO_N; i++)
|
|
43
|
-
if (microFlag && i === 0) hits++
|
|
44
|
-
const dt = Date.now() - t0
|
|
45
|
-
if (hits !== (microFlag ? 1 : 0)) throw new Error('micro sanity failed: hits=' + hits)
|
|
46
|
-
return dt
|
|
47
|
-
}
|
|
48
|
-
function microSuite(): void {
|
|
49
|
-
step('suite: S0 micro 0-check interpreter cost (n=' + String(MICRO_N) + ')')
|
|
50
|
-
microFlag = true; microLoop()
|
|
51
|
-
microFlag = false; microLoop()
|
|
52
|
-
const ts: number[] = []
|
|
53
|
-
const fs: number[] = []
|
|
54
|
-
for (let r = 0; r < 5; r++) {
|
|
55
|
-
// 奇偶交叉起跑顺序(同原 bench 方法)
|
|
56
|
-
if (r % 2 === 0) {
|
|
57
|
-
microFlag = true; ts.push(microLoop())
|
|
58
|
-
microFlag = false; fs.push(microLoop())
|
|
59
|
-
} else {
|
|
60
|
-
microFlag = false; fs.push(microLoop())
|
|
61
|
-
microFlag = true; ts.push(microLoop())
|
|
62
|
-
}
|
|
63
|
-
step(' round ' + String(r) + ': check=' + String(ts[ts.length - 1]) +
|
|
64
|
-
'ms base=' + String(fs[fs.length - 1]) + 'ms')
|
|
65
|
-
}
|
|
66
|
-
const ns = (ms: number) => (ms * 1e6 / MICRO_N).toFixed(2)
|
|
67
|
-
const tmed = med(ts), fmed = med(fs)
|
|
68
|
-
step(' ** median: check=' + ns(tmed) + 'ns/op base=' + ns(fmed) +
|
|
69
|
-
'ns/op ==> per-check cost=' + ((tmed - fmed) * 1e6 / MICRO_N).toFixed(2) + 'ns')
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// 文件日志(cwd=Z:\quickwin,宿主机 _build/bench_nonnull_log.txt 可实时读)——exec 只在
|
|
73
|
-
// 进程退出后回包,挂了靠它定位卡点
|
|
74
|
-
const log = std.open('bench_nonnull_log.txt', 'w')
|
|
75
|
-
function step(msg: string): void {
|
|
76
|
-
std.printf('%s\n', msg)
|
|
77
|
-
if (log) { log.puts(msg + '\n'); log.flush() }
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
step('stage: imports ok')
|
|
81
|
-
|
|
82
|
-
const winRaw = gui.CreateWindow('STATIC', 'bench-title', 0, 0, 0, 20, 20, null, null)
|
|
83
|
-
if (!winRaw) throw new Error('CreateWindow(STATIC) failed')
|
|
84
|
-
const win: gui.HWND = winRaw
|
|
85
|
-
step('stage: window created')
|
|
86
|
-
|
|
87
|
-
const SIG = '<HWND>ptr u32 <>ptr <>ptr -> <>ptr'
|
|
88
|
-
const fA1 = bind('user32.dll', 'SendMessageW', SIG)
|
|
89
|
-
const fA2 = bind('user32.dll', 'SendMessageW', SIG) // A/A 对照:同签名二绑 = 噪声底
|
|
90
|
-
const fB = bind('user32.dll', 'SendMessageW', '<HWND>ptr! u32 <>ptr <>ptr -> <>ptr')
|
|
91
|
-
const fC = bind('user32.dll', 'SendMessageW', '<HWND>ptr! u32 <>ptr <>ptr -> <>ptr!')
|
|
92
|
-
|
|
93
|
-
// 各 BindFn 结构等价 → 收敛到一个可传参的函数型(循环内统一走局部参数,开销对齐)
|
|
94
|
-
type SM = (h: gui.HWND, msg: number, w: number, l: number) => number
|
|
95
|
-
|
|
96
|
-
const TEXT = 'bench'
|
|
97
|
-
const buf = new PtrArrayBuffer<'WCHAR'>(64)
|
|
98
|
-
|
|
99
|
-
// C 臂可行性探针:A1 读各场景原始返回值,撞 0 的场景不进 C('!' 会 throw)。
|
|
100
|
-
// S1 的 WM_NULL 走 DefWindowProc 预期返 0 → C 不进 S1 是预期而非缺测。
|
|
101
|
-
const retS1 = fA1(win, WM_NULL, 0, 0x1234)
|
|
102
|
-
const retS2 = fA1(win, WM_SETTEXT, 0, WCHAR.encode(TEXT).ptr)
|
|
103
|
-
const retS3 = fA1(win, WM_GETTEXT, 64, buf.ptr)
|
|
104
|
-
step('probe ret: S1=' + String(retS1) + ' S2=' + String(retS2) + ' S3=' + String(retS3) +
|
|
105
|
-
' (C arm only enters nonzero scenes)')
|
|
106
|
-
|
|
107
|
-
function run1(f: SM): number {
|
|
108
|
-
const t0 = Date.now()
|
|
109
|
-
for (let i = 0; i < BATCH; i++) f(win, WM_NULL, 0, 0x1234)
|
|
110
|
-
return Date.now() - t0
|
|
111
|
-
}
|
|
112
|
-
function run2(f: SM): number {
|
|
113
|
-
const t0 = Date.now()
|
|
114
|
-
for (let i = 0; i < N_S2; i++) {
|
|
115
|
-
const w = WCHAR.encode(TEXT)
|
|
116
|
-
f(win, WM_SETTEXT, 0, w.ptr)
|
|
117
|
-
}
|
|
118
|
-
return Date.now() - t0
|
|
119
|
-
}
|
|
120
|
-
function run3(f: SM): number {
|
|
121
|
-
const t0 = Date.now()
|
|
122
|
-
for (let i = 0; i < BATCH; i++) f(win, WM_GETTEXT, 64, buf.ptr)
|
|
123
|
-
return Date.now() - t0
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
type Arm = { label: string; fn: () => number }
|
|
127
|
-
|
|
128
|
-
function suite(name: string, n: number, rounds: number, arms: Arm[]): void {
|
|
129
|
-
step('suite: ' + name + ' warmup')
|
|
130
|
-
for (const a of arms) a.fn() // 预热各 1 轮
|
|
131
|
-
const times: number[][] = arms.map(() => [])
|
|
132
|
-
for (let r = 0; r < rounds; r++) {
|
|
133
|
-
// 臂序按 r 轮转起跑,抵消顺序性偏置(温度/调度漂移)
|
|
134
|
-
for (let k = 0; k < arms.length; k++) {
|
|
135
|
-
const i = (r + k) % arms.length
|
|
136
|
-
times[i]!.push(arms[i]!.fn())
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
// 每轮原始数据只 dump 前 3 轮(30 轮全打没意义,log 只留诊断线索)
|
|
140
|
-
for (let r = 0; r < Math.min(rounds, 3); r++) {
|
|
141
|
-
step(' round ' + String(r) + ': ' +
|
|
142
|
-
arms.map((a, i) => a.label + '=' + String(times[i]![r]) + 'ms').join(' '))
|
|
143
|
-
}
|
|
144
|
-
const ns = (ms: number) => (ms * 1e6 / n).toFixed(1)
|
|
145
|
-
// median 是主指标(离群稳健);min 留作与前两轮/原 bench 的可比项
|
|
146
|
-
const meds = times.map(med)
|
|
147
|
-
const mins = times.map(t => Math.min(...t))
|
|
148
|
-
step(' ** median: ' + arms.map((a, i) =>
|
|
149
|
-
a.label + '=' + ns(meds[i]!) + 'ns').join(' | '))
|
|
150
|
-
step(' min: ' + arms.map((a, i) =>
|
|
151
|
-
a.label + '=' + ns(mins[i]!) + 'ns').join(' | '))
|
|
152
|
-
for (let i = 1; i < arms.length; i++)
|
|
153
|
-
step(' vs A1: ' + arms[i]!.label + ' delta=' +
|
|
154
|
-
((meds[i]! - meds[0]!) * 1e6 / n).toFixed(1) + 'ns/call (median), ' +
|
|
155
|
-
((mins[i]! - mins[0]!) * 1e6 / n).toFixed(1) + 'ns/call (min)' +
|
|
156
|
-
(i === 1 ? ' <-- A2-A1 = NOISE FLOOR' : ''))
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const s1Arms: Arm[] = [
|
|
160
|
-
{ label: 'A1', fn: () => run1(fA1) },
|
|
161
|
-
{ label: 'A2', fn: () => run1(fA2) },
|
|
162
|
-
{ label: 'B ', fn: () => run1(fB) },
|
|
163
|
-
]
|
|
164
|
-
if (retS1 !== 0) s1Arms.push({ label: 'C ', fn: () => run1(fC) })
|
|
165
|
-
const s2Arms: Arm[] = [
|
|
166
|
-
{ label: 'A1', fn: () => run2(fA1) },
|
|
167
|
-
{ label: 'A2', fn: () => run2(fA2) },
|
|
168
|
-
{ label: 'B ', fn: () => run2(fB) },
|
|
169
|
-
]
|
|
170
|
-
if (retS2 !== 0) s2Arms.push({ label: 'C ', fn: () => run2(fC) })
|
|
171
|
-
const s3Arms: Arm[] = [
|
|
172
|
-
{ label: 'A1', fn: () => run3(fA1) },
|
|
173
|
-
{ label: 'A2', fn: () => run3(fA2) },
|
|
174
|
-
{ label: 'B ', fn: () => run3(fB) },
|
|
175
|
-
]
|
|
176
|
-
if (retS3 !== 0) s3Arms.push({ label: 'C ', fn: () => run3(fC) })
|
|
177
|
-
|
|
178
|
-
step('bench_sendmessage_nonnull: S1/S3 batch=' + String(BATCH) + '×' + String(ROUNDS) +
|
|
179
|
-
'r, S2 n=' + String(N_S2) + '×' + String(ROUNDS_S2) + 'r (median 主指标)')
|
|
180
|
-
microSuite()
|
|
181
|
-
suite('S1 WM_NULL 纯数字参数 (最灵敏测点)', BATCH, ROUNDS, s1Arms)
|
|
182
|
-
suite('S2 WM_SETTEXT 字符串 lParam (FFI 侧含 WCHAR.encode)', N_S2, ROUNDS_S2, s2Arms)
|
|
183
|
-
suite('S3 WM_GETTEXT 缓冲出参往返', BATCH, ROUNDS, s3Arms)
|
|
184
|
-
|
|
185
|
-
gui.DestroyWindow(win)
|
|
186
|
-
step('DONE')
|
|
187
|
-
if (log) log.close()
|
|
188
|
-
std.exit(0)
|
package/test/complex.wasm
DELETED
|
Binary file
|
|
Binary file
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import '../../lib/fetch.js';
|
|
2
|
-
import { createServer } from '../../lib/http-server.js';
|
|
3
|
-
import * as std from 'std';
|
|
4
|
-
const server = createServer(async (req) => {
|
|
5
|
-
const url = new URL(req.url);
|
|
6
|
-
if (url.pathname === '/echo') {
|
|
7
|
-
return new Response(JSON.stringify({ method: req.method, path: url.pathname, body: await req.text(), q: Object.fromEntries(url.searchParams) }), { headers: { 'Content-Type': 'application/json' } });
|
|
8
|
-
}
|
|
9
|
-
return new Response('hello from quickwin http-server', { headers: { 'Content-Type': 'text/plain' } });
|
|
10
|
-
});
|
|
11
|
-
const rc = server.listen(0, '127.0.0.1');
|
|
12
|
-
if (rc !== 0) {
|
|
13
|
-
console.log('listen failed');
|
|
14
|
-
std.exit(1);
|
|
15
|
-
}
|
|
16
|
-
const addr = server.address();
|
|
17
|
-
const port = addr.port;
|
|
18
|
-
console.log('server on port', port);
|
|
19
|
-
async function main() {
|
|
20
|
-
const r1 = await fetch(`http://127.0.0.1:${port}/`);
|
|
21
|
-
console.log('GET / status', r1.status, 'body:', await r1.text());
|
|
22
|
-
const r2 = await fetch(`http://127.0.0.1:${port}/echo?x=1`, {
|
|
23
|
-
method: 'POST',
|
|
24
|
-
headers: { 'Content-Type': 'text/plain' },
|
|
25
|
-
body: 'hello-body',
|
|
26
|
-
});
|
|
27
|
-
console.log('POST /echo status', r2.status, 'body:', await r2.text());
|
|
28
|
-
server.close();
|
|
29
|
-
std.exit(0);
|
|
30
|
-
}
|
|
31
|
-
main();
|
package/test/debug/minwasm.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import * as std from 'std';
|
|
2
|
-
std.printf("Hello\n");
|
|
3
|
-
function readWasmFile(path) {
|
|
4
|
-
const fp = std.open(path, 'rb');
|
|
5
|
-
if (!fp) {
|
|
6
|
-
return null;
|
|
7
|
-
}
|
|
8
|
-
fp.seek(0, 2); // SEEK_END
|
|
9
|
-
const size = fp.tell();
|
|
10
|
-
fp.seek(0, 0); // SEEK_SET
|
|
11
|
-
const buffer = new ArrayBuffer(size);
|
|
12
|
-
fp.read(buffer, 0, size);
|
|
13
|
-
fp.close();
|
|
14
|
-
return buffer;
|
|
15
|
-
}
|
|
16
|
-
const wasmBuf = readWasmFile('./complex_imports.wasm');
|
|
17
|
-
try {
|
|
18
|
-
if (!wasmBuf)
|
|
19
|
-
throw new Error('failed to load wasm');
|
|
20
|
-
const m = new WebAssembly.Module(wasmBuf);
|
|
21
|
-
console.log('imports:', WebAssembly.Module.imports(m));
|
|
22
|
-
console.log('exports:', WebAssembly.Module.exports(m));
|
|
23
|
-
const inst = new WebAssembly.Instance(m, {
|
|
24
|
-
env: {
|
|
25
|
-
log_i32: (x) => { console.log(' log_i32:', x); },
|
|
26
|
-
log_i64: (x) => { console.log(' log_i64:', x); },
|
|
27
|
-
log_f32: (x) => { console.log(' log_f32:', x); },
|
|
28
|
-
log_f64: (x) => { console.log(' log_f64:', x); },
|
|
29
|
-
op_i32: (a, b, c) => a * b + c,
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
const exp = inst.exports;
|
|
33
|
-
console.log('--- i32 ---');
|
|
34
|
-
let r = exp.run_i32(7);
|
|
35
|
-
console.log(' run_i32(7) =>', r, '(expected 75)');
|
|
36
|
-
console.log('--- i64 ---');
|
|
37
|
-
r = exp.run_i64(100000, 200000);
|
|
38
|
-
console.log(' run_i64(100000, 200000) =>', r, '(expected 300000)');
|
|
39
|
-
r = exp.run_i64(10000000000, 20000000000);
|
|
40
|
-
console.log(' run_i64(10000000000, 20000000000) =>', r, '(expected 30000000000)');
|
|
41
|
-
console.log('--- f32 ---');
|
|
42
|
-
r = exp.run_f32(3.5);
|
|
43
|
-
console.log(' run_f32(3.5) =>', r, '(expected 7.0)');
|
|
44
|
-
console.log('--- f64 ---');
|
|
45
|
-
r = exp.run_f64(2.5, 4.0);
|
|
46
|
-
console.log(' run_f64(2.5, 4.0) =>', r, '(expected 10.0)');
|
|
47
|
-
console.log('--- all done ---');
|
|
48
|
-
}
|
|
49
|
-
catch (e) {
|
|
50
|
-
console.log('ERROR:', e);
|
|
51
|
-
}
|
|
52
|
-
;
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import * as std from 'std';
|
|
2
|
-
import { MUPDF_JS_URL, preloadMupdfWasm } from '../mupdf-cdn.js';
|
|
3
|
-
await preloadMupdfWasm();
|
|
4
|
-
await import(MUPDF_JS_URL);
|
|
5
|
-
// Debug the instance exports
|
|
6
|
-
const inst = globalThis["$wasm_inst"];
|
|
7
|
-
const mod = globalThis["$wasm_mod"];
|
|
8
|
-
console.log('=== WASM Module exports (first 30) ===');
|
|
9
|
-
const modExports = WebAssembly.Module.exports(mod);
|
|
10
|
-
for (let i = 0; i < 30 && i < modExports.length; i++)
|
|
11
|
-
console.log(` ${i}: ${modExports[i].name} (${modExports[i].kind})`);
|
|
12
|
-
// Find Sf and Tf indices
|
|
13
|
-
let sf_idx = -1, tf_idx = -1;
|
|
14
|
-
for (let i = 0; i < modExports.length; i++) {
|
|
15
|
-
if (modExports[i].name === 'Sf')
|
|
16
|
-
sf_idx = i;
|
|
17
|
-
if (modExports[i].name === 'Tf')
|
|
18
|
-
tf_idx = i;
|
|
19
|
-
}
|
|
20
|
-
console.log('Sf index:', sf_idx, 'Tf index:', tf_idx);
|
|
21
|
-
console.log('instance exports Sf:', typeof inst.exports['Sf']);
|
|
22
|
-
console.log('instance exports Tf:', typeof inst.exports['Tf']);
|
|
23
|
-
// Load a simple WASM to verify bridge works
|
|
24
|
-
const fp = std.open('./test/example.pdf', 'rb');
|
|
25
|
-
if (!fp) {
|
|
26
|
-
console.log('cannot open example.pdf');
|
|
27
|
-
std.exit(1);
|
|
28
|
-
}
|
|
29
|
-
fp.seek(0, 2);
|
|
30
|
-
const size = fp.tell();
|
|
31
|
-
fp.seek(0, 0);
|
|
32
|
-
const buf = new ArrayBuffer(size);
|
|
33
|
-
fp.read(buf, 0, size);
|
|
34
|
-
fp.close();
|
|
35
|
-
console.log('\npdf size:', size);
|
|
36
|
-
// Try calling lower-level functions directly
|
|
37
|
-
const lib = globalThis["$libmupdf_wasm_Module"];
|
|
38
|
-
// First open the document
|
|
39
|
-
const wasmMemory = inst.exports['cb'];
|
|
40
|
-
console.log('WASM memory:', typeof wasmMemory, wasmMemory?.buffer?.byteLength);
|
|
41
|
-
// Create a buffer and try
|
|
42
|
-
const bufPtr = lib._wasm_malloc(size);
|
|
43
|
-
console.log('malloc buffer pointer:', bufPtr);
|
|
44
|
-
// Write PDF data into WASM memory at bufPtr...
|
|
45
|
-
const mem8 = new Uint8Array(wasmMemory.buffer);
|
|
46
|
-
for (let i = 0; i < size; i++)
|
|
47
|
-
mem8[bufPtr + i] = (new Uint8Array(buf))[i];
|
|
48
|
-
console.log('wrote pdf data to WASM memory at', bufPtr);
|
|
49
|
-
// Try opening document directly with _wasm_open_document_with_buffer
|
|
50
|
-
// Need a string for "application/pdf"
|
|
51
|
-
const magicStr = "application/pdf\x00";
|
|
52
|
-
const magicPtr = lib._wasm_malloc(magicStr.length);
|
|
53
|
-
for (let i = 0; i < magicStr.length; i++)
|
|
54
|
-
mem8[magicPtr + i] = magicStr.charCodeAt(i);
|
|
55
|
-
console.log('magic string at', magicPtr);
|
|
56
|
-
// Create a Buffer wrapper object - need to call Buffer constructor
|
|
57
|
-
// Actually let's just call the low-level function directly
|
|
58
|
-
const fz_ptr = inst.exports['Mf'](magicPtr, bufPtr); // _wasm_open_document_with_buffer
|
|
59
|
-
console.log('_wasm_open_document_with_buffer returned:', fz_ptr, typeof fz_ptr);
|
|
60
|
-
if (fz_ptr && typeof fz_ptr === 'number') {
|
|
61
|
-
// Try countPages
|
|
62
|
-
const count = inst.exports['Sf'](fz_ptr);
|
|
63
|
-
console.log('_wasm_count_pages returned:', count, typeof count);
|
|
64
|
-
// Try loadPage
|
|
65
|
-
if (typeof fz_ptr !== 'number') {
|
|
66
|
-
console.log('fz_ptr is not a number!');
|
|
67
|
-
}
|
|
68
|
-
const pagePtr = inst.exports['Tf'](fz_ptr, 0);
|
|
69
|
-
console.log('_wasm_load_page returned:', pagePtr, typeof pagePtr);
|
|
70
|
-
// Get bounds
|
|
71
|
-
// _wasm_bound_page(Sf?) - need to find this export
|
|
72
|
-
for (let i = 0; i < modExports.length; i++) {
|
|
73
|
-
if (modExports[i].name.startsWith('Uf')) {
|
|
74
|
-
console.log('Uf at index', i, '- likely _wasm_pdf_page_from_fz_page');
|
|
75
|
-
}
|
|
76
|
-
if (modExports[i].name.startsWith('Vf')) {
|
|
77
|
-
console.log('Vf at index', i);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// Try calling _wasm_pdf_page_from_fz_page (Uf)
|
|
81
|
-
const pdfPtr = inst.exports['Uf'](pagePtr);
|
|
82
|
-
console.log('_wasm_pdf_page_from_fz_page returned:', pdfPtr, typeof pdfPtr);
|
|
83
|
-
}
|
|
84
|
-
lib._wasm_free(magicPtr);
|
|
85
|
-
lib._wasm_free(bufPtr);
|
|
86
|
-
console.log('\ndone');
|
package/test/debug/wasm.js
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import * as std from 'std';
|
|
2
|
-
function readWasmFile(path) {
|
|
3
|
-
const fp = std.open(path, 'rb');
|
|
4
|
-
if (!fp)
|
|
5
|
-
return null;
|
|
6
|
-
fp.seek(0, 2);
|
|
7
|
-
const size = fp.tell();
|
|
8
|
-
fp.seek(0, 0);
|
|
9
|
-
const buffer = new ArrayBuffer(size);
|
|
10
|
-
fp.read(buffer, 0, size);
|
|
11
|
-
fp.close();
|
|
12
|
-
return buffer;
|
|
13
|
-
}
|
|
14
|
-
var ok = 0, fail = 0;
|
|
15
|
-
function check(name, expected, actual) {
|
|
16
|
-
if (typeof expected === 'number' && typeof actual === 'number') {
|
|
17
|
-
if (Math.abs(expected - actual) < 0.0001) {
|
|
18
|
-
ok++;
|
|
19
|
-
std.printf(' PASS: %s = %s\n', name, String(actual));
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
fail++;
|
|
23
|
-
std.printf(' FAIL: %s = %s (expected %s)\n', name, String(actual), String(expected));
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
else if (expected === actual) {
|
|
27
|
-
ok++;
|
|
28
|
-
std.printf(' PASS: %s = %s\n', name, String(actual));
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
fail++;
|
|
32
|
-
std.printf(' FAIL: %s = %s (expected %s)\n', name, String(actual), String(expected));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
std.printf('=== validate ===\n');
|
|
36
|
-
check('empty buffer', false, WebAssembly.validate(new Uint8Array([]).buffer));
|
|
37
|
-
check('invalid bytes', false, WebAssembly.validate(new Uint8Array([1, 2, 3]).buffer));
|
|
38
|
-
const wasmBuffer = readWasmFile('./add.wasm');
|
|
39
|
-
if (!wasmBuffer) {
|
|
40
|
-
std.printf('FAIL: cannot load add.wasm\n');
|
|
41
|
-
std.exit(1);
|
|
42
|
-
}
|
|
43
|
-
check('valid module', true, WebAssembly.validate(wasmBuffer));
|
|
44
|
-
std.printf('=== Module ===\n');
|
|
45
|
-
var module = null;
|
|
46
|
-
try {
|
|
47
|
-
module = new WebAssembly.Module(wasmBuffer);
|
|
48
|
-
check('Module constructor', true, module instanceof WebAssembly.Module);
|
|
49
|
-
}
|
|
50
|
-
catch (e) {
|
|
51
|
-
std.printf(' FAIL: Module constructor: %s\n', String(e));
|
|
52
|
-
fail++;
|
|
53
|
-
}
|
|
54
|
-
std.printf('=== Module.exports ===\n');
|
|
55
|
-
if (module) {
|
|
56
|
-
try {
|
|
57
|
-
const exps = WebAssembly.Module.exports(module);
|
|
58
|
-
check('exports count', 1, exps.length);
|
|
59
|
-
check('export name', 'add', exps[0].name);
|
|
60
|
-
check('export kind', 'function', exps[0].kind);
|
|
61
|
-
}
|
|
62
|
-
catch (e) {
|
|
63
|
-
std.printf(' FAIL: Module.exports: %s\n', String(e));
|
|
64
|
-
fail++;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
std.printf('=== Instance (add.wasm) ===\n');
|
|
68
|
-
if (module) {
|
|
69
|
-
try {
|
|
70
|
-
const instance = new WebAssembly.Instance(module);
|
|
71
|
-
const iExp = instance.exports;
|
|
72
|
-
check('Instance created', true, instance instanceof WebAssembly.Instance);
|
|
73
|
-
check('add(1, 2)', 3, iExp.add(1, 2));
|
|
74
|
-
check('add(10, 20)', 30, iExp.add(10, 20));
|
|
75
|
-
check('add(-5, 3)', -2, iExp.add(-5, 3));
|
|
76
|
-
}
|
|
77
|
-
catch (e) {
|
|
78
|
-
std.printf(' FAIL: Instance: %s\n', String(e));
|
|
79
|
-
fail++;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
std.printf('=== complex.wasm (multi exports) ===\n');
|
|
83
|
-
const complexBuffer = readWasmFile('./complex.wasm');
|
|
84
|
-
if (complexBuffer) {
|
|
85
|
-
try {
|
|
86
|
-
const cmod = new WebAssembly.Module(complexBuffer);
|
|
87
|
-
const cinst = new WebAssembly.Instance(cmod);
|
|
88
|
-
const cExp = cinst.exports;
|
|
89
|
-
check('add(3, 4)', 7, cExp.add(3, 4));
|
|
90
|
-
check('sub(10, 3)', 7, cExp.sub(10, 3));
|
|
91
|
-
check('mul(6, 7)', 42, cExp.mul(6, 7));
|
|
92
|
-
check('factorial(0)', 1, cExp.factorial(0));
|
|
93
|
-
check('factorial(5)', 120, cExp.factorial(5));
|
|
94
|
-
check('factorial(10)', 3628800, cExp.factorial(10));
|
|
95
|
-
}
|
|
96
|
-
catch (e) {
|
|
97
|
-
std.printf(' FAIL: complex.wasm: %s\n', String(e));
|
|
98
|
-
fail++;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
std.printf('=== import function support ===\n');
|
|
102
|
-
const importFuncBuffer = readWasmFile('./import_func.wasm');
|
|
103
|
-
if (importFuncBuffer) {
|
|
104
|
-
try {
|
|
105
|
-
const ifmod = new WebAssembly.Module(importFuncBuffer);
|
|
106
|
-
const importObject = {
|
|
107
|
-
env: { imported_add: (a, b) => a + b }
|
|
108
|
-
};
|
|
109
|
-
const ifinst = new WebAssembly.Instance(ifmod, importObject);
|
|
110
|
-
const ifExp = ifinst.exports;
|
|
111
|
-
check('add_via_import(3, 4)', 7, ifExp.add_via_import(3, 4));
|
|
112
|
-
check('add_via_import(10, 20)', 30, ifExp.add_via_import(10, 20));
|
|
113
|
-
check('add_via_import(-5, 3)', -2, ifExp.add_via_import(-5, 3));
|
|
114
|
-
}
|
|
115
|
-
catch (e) {
|
|
116
|
-
std.printf(' FAIL: import_func.wasm: %s\n', String(e));
|
|
117
|
-
fail++;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
std.printf('\n%d/%d tests passed\n', ok, ok + fail);
|
|
121
|
-
if (fail > 0)
|
|
122
|
-
std.exit(1);
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { fetchMupdfWasm } from '../mupdf-cdn.js';
|
|
2
|
-
const buf = await fetchMupdfWasm();
|
|
3
|
-
const module = new WebAssembly.Module(buf);
|
|
4
|
-
const exports = WebAssembly.Module.exports(module);
|
|
5
|
-
const imports = WebAssembly.Module.imports(module);
|
|
6
|
-
// List ALL export names
|
|
7
|
-
console.log(`=== All exports (${exports.length}) ===`);
|
|
8
|
-
for (let i = 0; i < exports.length; i++) {
|
|
9
|
-
if (exports[i].name === 'ul' || exports[i].name === 'tl')
|
|
10
|
-
console.log(` ${i}: ${exports[i].name} (${exports[i].kind}) *** FOUND ***`);
|
|
11
|
-
}
|
|
12
|
-
// Check last 20 exports
|
|
13
|
-
console.log(`\n=== Last 20 exports ===`);
|
|
14
|
-
for (let i = Math.max(0, exports.length - 20); i < exports.length; i++)
|
|
15
|
-
console.log(` ${i}: ${exports[i].name} (${exports[i].kind})`);
|
|
16
|
-
// Check if ul/tl are import functions
|
|
17
|
-
console.log(`\n=== Imports (${imports.length}) ===`);
|
|
18
|
-
for (let i = 0; i < imports.length; i++) {
|
|
19
|
-
if (imports[i].name === 'ul' || imports[i].name === 'tl')
|
|
20
|
-
console.log(` ${i}: ${imports[i].module}.${imports[i].name}`);
|
|
21
|
-
}
|
|
22
|
-
// Now try to call simple exports and see if exec_env is the issue
|
|
23
|
-
console.log(`\n=== Direct instance call test ===`);
|
|
24
|
-
const importObj = { a: {} };
|
|
25
|
-
for (const imp of imports) {
|
|
26
|
-
if (!importObj[imp.module])
|
|
27
|
-
importObj[imp.module] = {};
|
|
28
|
-
if (imp.kind === 'function') {
|
|
29
|
-
importObj[imp.module][imp.name] = () => 0;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
// Test calling db, eb sequentially
|
|
33
|
-
const inst = new WebAssembly.Instance(module, importObj);
|
|
34
|
-
const exp = inst.exports;
|
|
35
|
-
console.log('1. calling db()...');
|
|
36
|
-
exp['db']();
|
|
37
|
-
console.log('2. calling db() again...');
|
|
38
|
-
exp['db']();
|
|
39
|
-
console.log('3. calling eb()...');
|
|
40
|
-
try {
|
|
41
|
-
exp['eb']();
|
|
42
|
-
console.log(' eb() succeeded');
|
|
43
|
-
}
|
|
44
|
-
catch (e) {
|
|
45
|
-
console.log(' eb() failed:', e);
|
|
46
|
-
}
|
|
47
|
-
console.log('4. calling fb(100)...');
|
|
48
|
-
try {
|
|
49
|
-
const r = exp['fb'](100);
|
|
50
|
-
console.log(' fb(100) =', r);
|
|
51
|
-
}
|
|
52
|
-
catch (e) {
|
|
53
|
-
console.log(' fb(100) failed:', e);
|
|
54
|
-
}
|
package/test/debug/wasm_names.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { fetchMupdfWasm } from '../mupdf-cdn.js';
|
|
2
|
-
// Fetch the mupdf-wasm binary over HTTPS (process-wide HTTP cache applies)
|
|
3
|
-
const buf = await fetchMupdfWasm();
|
|
4
|
-
// Check exports for Tf
|
|
5
|
-
const module = new WebAssembly.Module(buf);
|
|
6
|
-
const exports = WebAssembly.Module.exports(module);
|
|
7
|
-
const imports = WebAssembly.Module.imports(module);
|
|
8
|
-
// Look for Tf specifically
|
|
9
|
-
let foundTf = false;
|
|
10
|
-
for (const e of exports) {
|
|
11
|
-
if (e.name === 'Tf') {
|
|
12
|
-
console.log('FOUND Tf in exports');
|
|
13
|
-
foundTf = true;
|
|
14
|
-
break;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
if (!foundTf)
|
|
18
|
-
console.log('Tf NOT in exports');
|
|
19
|
-
// Check a few nearby names used in assignWasmExports
|
|
20
|
-
const wanted = ['Tf', 'Uf', 'Vf', 'Wf', 'Xf', 'Yf', 'Sf', 'Rf', 'Qf', 'Pf', 'Of', 'Nf'];
|
|
21
|
-
const found = [];
|
|
22
|
-
const missing = [];
|
|
23
|
-
for (const w of wanted) {
|
|
24
|
-
if (exports.some(e => e.name === w))
|
|
25
|
-
found.push(w);
|
|
26
|
-
else
|
|
27
|
-
missing.push(w);
|
|
28
|
-
}
|
|
29
|
-
console.log('found:', found.join(', '));
|
|
30
|
-
console.log('missing:', missing.join(', '));
|
|
31
|
-
// Count exports
|
|
32
|
-
console.log('total exports:', exports.length);
|
|
33
|
-
console.log('total imports:', imports.length);
|
|
34
|
-
// List first 30 export names
|
|
35
|
-
for (let i = 0; i < 30 && i < exports.length; i++)
|
|
36
|
-
console.log(' export', i, '=', exports[i].name);
|
package/test/example.pdf
DELETED
|
Binary file
|
package/test/global_imports.wasm
DELETED
|
Binary file
|
package/test/import_func.wasm
DELETED
|
Binary file
|
package/test/imports.wasm
DELETED
|
Binary file
|
package/test/mupdf-cdn.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// ── mupdf-wasm CDN loading ──
|
|
2
|
-
//
|
|
3
|
-
// The runtime loads mupdf from unpkg; the npm package itself only ships
|
|
4
|
-
// types (devDependency @quickwinlabs/mupdf-wasm resolved through the
|
|
5
|
-
// package's exports types mapping — no local vendor copy involved).
|
|
6
|
-
// MUPDF_VERSION must stay in sync with the devDependency in package.json
|
|
7
|
-
// when bumping.
|
|
8
|
-
//
|
|
9
|
-
// Importing this module wires up the HTTPS stack (certs + fetch): the
|
|
10
|
-
// wasm bytes travel through the process-wide HTTP cache next to the
|
|
11
|
-
// executable, so the first fetch is the only network hit.
|
|
12
|
-
import '../lib/certs.js';
|
|
13
|
-
import '../lib/fetch.js';
|
|
14
|
-
export const MUPDF_VERSION = '1.28.0';
|
|
15
|
-
const BASE = `https://unpkg.com/@quickwinlabs/mupdf-wasm@${MUPDF_VERSION}`;
|
|
16
|
-
export const MUPDF_JS_URL = `${BASE}/mupdf.js`;
|
|
17
|
-
export const MUPDF_WASM_URL = `${BASE}/mupdf-wasm.wasm`;
|
|
18
|
-
/** Fetch the wasm binary over HTTPS (HTTP-cached, no filesystem involved). */
|
|
19
|
-
export async function fetchMupdfWasm() {
|
|
20
|
-
const resp = await fetch(MUPDF_WASM_URL);
|
|
21
|
-
if (resp.status !== 200)
|
|
22
|
-
throw new Error(`mupdf wasm fetch failed: HTTP ${resp.status}`);
|
|
23
|
-
const wasmBinary = await resp.arrayBuffer();
|
|
24
|
-
if (wasmBinary.byteLength < 1_000_000)
|
|
25
|
-
throw new Error(`mupdf wasm truncated: ${wasmBinary.byteLength} bytes`);
|
|
26
|
-
return wasmBinary;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Fetch the wasm binary and pre-wire it as $libmupdf_wasm_Module so the
|
|
30
|
-
* mupdf.js module factory instantiates from memory (same injection the
|
|
31
|
-
* local-vendor loading used).
|
|
32
|
-
*/
|
|
33
|
-
export async function preloadMupdfWasm() {
|
|
34
|
-
const wasmBinary = await fetchMupdfWasm();
|
|
35
|
-
globalThis.$libmupdf_wasm_Module = {
|
|
36
|
-
wasmBinary,
|
|
37
|
-
locateFile: (p) => p,
|
|
38
|
-
};
|
|
39
|
-
return wasmBinary;
|
|
40
|
-
}
|
package/test/mupdf-cdn.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// ── mupdf-wasm CDN loading ──
|
|
2
|
-
//
|
|
3
|
-
// The runtime loads mupdf from unpkg; the npm package itself only ships
|
|
4
|
-
// types (devDependency @quickwinlabs/mupdf-wasm resolved through the
|
|
5
|
-
// package's exports types mapping — no local vendor copy involved).
|
|
6
|
-
// MUPDF_VERSION must stay in sync with the devDependency in package.json
|
|
7
|
-
// when bumping.
|
|
8
|
-
//
|
|
9
|
-
// Importing this module wires up the HTTPS stack (certs + fetch): the
|
|
10
|
-
// wasm bytes travel through the process-wide HTTP cache next to the
|
|
11
|
-
// executable, so the first fetch is the only network hit.
|
|
12
|
-
|
|
13
|
-
import '../lib/certs.js'
|
|
14
|
-
import '../lib/fetch.js'
|
|
15
|
-
|
|
16
|
-
export const MUPDF_VERSION = '1.28.0'
|
|
17
|
-
const BASE = `https://unpkg.com/@quickwinlabs/mupdf-wasm@${MUPDF_VERSION}`
|
|
18
|
-
|
|
19
|
-
export const MUPDF_JS_URL = `${BASE}/mupdf.js`
|
|
20
|
-
export const MUPDF_WASM_URL = `${BASE}/mupdf-wasm.wasm`
|
|
21
|
-
|
|
22
|
-
/** Fetch the wasm binary over HTTPS (HTTP-cached, no filesystem involved). */
|
|
23
|
-
export async function fetchMupdfWasm(): Promise<ArrayBuffer> {
|
|
24
|
-
const resp = await fetch(MUPDF_WASM_URL)
|
|
25
|
-
if (resp.status !== 200) throw new Error(`mupdf wasm fetch failed: HTTP ${resp.status}`)
|
|
26
|
-
const wasmBinary = await resp.arrayBuffer()
|
|
27
|
-
if (wasmBinary.byteLength < 1_000_000) throw new Error(`mupdf wasm truncated: ${wasmBinary.byteLength} bytes`)
|
|
28
|
-
return wasmBinary
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Fetch the wasm binary and pre-wire it as $libmupdf_wasm_Module so the
|
|
33
|
-
* mupdf.js module factory instantiates from memory (same injection the
|
|
34
|
-
* local-vendor loading used).
|
|
35
|
-
*/
|
|
36
|
-
export async function preloadMupdfWasm(): Promise<ArrayBuffer> {
|
|
37
|
-
const wasmBinary = await fetchMupdfWasm()
|
|
38
|
-
;(globalThis as any).$libmupdf_wasm_Module = {
|
|
39
|
-
wasmBinary,
|
|
40
|
-
locateFile: (p: string) => p,
|
|
41
|
-
}
|
|
42
|
-
return wasmBinary
|
|
43
|
-
}
|