quickwin 1.0.2 → 1.1.1
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 +204 -204
- package/README.md +203 -203
- package/examples/PdfCanvas.tsx +83 -83
- package/examples/exec_server.ts +35 -35
- package/examples/pdf_preview2.ts +375 -375
- package/examples/pdf_viewer.tsx +279 -279
- package/examples/test_gallery.tsx +285 -285
- package/examples/test_react_lazy.tsx +63 -63
- package/examples/test_react_listbox.tsx +71 -71
- package/examples/test_root_window.tsx +41 -41
- package/examples/test_tab.tsx +75 -75
- package/examples/tray_demo.tsx +81 -81
- package/lib/assert.ts +6 -6
- package/lib/cache-utils.ts +40 -40
- package/lib/dumpRects.ts +25 -25
- package/lib/fetch.ts +502 -502
- package/lib/http-common.ts +399 -399
- package/lib/http-server.ts +424 -424
- package/lib/polyfill.ts +171 -171
- package/lib/react-qw/components/index.ts +17 -17
- package/lib/react-qw/index.ts +90 -90
- package/lib/react-qw/jsx.d.ts +34 -34
- package/lib/react-qw/layout.ts +111 -111
- package/lib/react-qw/props.ts +36 -36
- package/lib/react-qw/reconciler.ts +373 -373
- package/lib/stream.ts +21 -21
- package/lib/text-codec.ts +171 -171
- package/lib/text-measure.ts +54 -54
- package/lib/url.ts +201 -201
- package/lib/vendor/web-streams/ponyfill.d.mts +829 -829
- package/lib/vendor/web-streams/ponyfill.mjs +8 -8
- package/lib/websocket.js +8 -0
- package/lib/websocket.ts +563 -555
- package/package.json +50 -44
- 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/run.ts +96 -96
- package/test/test_basic.ts +9 -9
- package/test/test_basic_fetch.ts +33 -33
- package/test/test_brotli.ts +52 -52
- package/test/test_fetch_cache.ts +187 -187
- package/test/test_ffi.ts +174 -174
- package/test/test_frame_encoding.ts +132 -132
- package/test/test_helper.ts +80 -80
- package/test/test_http_import.ts +74 -74
- package/test/test_http_server.ts +136 -136
- package/test/test_import_dir.ts +5 -5
- package/test/test_ipv6.ts +129 -129
- package/test/test_meta_url.ts +4 -4
- package/test/test_mupdf_render.ts +74 -74
- package/test/test_mupdf_twice.ts +81 -81
- package/test/test_mupdf_wasm.ts +30 -30
- package/test/test_net_event.ts +55 -55
- package/test/test_net_fetch.ts +238 -238
- package/test/test_net_websocket.ts +164 -164
- package/test/test_polyfill.ts +159 -159
- package/test/test_url.ts +183 -183
- package/test/test_wasm_basic.ts +73 -73
- package/test/test_wasm_import_global.ts +45 -45
- package/test/test_wasm_sjlj.ts +125 -125
- package/test/test_wasm_types.ts +124 -124
- package/test/test_worker.ts +24 -24
- package/test/test_worker_fetch.ts +27 -27
- package/test/test_worker_net.ts +54 -54
- package/test/test_worker_wasm_concurrent.ts +45 -45
- package/test/worker_fetch.ts +13 -13
- package/test/worker_helper.ts +1 -1
- package/test/worker_http.ts +20 -20
- package/test/worker_import_lib.ts +13 -13
- package/test/worker_module.ts +17 -17
- package/test/worker_wasm_concurrent.ts +22 -22
- package/tsconfig.json +27 -27
- package/vendor/mupdf-wasm/mupdf-wasm.d.ts +571 -571
- package/vendor/mupdf-wasm/mupdf-wasm.js +2749 -2749
- package/vendor/mupdf-wasm/mupdf.d.ts +939 -939
- 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
|