quickwin 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.en.md +204 -204
  2. package/README.md +203 -203
  3. package/examples/PdfCanvas.tsx +83 -83
  4. package/examples/exec_server.ts +35 -35
  5. package/examples/pdf_preview2.ts +375 -375
  6. package/examples/pdf_viewer.tsx +279 -279
  7. package/examples/test_gallery.tsx +285 -285
  8. package/examples/test_react_lazy.tsx +63 -63
  9. package/examples/test_react_listbox.tsx +71 -71
  10. package/examples/test_root_window.tsx +41 -41
  11. package/examples/test_tab.tsx +75 -75
  12. package/examples/tray_demo.tsx +81 -81
  13. package/lib/assert.ts +6 -6
  14. package/lib/cache-utils.ts +40 -40
  15. package/lib/dumpRects.ts +25 -25
  16. package/lib/fetch.ts +502 -502
  17. package/lib/http-common.ts +399 -399
  18. package/lib/http-server.ts +424 -424
  19. package/lib/polyfill.ts +171 -171
  20. package/lib/react-qw/components/index.ts +17 -17
  21. package/lib/react-qw/index.ts +90 -90
  22. package/lib/react-qw/jsx.d.ts +34 -34
  23. package/lib/react-qw/layout.ts +111 -111
  24. package/lib/react-qw/props.ts +36 -36
  25. package/lib/react-qw/reconciler.ts +373 -373
  26. package/lib/stream.ts +21 -21
  27. package/lib/text-codec.ts +171 -171
  28. package/lib/text-measure.ts +54 -54
  29. package/lib/url.ts +201 -201
  30. package/lib/vendor/web-streams/ponyfill.d.mts +829 -829
  31. package/lib/vendor/web-streams/ponyfill.mjs +8 -8
  32. package/lib/websocket.js +8 -0
  33. package/lib/websocket.ts +563 -555
  34. package/package.json +50 -44
  35. package/qwin-nowasm-x86.exe +0 -0
  36. package/qwin-nowasm.exe +0 -0
  37. package/qwin-x86.exe +0 -0
  38. package/qwin.exe +0 -0
  39. package/test/run.ts +96 -96
  40. package/test/test_basic.ts +9 -9
  41. package/test/test_basic_fetch.ts +33 -33
  42. package/test/test_brotli.ts +52 -52
  43. package/test/test_fetch_cache.ts +187 -187
  44. package/test/test_ffi.ts +174 -174
  45. package/test/test_frame_encoding.ts +132 -132
  46. package/test/test_helper.ts +80 -80
  47. package/test/test_http_import.ts +74 -74
  48. package/test/test_http_server.ts +136 -136
  49. package/test/test_import_dir.ts +5 -5
  50. package/test/test_ipv6.ts +129 -129
  51. package/test/test_meta_url.ts +4 -4
  52. package/test/test_mupdf_render.ts +74 -74
  53. package/test/test_mupdf_twice.ts +81 -81
  54. package/test/test_mupdf_wasm.ts +30 -30
  55. package/test/test_net_event.ts +55 -55
  56. package/test/test_net_fetch.ts +238 -238
  57. package/test/test_net_websocket.ts +164 -164
  58. package/test/test_polyfill.ts +159 -159
  59. package/test/test_url.ts +183 -183
  60. package/test/test_wasm_basic.ts +73 -73
  61. package/test/test_wasm_import_global.ts +45 -45
  62. package/test/test_wasm_sjlj.ts +125 -125
  63. package/test/test_wasm_types.ts +124 -124
  64. package/test/test_worker.ts +24 -24
  65. package/test/test_worker_fetch.ts +27 -27
  66. package/test/test_worker_net.ts +54 -54
  67. package/test/test_worker_wasm_concurrent.ts +45 -45
  68. package/test/worker_fetch.ts +13 -13
  69. package/test/worker_helper.ts +1 -1
  70. package/test/worker_http.ts +20 -20
  71. package/test/worker_import_lib.ts +13 -13
  72. package/test/worker_module.ts +17 -17
  73. package/test/worker_wasm_concurrent.ts +22 -22
  74. package/tsconfig.json +27 -27
  75. package/vendor/mupdf-wasm/mupdf-wasm.d.ts +571 -571
  76. package/vendor/mupdf-wasm/mupdf-wasm.js +2749 -2749
  77. package/vendor/mupdf-wasm/mupdf.d.ts +939 -939
  78. package/vendor/mupdf-wasm/mupdf.js +3317 -3317
package/README.en.md CHANGED
@@ -1,205 +1,205 @@
1
- > [中文文档](README.md) · **English**
2
-
3
- # QuickWin
4
-
5
- QuickJS runtime for Windows, with native GUI, networking, WASM, FFI and more.
6
-
7
- Goal: compatibility with Windows XP+ (32/64-bit) and a minimal binary size.
8
-
9
- Currently: supports Windows 7+ (64-bit), ~1.5MB binary.
10
-
11
- Early-stage project with known bugs.
12
-
13
- Download directly from the GitHub Release:
14
-
15
- ```powershell
16
- iwr https://github.com/xna00/quickwin/releases/latest/download/qwin.exe -OutFile qwin.exe
17
- iwr https://github.com/xna00/quickwin/releases/latest/download/main.js -OutFile main.js
18
- .\qwin.exe main.js
19
- ```
20
-
21
- ## Features
22
-
23
- - **Win32 GUI** — native windows, buttons, edit boxes, list boxes, tray icons, popup menus
24
- - **React renderer** — declarative GUI in JSX with `useState`/`useEffect`, diff updates ([react-qw](lib/react-qw/))
25
- - **HTTP/HTTPS** — `fetch()` API, Brotli decompression, chunked transfer, conditional caching
26
- - **WebSocket** — full RFC 6455 implementation, ws:// + wss://
27
- - **WebAssembly** — WAMR-based, supports `WebAssembly.*` standard API
28
- - **FFI** — call any DLL function via libffi
29
- - **Polyfills** — `TextEncoder`, `URL`, `URLSearchParams`, `btoa`/`atob`, `crypto.subtle`, `setTimeout`
30
- - **Dynamic import** — `import('https://esm.sh/...')`, no dependency installation needed
31
-
32
- ## CLI
33
-
34
- ```bash
35
- quickwin script.js # run a script
36
- quickwin -o CON script.js # run with console (AllocConsole)
37
- quickwin -o LOG script.js # run with auto-generated log file
38
- quickwin -e "console.log('hi')" # execute expression
39
- quickwin -- script.js --flag # -- stops option parsing
40
- ```
41
-
42
- ### Options
43
-
44
- | Flag | Description |
45
- |------|-------------|
46
- | `-e <expr>` | Execute expression instead of a file |
47
- | `-o CON` | Allocate console (`AllocConsole`); only needed for GUI-subsystem builds |
48
- | `-o LOG` | Redirect stdout+stderr to `log_YYYY_MM_DD_HH_MM_SS.txt` (exe directory) |
49
- | `-o <file>` | Redirect stdout+stderr to specified file |
50
- | `-d` | Enable HTTP debug logging |
51
- | `--` | Stop option parsing, remaining args passed to script |
52
-
53
- All unknown flags are transparently forwarded to `scriptArgs` — no error,
54
- no consumption. Script file is the first non-flag argument after option parsing.
55
-
56
- ## Embedded Script
57
-
58
- You can embed a JS script directly into the `qwin.exe` binary — no recompilation needed.
59
-
60
- ### Format (appended to exe)
61
-
62
- ```
63
- [JS bytes (N)] [N: uint32 LE] [magic "QWJS"]
64
- ```
65
-
66
- ### Usage
67
-
68
- ```bash
69
- # Embed a script
70
- powershell -ExecutionPolicy Bypass -File scripts/embed-js.ps1 -ExePath _build/qwin.exe -JsFile script.js
71
-
72
- # Or via make
73
- make embed-js JS_EMBED=script.js
74
-
75
- # Embed a script brotli-compressed (smaller exe, decompressed at runtime)
76
- make embed-js-br JS_EMBED=script.js
77
-
78
- # Run it (no file argument needed)
79
- qwin.exe
80
- ```
81
-
82
- When run without a script file argument, `qwin.exe` checks for embedded JS at the end of itself. If found, it executes the embedded code. If not, it falls back to `main.js`. Both raw (`QWJS`) and brotli-compressed (`QWBR`) embedded payloads are supported; the compressed form is decompressed at startup.
83
-
84
- ## Modules
85
-
86
- | Module | Import | Description |
87
- |--------|--------|-------------|
88
- | `std` | built-in | file I/O, environment, URL download |
89
- | `os` | built-in | filesystem, process, Worker, timer |
90
- | `gui` | built-in | Win32 window/control/message/tray API |
91
- | `sock` | built-in | socket networking (`AddrFamily`, `FdEvent` etc.) |
92
- | `wolfssl` | built-in | TLS/SSL (`VerifyMode`, `ReturnCode` etc.) |
93
- | `ffi` | built-in | foreign function interface |
94
- | `win` | built-in | DLL loading (`LoadLibrary`, `GetProcAddress`) |
95
- | `brotli` | built-in | Brotli decompression |
96
- | `wamr` | built-in | low-level WAMR API |
97
- | `fetch` | `import './lib/fetch.js'` | adds `fetch()`, `Response`, `Headers` to globalThis |
98
- | `websocket` | `import './lib/websocket.js'` | adds `WebSocket` to globalThis |
99
- | `polyfill` | `import './lib/polyfill.js'` | adds `TextEncoder`, `URL`, `btoa`/`atob`, `setTimeout` to globalThis |
100
- | `preact` | `lib/preact/...` | JSX → Win32 renderer (`render`, `useState`, `useEffect`) |
101
- | `react-qw` | `lib/react-qw/` | React Custom Renderer for Win32 GUI ([docs](lib/react-qw/)) |
102
-
103
- ## Worker
104
-
105
- Spawn background threads for CPU-bound or I/O-bound work. Workers run in separate QuickJS runtimes with their own event loops.
106
-
107
- ### Main Thread
108
-
109
- ```js
110
- import * as os from 'os'
111
-
112
- const worker = new os.Worker('./worker.js')
113
-
114
- worker.onmessage = (e) => {
115
- console.log('received:', e.data)
116
- worker.onmessage = null // clean up when done
117
- }
118
-
119
- worker.postMessage({ type: 'start', value: 42 })
120
- ```
121
-
122
- ### Worker Thread
123
-
124
- ```js
125
- // worker.js
126
- import * as os from 'os'
127
-
128
- const parent = os.Worker.parent
129
-
130
- parent.onmessage = (e) => {
131
- if (e.data.type === 'start') {
132
- parent.postMessage({ type: 'result', value: e.data.value * 2 })
133
- } else if (e.data.type === 'done') {
134
- parent.onmessage = null // clean up to allow event loop exit
135
- }
136
- }
137
- ```
138
-
139
- ### API
140
-
141
- | API | Description |
142
- |-----|-------------|
143
- | `new os.Worker(specifier)` | Create worker. `specifier` is a file path or URL (supports `https://` for ESM imports) |
144
- | `worker.postMessage(data)` | Send message (JSON-serializable) to worker |
145
- | `worker.onmessage = fn` | Set callback for messages from worker. Set to `null` when done to release the message port |
146
- | `os.Worker.parent` | (Worker side) reference to the parent thread |
147
-
148
- ### Cleanup
149
-
150
- Both sides must set `onmessage = null` when communication is complete. This releases the message port so the event loop can exit cleanly. Forgetting to do so will cause the process to hang.
151
-
152
- ## Examples
153
-
154
- ```bash
155
- .\qwin.exe examples/preact_demo.js # counter GUI with JSX + hooks
156
- .\qwin.exe examples/tray_demo.js # system tray app
157
- .\qwin.exe examples/pdf_preview.js # PDF reader with mupdf
158
- ```
159
-
160
- ## Build from Source
161
-
162
- ### Prerequisites
163
-
164
- - MSYS2 UCRT64 or MINGW64
165
- - Node.js (for TypeScript compilation via tsc)
166
- - Git (for submodules)
167
-
168
- ### Build
169
-
170
- ```bash
171
- git clone --recursive https://github.com/anomalyco/quickwin.git
172
- cd quickwin
173
-
174
- .\run.ps1 "make wamr" # build WAMR library (first time only)
175
- .\run.ps1 "make minimal" # build qwin.exe (-Os + LTO + UPX)
176
- .\run.ps1 "make js" # compile TypeScript
177
- .\run.ps1 "make test" # run all tests
178
- ```
179
-
180
- `make nowasm` produces a smaller `_build/qwin-nowasm.exe` without WASM/WAMR
181
- (no `WebAssembly` global); run `make test TEST=-wasm` to skip WASM tests on it.
182
-
183
- ### Build Targets
184
-
185
- | Target | Description |
186
- |--------|-------------|
187
- | `make` / `make nodebug` | fast build |
188
- | `make minimal` | `-Os` + LTO + `-mwindows` + UPX, no console, add `-o CON` for console |
189
- | `make nowasm` | no WASM/WAMR build → `_build/qwin-nowasm.exe` (~1.2MB, no `WebAssembly` global) |
190
- | `make release` | `-O2` + LTO + strip, ~1.5MB |
191
- | `make debug` | debug build with bridge logs |
192
- | `make js` | compile TypeScript via tsc |
193
- | `make wasm` | compile WAT → WASM fixtures |
194
- | `make test` | run all tests |
195
- | `make test TEST=-net` | skip network tests (fast) |
196
- | `make test TEST=wasm` | run WASM tests only |
197
- | `make wamr` | rebuild WAMR library |
198
- | `make embed-js` | embed `embed.js` into exe (use `JS_EMBED=file.js`) |
199
- | `make embed-js-br` | embed brotli-compressed JS into exe |
200
- | `make npm-pkg` | package into `dist/quickwin/` |
201
- | `make clean` | clean build artifacts |
202
-
203
- ## License
204
-
1
+ > [中文文档](README.md) · **English**
2
+
3
+ # QuickWin
4
+
5
+ QuickJS runtime for Windows, with native GUI, networking, WASM, FFI and more.
6
+
7
+ Goal: compatibility with Windows XP+ (32/64-bit) and a minimal binary size.
8
+
9
+ Currently: supports Windows 7+ (64-bit), ~1.5MB binary.
10
+
11
+ Early-stage project with known bugs.
12
+
13
+ Download directly from the GitHub Release:
14
+
15
+ ```powershell
16
+ iwr https://github.com/xna00/quickwin/releases/latest/download/qwin.exe -OutFile qwin.exe
17
+ iwr https://github.com/xna00/quickwin/releases/latest/download/main.js -OutFile main.js
18
+ .\qwin.exe main.js
19
+ ```
20
+
21
+ ## Features
22
+
23
+ - **Win32 GUI** — native windows, buttons, edit boxes, list boxes, tray icons, popup menus
24
+ - **React renderer** — declarative GUI in JSX with `useState`/`useEffect`, diff updates ([react-qw](lib/react-qw/))
25
+ - **HTTP/HTTPS** — `fetch()` API, Brotli decompression, chunked transfer, conditional caching
26
+ - **WebSocket** — full RFC 6455 implementation, ws:// + wss://
27
+ - **WebAssembly** — WAMR-based, supports `WebAssembly.*` standard API
28
+ - **FFI** — call any DLL function via libffi
29
+ - **Polyfills** — `TextEncoder`, `URL`, `URLSearchParams`, `btoa`/`atob`, `crypto.subtle`, `setTimeout`
30
+ - **Dynamic import** — `import('https://esm.sh/...')`, no dependency installation needed
31
+
32
+ ## CLI
33
+
34
+ ```bash
35
+ quickwin script.js # run a script
36
+ quickwin -o CON script.js # run with console (AllocConsole)
37
+ quickwin -o LOG script.js # run with auto-generated log file
38
+ quickwin -e "console.log('hi')" # execute expression
39
+ quickwin -- script.js --flag # -- stops option parsing
40
+ ```
41
+
42
+ ### Options
43
+
44
+ | Flag | Description |
45
+ |------|-------------|
46
+ | `-e <expr>` | Execute expression instead of a file |
47
+ | `-o CON` | Allocate console (`AllocConsole`); only needed for GUI-subsystem builds |
48
+ | `-o LOG` | Redirect stdout+stderr to `log_YYYY_MM_DD_HH_MM_SS.txt` (exe directory) |
49
+ | `-o <file>` | Redirect stdout+stderr to specified file |
50
+ | `-d` | Enable HTTP debug logging |
51
+ | `--` | Stop option parsing, remaining args passed to script |
52
+
53
+ All unknown flags are transparently forwarded to `scriptArgs` — no error,
54
+ no consumption. Script file is the first non-flag argument after option parsing.
55
+
56
+ ## Embedded Script
57
+
58
+ You can embed a JS script directly into the `qwin.exe` binary — no recompilation needed.
59
+
60
+ ### Format (appended to exe)
61
+
62
+ ```
63
+ [JS bytes (N)] [N: uint32 LE] [magic "QWJS"]
64
+ ```
65
+
66
+ ### Usage
67
+
68
+ ```bash
69
+ # Embed a script
70
+ powershell -ExecutionPolicy Bypass -File scripts/embed-js.ps1 -ExePath _build/qwin.exe -JsFile script.js
71
+
72
+ # Or via make
73
+ make embed-js JS_EMBED=script.js
74
+
75
+ # Embed a script brotli-compressed (smaller exe, decompressed at runtime)
76
+ make embed-js-br JS_EMBED=script.js
77
+
78
+ # Run it (no file argument needed)
79
+ qwin.exe
80
+ ```
81
+
82
+ When run without a script file argument, `qwin.exe` checks for embedded JS at the end of itself. If found, it executes the embedded code. If not, it falls back to `main.js`. Both raw (`QWJS`) and brotli-compressed (`QWBR`) embedded payloads are supported; the compressed form is decompressed at startup.
83
+
84
+ ## Modules
85
+
86
+ | Module | Import | Description |
87
+ |--------|--------|-------------|
88
+ | `std` | built-in | file I/O, environment, URL download |
89
+ | `os` | built-in | filesystem, process, Worker, timer |
90
+ | `gui` | built-in | Win32 window/control/message/tray API |
91
+ | `sock` | built-in | socket networking (`AddrFamily`, `FdEvent` etc.) |
92
+ | `wolfssl` | built-in | TLS/SSL (`VerifyMode`, `ReturnCode` etc.) |
93
+ | `ffi` | built-in | foreign function interface |
94
+ | `win` | built-in | DLL loading (`LoadLibrary`, `GetProcAddress`) |
95
+ | `brotli` | built-in | Brotli decompression |
96
+ | `wamr` | built-in | low-level WAMR API |
97
+ | `fetch` | `import './lib/fetch.js'` | adds `fetch()`, `Response`, `Headers` to globalThis |
98
+ | `websocket` | `import './lib/websocket.js'` | adds `WebSocket` to globalThis |
99
+ | `polyfill` | `import './lib/polyfill.js'` | adds `TextEncoder`, `URL`, `btoa`/`atob`, `setTimeout` to globalThis |
100
+ | `preact` | `lib/preact/...` | JSX → Win32 renderer (`render`, `useState`, `useEffect`) |
101
+ | `react-qw` | `lib/react-qw/` | React Custom Renderer for Win32 GUI ([docs](lib/react-qw/)) |
102
+
103
+ ## Worker
104
+
105
+ Spawn background threads for CPU-bound or I/O-bound work. Workers run in separate QuickJS runtimes with their own event loops.
106
+
107
+ ### Main Thread
108
+
109
+ ```js
110
+ import * as os from 'os'
111
+
112
+ const worker = new os.Worker('./worker.js')
113
+
114
+ worker.onmessage = (e) => {
115
+ console.log('received:', e.data)
116
+ worker.onmessage = null // clean up when done
117
+ }
118
+
119
+ worker.postMessage({ type: 'start', value: 42 })
120
+ ```
121
+
122
+ ### Worker Thread
123
+
124
+ ```js
125
+ // worker.js
126
+ import * as os from 'os'
127
+
128
+ const parent = os.Worker.parent
129
+
130
+ parent.onmessage = (e) => {
131
+ if (e.data.type === 'start') {
132
+ parent.postMessage({ type: 'result', value: e.data.value * 2 })
133
+ } else if (e.data.type === 'done') {
134
+ parent.onmessage = null // clean up to allow event loop exit
135
+ }
136
+ }
137
+ ```
138
+
139
+ ### API
140
+
141
+ | API | Description |
142
+ |-----|-------------|
143
+ | `new os.Worker(specifier)` | Create worker. `specifier` is a file path or URL (supports `https://` for ESM imports) |
144
+ | `worker.postMessage(data)` | Send message (JSON-serializable) to worker |
145
+ | `worker.onmessage = fn` | Set callback for messages from worker. Set to `null` when done to release the message port |
146
+ | `os.Worker.parent` | (Worker side) reference to the parent thread |
147
+
148
+ ### Cleanup
149
+
150
+ Both sides must set `onmessage = null` when communication is complete. This releases the message port so the event loop can exit cleanly. Forgetting to do so will cause the process to hang.
151
+
152
+ ## Examples
153
+
154
+ ```bash
155
+ .\qwin.exe examples/preact_demo.js # counter GUI with JSX + hooks
156
+ .\qwin.exe examples/tray_demo.js # system tray app
157
+ .\qwin.exe examples/pdf_preview.js # PDF reader with mupdf
158
+ ```
159
+
160
+ ## Build from Source
161
+
162
+ ### Prerequisites
163
+
164
+ - MSYS2 UCRT64 or MINGW64
165
+ - Node.js (for TypeScript compilation via tsc)
166
+ - Git (for submodules)
167
+
168
+ ### Build
169
+
170
+ ```bash
171
+ git clone --recursive https://github.com/anomalyco/quickwin.git
172
+ cd quickwin
173
+
174
+ .\run.ps1 "make wamr" # build WAMR library (first time only)
175
+ .\run.ps1 "make minimal" # build qwin.exe (-Os + LTO + UPX)
176
+ .\run.ps1 "make js" # compile TypeScript
177
+ .\run.ps1 "make test" # run all tests
178
+ ```
179
+
180
+ `make nowasm` produces a smaller `_build/qwin-nowasm.exe` without WASM/WAMR
181
+ (no `WebAssembly` global); run `make test TEST=-wasm` to skip WASM tests on it.
182
+
183
+ ### Build Targets
184
+
185
+ | Target | Description |
186
+ |--------|-------------|
187
+ | `make` / `make nodebug` | fast build |
188
+ | `make minimal` | `-Os` + LTO + `-mwindows` + UPX, no console, add `-o CON` for console |
189
+ | `make nowasm` | no WASM/WAMR build → `_build/qwin-nowasm.exe` (~1.2MB, no `WebAssembly` global) |
190
+ | `make release` | `-O2` + LTO + strip, ~1.5MB |
191
+ | `make debug` | debug build with bridge logs |
192
+ | `make js` | compile TypeScript via tsc |
193
+ | `make wasm` | compile WAT → WASM fixtures |
194
+ | `make test` | run all tests |
195
+ | `make test TEST=-net` | skip network tests (fast) |
196
+ | `make test TEST=wasm` | run WASM tests only |
197
+ | `make wamr` | rebuild WAMR library |
198
+ | `make embed-js` | embed `embed.js` into exe (use `JS_EMBED=file.js`) |
199
+ | `make embed-js-br` | embed brotli-compressed JS into exe |
200
+ | `make npm-pkg` | package into `dist/quickwin/` |
201
+ | `make clean` | clean build artifacts |
202
+
203
+ ## License
204
+
205
205
  MIT