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/lib/polyfill.ts
CHANGED
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
import * as os from 'os'
|
|
2
|
-
import './url.js'
|
|
3
|
-
import './text-codec.js'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
declare global {
|
|
7
|
-
interface Console {
|
|
8
|
-
error: (...args: unknown[]) => void
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
var window: typeof globalThis
|
|
12
|
-
|
|
13
|
-
type TimerId = os.TimerId
|
|
14
|
-
function setTimeout<P extends unknown[]>(fn: (...argsf: P) => void, ms?: number, ...argsr: P): TimerId
|
|
15
|
-
function clearTimeout(id: TimerId): void
|
|
16
|
-
|
|
17
|
-
function btoa(data: string): string
|
|
18
|
-
function atob(data: string): string
|
|
19
|
-
|
|
20
|
-
interface SubtleCrypto {
|
|
21
|
-
digest(algorithm: 'SHA-1', data: ArrayBuffer | Uint8Array): Promise<ArrayBuffer>
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
interface Crypto {
|
|
25
|
-
getRandomValues<T extends ArrayBufferView>(array: T): T
|
|
26
|
-
subtle: SubtleCrypto
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
var crypto: Crypto
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// 1. window — triggers Emscripten browser path
|
|
33
|
-
if (typeof globalThis.window === 'undefined')
|
|
34
|
-
globalThis.window = globalThis
|
|
35
|
-
|
|
36
|
-
// 2. setTimeout polyfill — bridge to os.setTimeout
|
|
37
|
-
if (typeof globalThis.setTimeout === 'undefined') {
|
|
38
|
-
globalThis.setTimeout = ((fn, ms, ...args) => {
|
|
39
|
-
return os.setTimeout(() => fn(...args), ms ?? 0)
|
|
40
|
-
}) satisfies typeof setTimeout
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// 2b. clearTimeout polyfill — bridge to os.clearTimeout
|
|
44
|
-
if (typeof globalThis.clearTimeout === 'undefined') {
|
|
45
|
-
globalThis.clearTimeout = os.clearTimeout
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// 3. console.error polyfill — QuickJS only has console.log
|
|
49
|
-
if (typeof console.error === 'undefined') {
|
|
50
|
-
console.error = (...args: unknown[]) => { console.log(...args) }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// ── SHA-1 ──
|
|
55
|
-
|
|
56
|
-
function sha1Bytes(bytes: number[]): ArrayBuffer {
|
|
57
|
-
const len = bytes.length
|
|
58
|
-
const ml = len * 8
|
|
59
|
-
|
|
60
|
-
bytes.push(0x80)
|
|
61
|
-
while (bytes.length % 64 !== 56) { bytes.push(0) }
|
|
62
|
-
bytes.push(0)
|
|
63
|
-
bytes.push(0)
|
|
64
|
-
bytes.push(0)
|
|
65
|
-
bytes.push(0)
|
|
66
|
-
bytes.push((ml >>> 24) & 0xFF)
|
|
67
|
-
bytes.push((ml >>> 16) & 0xFF)
|
|
68
|
-
bytes.push((ml >>> 8) & 0xFF)
|
|
69
|
-
bytes.push(ml & 0xFF)
|
|
70
|
-
|
|
71
|
-
let h0 = 0x67452301, h1 = 0xEFCDAB89
|
|
72
|
-
let h2 = 0x98BADCFE, h3 = 0x10325476, h4 = 0xC3D2E1F0
|
|
73
|
-
const rotl = (x: number, n: number): number => ((x << n) | (x >>> (32 - n))) >>> 0
|
|
74
|
-
|
|
75
|
-
for (let i = 0; i < bytes.length; i += 64) {
|
|
76
|
-
const w: number[] = []
|
|
77
|
-
for (let t = 0; t < 16; t++) {
|
|
78
|
-
w[t] = (bytes[i + 4 * t]! << 24) | (bytes[i + 4 * t + 1]! << 16) |
|
|
79
|
-
(bytes[i + 4 * t + 2]! << 8) | bytes[i + 4 * t + 3]!
|
|
80
|
-
}
|
|
81
|
-
for (let t = 16; t < 80; t++) {
|
|
82
|
-
w[t] = rotl(w[t - 3]! ^ w[t - 8]! ^ w[t - 14]! ^ w[t - 16]!, 1)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
let a = h0, b = h1, c = h2, d = h3, e = h4
|
|
86
|
-
for (let t = 0; t < 80; t++) {
|
|
87
|
-
let f: number, k: number
|
|
88
|
-
if (t < 20) { f = (b & c) | (~b & d); k = 0x5A827999 }
|
|
89
|
-
else if (t < 40) { f = b ^ c ^ d; k = 0x6ED9EBA1 }
|
|
90
|
-
else if (t < 60) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC }
|
|
91
|
-
else { f = b ^ c ^ d; k = 0xCA62C1D6 }
|
|
92
|
-
const temp = (rotl(a, 5) + f + e + k + w[t]!) >>> 0
|
|
93
|
-
e = d; d = c; c = rotl(b, 30); b = a; a = temp
|
|
94
|
-
}
|
|
95
|
-
h0 = (h0 + a) >>> 0; h1 = (h1 + b) >>> 0
|
|
96
|
-
h2 = (h2 + c) >>> 0; h3 = (h3 + d) >>> 0; h4 = (h4 + e) >>> 0
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const result = new Uint8Array(20)
|
|
100
|
-
const w32 = (off: number, v: number) => {
|
|
101
|
-
result[off] = (v >>> 24) & 0xFF; result[off + 1] = (v >>> 16) & 0xFF
|
|
102
|
-
result[off + 2] = (v >>> 8) & 0xFF; result[off + 3] = v & 0xFF
|
|
103
|
-
}
|
|
104
|
-
w32(0, h0); w32(4, h1); w32(8, h2); w32(12, h3); w32(16, h4)
|
|
105
|
-
return result.buffer
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ── Base64 ──
|
|
109
|
-
|
|
110
|
-
const B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
|
111
|
-
|
|
112
|
-
function b64Encode(data: Uint8Array): string {
|
|
113
|
-
let r = ''
|
|
114
|
-
for (let i = 0; i < data.length; i += 3) {
|
|
115
|
-
const b0 = data[i]!, b1 = i + 1 < data.length ? data[i + 1]! : 0, b2 = i + 2 < data.length ? data[i + 2]! : 0
|
|
116
|
-
r += B64[b0 >> 2]! + B64[((b0 & 3) << 4) | (b1 >> 4)]!
|
|
117
|
-
r += i + 1 < data.length ? B64[((b1 & 15) << 2) | (b2 >> 6)]! : '='
|
|
118
|
-
r += i + 2 < data.length ? B64[b2 & 63]! : '='
|
|
119
|
-
}
|
|
120
|
-
return r
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function b64Decode(str: string): Uint8Array {
|
|
124
|
-
str = str.replace(/[^A-Za-z0-9+/=]/g, '')
|
|
125
|
-
const bytes: number[] = []
|
|
126
|
-
for (let i = 0; i < str.length; i += 4) {
|
|
127
|
-
const c0 = B64.indexOf(str[i]!), c1 = B64.indexOf(str[i + 1]!)
|
|
128
|
-
const c2 = B64.indexOf(str[i + 2]!), c3 = B64.indexOf(str[i + 3]!)
|
|
129
|
-
bytes.push((c0 << 2) | (c1 >> 4))
|
|
130
|
-
if (c2 >= 0) bytes.push(((c1 & 15) << 4) | (c2 >> 2))
|
|
131
|
-
if (c3 >= 0) bytes.push(((c2 & 3) << 6) | c3)
|
|
132
|
-
}
|
|
133
|
-
return new Uint8Array(bytes)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ── btoa / atob ──
|
|
137
|
-
|
|
138
|
-
if (typeof globalThis.btoa === 'undefined') {
|
|
139
|
-
globalThis.btoa = (data: string): string => {
|
|
140
|
-
const bytes = new Uint8Array(data.length)
|
|
141
|
-
for (let i = 0; i < data.length; i++) bytes[i] = data.charCodeAt(i) & 0xFF
|
|
142
|
-
return b64Encode(bytes)
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (typeof globalThis.atob === 'undefined') {
|
|
147
|
-
globalThis.atob = (data: string): string => {
|
|
148
|
-
const bytes = b64Decode(data)
|
|
149
|
-
let r = ''
|
|
150
|
-
for (let i = 0; i < bytes.length; i++) r += String.fromCharCode(bytes[i]!)
|
|
151
|
-
return r
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (typeof globalThis.crypto === 'undefined') {
|
|
156
|
-
globalThis.crypto = {
|
|
157
|
-
getRandomValues: <T extends ArrayBufferView>(array: T): T => {
|
|
158
|
-
const view = new Uint8Array(array.buffer, array.byteOffset, array.byteLength)
|
|
159
|
-
for (let i = 0; i < view.length; i++) view[i] = (Math.random() * 256) | 0
|
|
160
|
-
return array
|
|
161
|
-
},
|
|
162
|
-
subtle: {
|
|
163
|
-
digest: (algorithm: string, data: ArrayBuffer | Uint8Array): Promise<ArrayBuffer> => {
|
|
164
|
-
if (algorithm.toUpperCase() !== 'SHA-1')
|
|
165
|
-
return Promise.reject(new Error('Digest: ' + algorithm + ' not supported'))
|
|
166
|
-
const bytes = data instanceof Uint8Array ? Array.from(data) : Array.from(new Uint8Array(data))
|
|
167
|
-
return Promise.resolve(sha1Bytes(bytes))
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
1
|
+
import * as os from 'os'
|
|
2
|
+
import './url.js'
|
|
3
|
+
import './text-codec.js'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
interface Console {
|
|
8
|
+
error: (...args: unknown[]) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
var window: typeof globalThis
|
|
12
|
+
|
|
13
|
+
type TimerId = os.TimerId
|
|
14
|
+
function setTimeout<P extends unknown[]>(fn: (...argsf: P) => void, ms?: number, ...argsr: P): TimerId
|
|
15
|
+
function clearTimeout(id: TimerId): void
|
|
16
|
+
|
|
17
|
+
function btoa(data: string): string
|
|
18
|
+
function atob(data: string): string
|
|
19
|
+
|
|
20
|
+
interface SubtleCrypto {
|
|
21
|
+
digest(algorithm: 'SHA-1', data: ArrayBuffer | Uint8Array): Promise<ArrayBuffer>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface Crypto {
|
|
25
|
+
getRandomValues<T extends ArrayBufferView>(array: T): T
|
|
26
|
+
subtle: SubtleCrypto
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var crypto: Crypto
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 1. window — triggers Emscripten browser path
|
|
33
|
+
if (typeof globalThis.window === 'undefined')
|
|
34
|
+
globalThis.window = globalThis
|
|
35
|
+
|
|
36
|
+
// 2. setTimeout polyfill — bridge to os.setTimeout
|
|
37
|
+
if (typeof globalThis.setTimeout === 'undefined') {
|
|
38
|
+
globalThis.setTimeout = ((fn, ms, ...args) => {
|
|
39
|
+
return os.setTimeout(() => fn(...args), ms ?? 0)
|
|
40
|
+
}) satisfies typeof setTimeout
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 2b. clearTimeout polyfill — bridge to os.clearTimeout
|
|
44
|
+
if (typeof globalThis.clearTimeout === 'undefined') {
|
|
45
|
+
globalThis.clearTimeout = os.clearTimeout
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 3. console.error polyfill — QuickJS only has console.log
|
|
49
|
+
if (typeof console.error === 'undefined') {
|
|
50
|
+
console.error = (...args: unknown[]) => { console.log(...args) }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
// ── SHA-1 ──
|
|
55
|
+
|
|
56
|
+
function sha1Bytes(bytes: number[]): ArrayBuffer {
|
|
57
|
+
const len = bytes.length
|
|
58
|
+
const ml = len * 8
|
|
59
|
+
|
|
60
|
+
bytes.push(0x80)
|
|
61
|
+
while (bytes.length % 64 !== 56) { bytes.push(0) }
|
|
62
|
+
bytes.push(0)
|
|
63
|
+
bytes.push(0)
|
|
64
|
+
bytes.push(0)
|
|
65
|
+
bytes.push(0)
|
|
66
|
+
bytes.push((ml >>> 24) & 0xFF)
|
|
67
|
+
bytes.push((ml >>> 16) & 0xFF)
|
|
68
|
+
bytes.push((ml >>> 8) & 0xFF)
|
|
69
|
+
bytes.push(ml & 0xFF)
|
|
70
|
+
|
|
71
|
+
let h0 = 0x67452301, h1 = 0xEFCDAB89
|
|
72
|
+
let h2 = 0x98BADCFE, h3 = 0x10325476, h4 = 0xC3D2E1F0
|
|
73
|
+
const rotl = (x: number, n: number): number => ((x << n) | (x >>> (32 - n))) >>> 0
|
|
74
|
+
|
|
75
|
+
for (let i = 0; i < bytes.length; i += 64) {
|
|
76
|
+
const w: number[] = []
|
|
77
|
+
for (let t = 0; t < 16; t++) {
|
|
78
|
+
w[t] = (bytes[i + 4 * t]! << 24) | (bytes[i + 4 * t + 1]! << 16) |
|
|
79
|
+
(bytes[i + 4 * t + 2]! << 8) | bytes[i + 4 * t + 3]!
|
|
80
|
+
}
|
|
81
|
+
for (let t = 16; t < 80; t++) {
|
|
82
|
+
w[t] = rotl(w[t - 3]! ^ w[t - 8]! ^ w[t - 14]! ^ w[t - 16]!, 1)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let a = h0, b = h1, c = h2, d = h3, e = h4
|
|
86
|
+
for (let t = 0; t < 80; t++) {
|
|
87
|
+
let f: number, k: number
|
|
88
|
+
if (t < 20) { f = (b & c) | (~b & d); k = 0x5A827999 }
|
|
89
|
+
else if (t < 40) { f = b ^ c ^ d; k = 0x6ED9EBA1 }
|
|
90
|
+
else if (t < 60) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC }
|
|
91
|
+
else { f = b ^ c ^ d; k = 0xCA62C1D6 }
|
|
92
|
+
const temp = (rotl(a, 5) + f + e + k + w[t]!) >>> 0
|
|
93
|
+
e = d; d = c; c = rotl(b, 30); b = a; a = temp
|
|
94
|
+
}
|
|
95
|
+
h0 = (h0 + a) >>> 0; h1 = (h1 + b) >>> 0
|
|
96
|
+
h2 = (h2 + c) >>> 0; h3 = (h3 + d) >>> 0; h4 = (h4 + e) >>> 0
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const result = new Uint8Array(20)
|
|
100
|
+
const w32 = (off: number, v: number) => {
|
|
101
|
+
result[off] = (v >>> 24) & 0xFF; result[off + 1] = (v >>> 16) & 0xFF
|
|
102
|
+
result[off + 2] = (v >>> 8) & 0xFF; result[off + 3] = v & 0xFF
|
|
103
|
+
}
|
|
104
|
+
w32(0, h0); w32(4, h1); w32(8, h2); w32(12, h3); w32(16, h4)
|
|
105
|
+
return result.buffer
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ── Base64 ──
|
|
109
|
+
|
|
110
|
+
const B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
|
111
|
+
|
|
112
|
+
function b64Encode(data: Uint8Array): string {
|
|
113
|
+
let r = ''
|
|
114
|
+
for (let i = 0; i < data.length; i += 3) {
|
|
115
|
+
const b0 = data[i]!, b1 = i + 1 < data.length ? data[i + 1]! : 0, b2 = i + 2 < data.length ? data[i + 2]! : 0
|
|
116
|
+
r += B64[b0 >> 2]! + B64[((b0 & 3) << 4) | (b1 >> 4)]!
|
|
117
|
+
r += i + 1 < data.length ? B64[((b1 & 15) << 2) | (b2 >> 6)]! : '='
|
|
118
|
+
r += i + 2 < data.length ? B64[b2 & 63]! : '='
|
|
119
|
+
}
|
|
120
|
+
return r
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function b64Decode(str: string): Uint8Array {
|
|
124
|
+
str = str.replace(/[^A-Za-z0-9+/=]/g, '')
|
|
125
|
+
const bytes: number[] = []
|
|
126
|
+
for (let i = 0; i < str.length; i += 4) {
|
|
127
|
+
const c0 = B64.indexOf(str[i]!), c1 = B64.indexOf(str[i + 1]!)
|
|
128
|
+
const c2 = B64.indexOf(str[i + 2]!), c3 = B64.indexOf(str[i + 3]!)
|
|
129
|
+
bytes.push((c0 << 2) | (c1 >> 4))
|
|
130
|
+
if (c2 >= 0) bytes.push(((c1 & 15) << 4) | (c2 >> 2))
|
|
131
|
+
if (c3 >= 0) bytes.push(((c2 & 3) << 6) | c3)
|
|
132
|
+
}
|
|
133
|
+
return new Uint8Array(bytes)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ── btoa / atob ──
|
|
137
|
+
|
|
138
|
+
if (typeof globalThis.btoa === 'undefined') {
|
|
139
|
+
globalThis.btoa = (data: string): string => {
|
|
140
|
+
const bytes = new Uint8Array(data.length)
|
|
141
|
+
for (let i = 0; i < data.length; i++) bytes[i] = data.charCodeAt(i) & 0xFF
|
|
142
|
+
return b64Encode(bytes)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (typeof globalThis.atob === 'undefined') {
|
|
147
|
+
globalThis.atob = (data: string): string => {
|
|
148
|
+
const bytes = b64Decode(data)
|
|
149
|
+
let r = ''
|
|
150
|
+
for (let i = 0; i < bytes.length; i++) r += String.fromCharCode(bytes[i]!)
|
|
151
|
+
return r
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (typeof globalThis.crypto === 'undefined') {
|
|
156
|
+
globalThis.crypto = {
|
|
157
|
+
getRandomValues: <T extends ArrayBufferView>(array: T): T => {
|
|
158
|
+
const view = new Uint8Array(array.buffer, array.byteOffset, array.byteLength)
|
|
159
|
+
for (let i = 0; i < view.length; i++) view[i] = (Math.random() * 256) | 0
|
|
160
|
+
return array
|
|
161
|
+
},
|
|
162
|
+
subtle: {
|
|
163
|
+
digest: (algorithm: string, data: ArrayBuffer | Uint8Array): Promise<ArrayBuffer> => {
|
|
164
|
+
if (algorithm.toUpperCase() !== 'SHA-1')
|
|
165
|
+
return Promise.reject(new Error('Digest: ' + algorithm + ' not supported'))
|
|
166
|
+
const bytes = data instanceof Uint8Array ? Array.from(data) : Array.from(new Uint8Array(data))
|
|
167
|
+
return Promise.resolve(sha1Bytes(bytes))
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
export { Button, type ButtonProps } from './Button.js'
|
|
2
|
-
export { CheckBox, type CheckBoxProps } from './CheckBox.js'
|
|
3
|
-
export { ComboBox, type ComboBoxProps } from './ComboBox.js'
|
|
4
|
-
export { DateTimePicker, type DateTimePickerProps } from './DateTimePicker.js'
|
|
5
|
-
export { Input, type InputProps } from './Input.js'
|
|
6
|
-
export { Link, type LinkProps } from './Link.js'
|
|
7
|
-
export { ListBox, type ListBoxProps } from './ListBox.js'
|
|
8
|
-
export { ListView, makeColorBlock, type ListViewProps, type Column, type CellStyle, type Align } from './ListView.js'
|
|
9
|
-
export { ProgressBar, type ProgressBarProps } from './ProgressBar.js'
|
|
10
|
-
export { RadioButton, type RadioButtonProps } from './RadioButton.js'
|
|
11
|
-
export { ScrollView, type ScrollViewProps } from './ScrollView.js'
|
|
12
|
-
export { Slider, type SliderProps } from './Slider.js'
|
|
13
|
-
export { Tab, type TabProps } from './Tab.js'
|
|
14
|
-
export { Tooltip, type TooltipProps } from './Tooltip.js'
|
|
15
|
-
export { TreeView, type TreeViewProps, type TreeNode } from './TreeView.js'
|
|
16
|
-
export { PathPicker, type PathPickerProps } from './PathPicker.js'
|
|
17
|
-
|
|
1
|
+
export { Button, type ButtonProps } from './Button.js'
|
|
2
|
+
export { CheckBox, type CheckBoxProps } from './CheckBox.js'
|
|
3
|
+
export { ComboBox, type ComboBoxProps } from './ComboBox.js'
|
|
4
|
+
export { DateTimePicker, type DateTimePickerProps } from './DateTimePicker.js'
|
|
5
|
+
export { Input, type InputProps } from './Input.js'
|
|
6
|
+
export { Link, type LinkProps } from './Link.js'
|
|
7
|
+
export { ListBox, type ListBoxProps } from './ListBox.js'
|
|
8
|
+
export { ListView, makeColorBlock, type ListViewProps, type Column, type CellStyle, type Align } from './ListView.js'
|
|
9
|
+
export { ProgressBar, type ProgressBarProps } from './ProgressBar.js'
|
|
10
|
+
export { RadioButton, type RadioButtonProps } from './RadioButton.js'
|
|
11
|
+
export { ScrollView, type ScrollViewProps } from './ScrollView.js'
|
|
12
|
+
export { Slider, type SliderProps } from './Slider.js'
|
|
13
|
+
export { Tab, type TabProps } from './Tab.js'
|
|
14
|
+
export { Tooltip, type TooltipProps } from './Tooltip.js'
|
|
15
|
+
export { TreeView, type TreeViewProps, type TreeNode } from './TreeView.js'
|
|
16
|
+
export { PathPicker, type PathPickerProps } from './PathPicker.js'
|
|
17
|
+
|
package/lib/react-qw/index.ts
CHANGED
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
import * as gui from 'gui'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import reconciler, { scaleFactor, instancesByHwnd, forceFlexLayout, type Instance } from './reconciler.js'
|
|
4
|
-
|
|
5
|
-
const noop = () => { }
|
|
6
|
-
|
|
7
|
-
export interface RootWindowConfig {
|
|
8
|
-
text?: string
|
|
9
|
-
ws?: number
|
|
10
|
-
x?: number
|
|
11
|
-
y?: number
|
|
12
|
-
width?: number
|
|
13
|
-
height?: number
|
|
14
|
-
noShowWindow?: boolean
|
|
15
|
-
onEvent?: (e: { hwnd: gui.HWND; msg: number; wParam: number; lParam: number }) => number | void
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
let defaultClassRegistered = false
|
|
19
|
-
const DEFAULT_CLASS = '_QuickWinDefault'
|
|
20
|
-
const rootMap = new Map<gui.HWND, { root: ReturnType<typeof reconciler.createContainer>, onEvent?: RootWindowConfig['onEvent'] }>()
|
|
21
|
-
|
|
22
|
-
function ensureDefaultClass() {
|
|
23
|
-
if (defaultClassRegistered) return DEFAULT_CLASS
|
|
24
|
-
gui.RegisterClass(DEFAULT_CLASS, (hwnd, msg, wParam, lParam) => {
|
|
25
|
-
const entry = rootMap.get(hwnd)
|
|
26
|
-
if (msg === gui.WmMsg.DESTROY && entry) {
|
|
27
|
-
rootMap.delete(hwnd)
|
|
28
|
-
reconciler.updateContainer(null, entry.root, null, () => {
|
|
29
|
-
instancesByHwnd.delete(hwnd)
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
const result = entry?.onEvent?.({ hwnd, msg, wParam, lParam })
|
|
33
|
-
if (typeof result === 'number') return result
|
|
34
|
-
if (msg === gui.WmMsg.SIZE) forceFlexLayout(hwnd)
|
|
35
|
-
return gui.DefWindowProc(hwnd, msg, wParam, lParam)
|
|
36
|
-
})
|
|
37
|
-
defaultClassRegistered = true
|
|
38
|
-
return DEFAULT_CLASS
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function createRoot(container: gui.HWND | RootWindowConfig) {
|
|
42
|
-
let hwnd: gui.HWND
|
|
43
|
-
if (typeof container === 'object') {
|
|
44
|
-
const cfg = container
|
|
45
|
-
const className = ensureDefaultClass()
|
|
46
|
-
const ws = (cfg.ws ?? 0) | gui.WindowStyle.OVERLAPPEDWINDOW
|
|
47
|
-
const w = (cfg.width ?? 800) * scaleFactor
|
|
48
|
-
const h = (cfg.height ?? 600) * scaleFactor
|
|
49
|
-
const [sw, sh] = gui.GetScreenSize()
|
|
50
|
-
const x = cfg.x === undefined ? ((sw - w) / 2) | 0
|
|
51
|
-
: cfg.x === gui.CreatePos.USEDEFAULT ? gui.CreatePos.USEDEFAULT
|
|
52
|
-
: cfg.x * scaleFactor
|
|
53
|
-
const y = cfg.y === undefined ? ((sh - h) / 2) | 0
|
|
54
|
-
: cfg.y === gui.CreatePos.USEDEFAULT ? gui.CreatePos.USEDEFAULT
|
|
55
|
-
: cfg.y * scaleFactor
|
|
56
|
-
const hwin = gui.CreateWindow(className, cfg.text || '', ws, x, y, w, h, null, null)
|
|
57
|
-
if (!hwin) throw new Error('CreateWindow failed')
|
|
58
|
-
hwnd = hwin
|
|
59
|
-
if (!cfg.noShowWindow) gui.ShowWindow(hwnd)
|
|
60
|
-
} else {
|
|
61
|
-
hwnd = container
|
|
62
|
-
}
|
|
63
|
-
const root = reconciler.createContainer(
|
|
64
|
-
hwnd, 0, null, false, null, '',
|
|
65
|
-
noop, noop, noop, noop,
|
|
66
|
-
)
|
|
67
|
-
const rootInst: Instance = { hwnd, type: '_root', props: { type: '_root', style: { flexDirection: 'column', alignItems: 'stretch' } }, children: [] }
|
|
68
|
-
instancesByHwnd.set(hwnd, rootInst)
|
|
69
|
-
if (typeof container === 'object')
|
|
70
|
-
rootMap.set(hwnd, { root, onEvent: container.onEvent })
|
|
71
|
-
return {
|
|
72
|
-
hwnd,
|
|
73
|
-
render(element: React.ReactNode) {
|
|
74
|
-
reconciler.updateContainer(element, root, null, noop)
|
|
75
|
-
},
|
|
76
|
-
unmount() {
|
|
77
|
-
reconciler.updateContainer(null, root, null, noop)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export * from './components/index.js'
|
|
83
|
-
|
|
84
|
-
export function render(element: React.ReactNode, containerOrConfig?: gui.HWND | RootWindowConfig | null, _callback?: () => void) {
|
|
85
|
-
if (containerOrConfig == null) {
|
|
86
|
-
throw new Error('render() requires a window handle or RootWindowConfig as second argument')
|
|
87
|
-
}
|
|
88
|
-
const root = createRoot(containerOrConfig)
|
|
89
|
-
root.render(element)
|
|
90
|
-
}
|
|
1
|
+
import * as gui from 'gui'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import reconciler, { scaleFactor, instancesByHwnd, forceFlexLayout, type Instance } from './reconciler.js'
|
|
4
|
+
|
|
5
|
+
const noop = () => { }
|
|
6
|
+
|
|
7
|
+
export interface RootWindowConfig {
|
|
8
|
+
text?: string
|
|
9
|
+
ws?: number
|
|
10
|
+
x?: number
|
|
11
|
+
y?: number
|
|
12
|
+
width?: number
|
|
13
|
+
height?: number
|
|
14
|
+
noShowWindow?: boolean
|
|
15
|
+
onEvent?: (e: { hwnd: gui.HWND; msg: number; wParam: number; lParam: number }) => number | void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let defaultClassRegistered = false
|
|
19
|
+
const DEFAULT_CLASS = '_QuickWinDefault'
|
|
20
|
+
const rootMap = new Map<gui.HWND, { root: ReturnType<typeof reconciler.createContainer>, onEvent?: RootWindowConfig['onEvent'] }>()
|
|
21
|
+
|
|
22
|
+
function ensureDefaultClass() {
|
|
23
|
+
if (defaultClassRegistered) return DEFAULT_CLASS
|
|
24
|
+
gui.RegisterClass(DEFAULT_CLASS, (hwnd, msg, wParam, lParam) => {
|
|
25
|
+
const entry = rootMap.get(hwnd)
|
|
26
|
+
if (msg === gui.WmMsg.DESTROY && entry) {
|
|
27
|
+
rootMap.delete(hwnd)
|
|
28
|
+
reconciler.updateContainer(null, entry.root, null, () => {
|
|
29
|
+
instancesByHwnd.delete(hwnd)
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
const result = entry?.onEvent?.({ hwnd, msg, wParam, lParam })
|
|
33
|
+
if (typeof result === 'number') return result
|
|
34
|
+
if (msg === gui.WmMsg.SIZE) forceFlexLayout(hwnd)
|
|
35
|
+
return gui.DefWindowProc(hwnd, msg, wParam, lParam)
|
|
36
|
+
})
|
|
37
|
+
defaultClassRegistered = true
|
|
38
|
+
return DEFAULT_CLASS
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function createRoot(container: gui.HWND | RootWindowConfig) {
|
|
42
|
+
let hwnd: gui.HWND
|
|
43
|
+
if (typeof container === 'object') {
|
|
44
|
+
const cfg = container
|
|
45
|
+
const className = ensureDefaultClass()
|
|
46
|
+
const ws = (cfg.ws ?? 0) | gui.WindowStyle.OVERLAPPEDWINDOW
|
|
47
|
+
const w = (cfg.width ?? 800) * scaleFactor
|
|
48
|
+
const h = (cfg.height ?? 600) * scaleFactor
|
|
49
|
+
const [sw, sh] = gui.GetScreenSize()
|
|
50
|
+
const x = cfg.x === undefined ? ((sw - w) / 2) | 0
|
|
51
|
+
: cfg.x === gui.CreatePos.USEDEFAULT ? gui.CreatePos.USEDEFAULT
|
|
52
|
+
: cfg.x * scaleFactor
|
|
53
|
+
const y = cfg.y === undefined ? ((sh - h) / 2) | 0
|
|
54
|
+
: cfg.y === gui.CreatePos.USEDEFAULT ? gui.CreatePos.USEDEFAULT
|
|
55
|
+
: cfg.y * scaleFactor
|
|
56
|
+
const hwin = gui.CreateWindow(className, cfg.text || '', ws, x, y, w, h, null, null)
|
|
57
|
+
if (!hwin) throw new Error('CreateWindow failed')
|
|
58
|
+
hwnd = hwin
|
|
59
|
+
if (!cfg.noShowWindow) gui.ShowWindow(hwnd)
|
|
60
|
+
} else {
|
|
61
|
+
hwnd = container
|
|
62
|
+
}
|
|
63
|
+
const root = reconciler.createContainer(
|
|
64
|
+
hwnd, 0, null, false, null, '',
|
|
65
|
+
noop, noop, noop, noop,
|
|
66
|
+
)
|
|
67
|
+
const rootInst: Instance = { hwnd, type: '_root', props: { type: '_root', style: { flexDirection: 'column', alignItems: 'stretch' } }, children: [] }
|
|
68
|
+
instancesByHwnd.set(hwnd, rootInst)
|
|
69
|
+
if (typeof container === 'object')
|
|
70
|
+
rootMap.set(hwnd, { root, onEvent: container.onEvent })
|
|
71
|
+
return {
|
|
72
|
+
hwnd,
|
|
73
|
+
render(element: React.ReactNode) {
|
|
74
|
+
reconciler.updateContainer(element, root, null, noop)
|
|
75
|
+
},
|
|
76
|
+
unmount() {
|
|
77
|
+
reconciler.updateContainer(null, root, null, noop)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export * from './components/index.js'
|
|
83
|
+
|
|
84
|
+
export function render(element: React.ReactNode, containerOrConfig?: gui.HWND | RootWindowConfig | null, _callback?: () => void) {
|
|
85
|
+
if (containerOrConfig == null) {
|
|
86
|
+
throw new Error('render() requires a window handle or RootWindowConfig as second argument')
|
|
87
|
+
}
|
|
88
|
+
const root = createRoot(containerOrConfig)
|
|
89
|
+
root.render(element)
|
|
90
|
+
}
|
package/lib/react-qw/jsx.d.ts
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import type { HWND } from 'gui'
|
|
2
|
-
|
|
3
|
-
interface WStyle {
|
|
4
|
-
width?: number | 'auto'; height?: number | 'auto'
|
|
5
|
-
flexDirection?: 'row' | 'column'
|
|
6
|
-
justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly'
|
|
7
|
-
alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch'
|
|
8
|
-
alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch'
|
|
9
|
-
gap?: number
|
|
10
|
-
padding?: number
|
|
11
|
-
paddingTop?: number
|
|
12
|
-
paddingRight?: number
|
|
13
|
-
paddingBottom?: number
|
|
14
|
-
paddingLeft?: number
|
|
15
|
-
flexGrow?: number
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface WEvent {
|
|
19
|
-
hwnd: HWND; msg: number; wParam: number; lParam: number
|
|
20
|
-
}
|
|
21
|
-
interface WOnEventObj {
|
|
22
|
-
fn: (e: WEvent & {callOldWndProc: () => number}) => number
|
|
23
|
-
}
|
|
24
|
-
interface WIntrinsicProps {
|
|
25
|
-
key?: string | number; type: string; text?: string; ws?: number
|
|
26
|
-
disabled?: boolean; visible?: boolean; hidden?: boolean; style?: WStyle
|
|
27
|
-
onEvent?: ((e: WEvent) => number | void) | WOnEventObj
|
|
28
|
-
children?: React.ReactNode
|
|
29
|
-
ref?: React.Ref<HWND>
|
|
30
|
-
}
|
|
31
|
-
declare module 'react' {
|
|
32
|
-
namespace JSX { interface IntrinsicElements { w: WIntrinsicProps } }
|
|
33
|
-
}
|
|
34
|
-
export type { WEvent, WIntrinsicProps, WStyle }
|
|
1
|
+
import type { HWND } from 'gui'
|
|
2
|
+
|
|
3
|
+
interface WStyle {
|
|
4
|
+
width?: number | 'auto'; height?: number | 'auto'
|
|
5
|
+
flexDirection?: 'row' | 'column'
|
|
6
|
+
justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly'
|
|
7
|
+
alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch'
|
|
8
|
+
alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch'
|
|
9
|
+
gap?: number
|
|
10
|
+
padding?: number
|
|
11
|
+
paddingTop?: number
|
|
12
|
+
paddingRight?: number
|
|
13
|
+
paddingBottom?: number
|
|
14
|
+
paddingLeft?: number
|
|
15
|
+
flexGrow?: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface WEvent {
|
|
19
|
+
hwnd: HWND; msg: number; wParam: number; lParam: number
|
|
20
|
+
}
|
|
21
|
+
interface WOnEventObj {
|
|
22
|
+
fn: (e: WEvent & {callOldWndProc: () => number}) => number
|
|
23
|
+
}
|
|
24
|
+
interface WIntrinsicProps {
|
|
25
|
+
key?: string | number; type: string; text?: string; ws?: number
|
|
26
|
+
disabled?: boolean; visible?: boolean; hidden?: boolean; style?: WStyle
|
|
27
|
+
onEvent?: ((e: WEvent) => number | void) | WOnEventObj
|
|
28
|
+
children?: React.ReactNode
|
|
29
|
+
ref?: React.Ref<HWND>
|
|
30
|
+
}
|
|
31
|
+
declare module 'react' {
|
|
32
|
+
namespace JSX { interface IntrinsicElements { w: WIntrinsicProps } }
|
|
33
|
+
}
|
|
34
|
+
export type { WEvent, WIntrinsicProps, WStyle }
|