quickwin 3.0.0 → 3.0.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.
Files changed (95) hide show
  1. package/lib/abort.d.ts +21 -0
  2. package/lib/assert.d.ts +2 -0
  3. package/lib/bitmap.d.ts +7 -0
  4. package/lib/cache-utils.d.ts +6 -0
  5. package/lib/certs.d.ts +1 -0
  6. package/lib/dpi.d.ts +9 -0
  7. package/lib/dumpRects.d.ts +2 -0
  8. package/lib/exec-log.d.ts +23 -0
  9. package/lib/fetch.d.ts +4 -0
  10. package/lib/ffi/bind.d.ts +70 -0
  11. package/lib/ffi/ctype.d.ts +117 -0
  12. package/lib/ffi/index.d.ts +2 -0
  13. package/lib/ffi/struct.d.ts +174 -0
  14. package/lib/http-common.d.ts +143 -0
  15. package/lib/http-server.d.ts +59 -0
  16. package/lib/polyfill.d.ts +22 -0
  17. package/lib/react-qw/components/Button.d.ts +9 -0
  18. package/lib/react-qw/components/CheckBox.d.ts +11 -0
  19. package/lib/react-qw/components/ComboBox.d.ts +11 -0
  20. package/lib/react-qw/components/DateTimePicker.d.ts +15 -0
  21. package/lib/react-qw/components/Input.d.ts +15 -0
  22. package/lib/react-qw/components/Link.d.ts +12 -0
  23. package/lib/react-qw/components/ListBox.d.ts +13 -0
  24. package/lib/react-qw/components/ListView.d.ts +37 -0
  25. package/lib/react-qw/components/PathPicker.d.ts +23 -0
  26. package/lib/react-qw/components/ProgressBar.d.ts +9 -0
  27. package/lib/react-qw/components/RadioButton.d.ts +11 -0
  28. package/lib/react-qw/components/ScrollView.d.ts +9 -0
  29. package/lib/react-qw/components/Slider.d.ts +12 -0
  30. package/lib/react-qw/components/Tab.d.ts +14 -0
  31. package/lib/react-qw/components/Tooltip.d.ts +7 -0
  32. package/lib/react-qw/components/TreeView.d.ts +18 -0
  33. package/lib/react-qw/components/index.d.ts +16 -0
  34. package/lib/react-qw/index.d.ts +24 -0
  35. package/lib/react-qw/layout.d.ts +29 -0
  36. package/lib/react-qw/nmhdr.d.ts +1 -0
  37. package/lib/react-qw/props.d.ts +2 -0
  38. package/lib/react-qw/reconciler.d.ts +21 -0
  39. package/lib/stream.d.ts +20 -0
  40. package/lib/text-codec.d.ts +39 -0
  41. package/lib/text-measure.d.ts +14 -0
  42. package/lib/url.d.ts +54 -0
  43. package/lib/websocket.d.ts +73 -0
  44. package/lib/windows/{advapi32.ts → advapi32.d.ts} +6 -21
  45. package/lib/windows/comctl32.d.ts +14 -0
  46. package/lib/windows/comdlg32.d.ts +4 -0
  47. package/lib/windows/{gdi32.ts → gdi32.d.ts} +161 -98
  48. package/lib/windows/{kernel32.ts → kernel32.d.ts} +138 -115
  49. package/lib/windows/{msimg32.ts → msimg32.d.ts} +11 -14
  50. package/lib/windows/ntdll.d.ts +5 -0
  51. package/lib/windows/ole32.d.ts +3 -0
  52. package/lib/windows/{psapi.ts → psapi.d.ts} +9 -18
  53. package/lib/windows/{shell32.ts → shell32.d.ts} +25 -24
  54. package/lib/windows/structs.d.ts +3141 -0
  55. package/lib/windows/{user32.ts → user32.d.ts} +196 -193
  56. package/lib/windows/version.d.ts +27 -0
  57. package/lib/windows/{winspool.ts → winspool.d.ts} +18 -32
  58. package/package.json +15 -6
  59. package/qwin-nowasm-x86.exe +0 -0
  60. package/qwin-nowasm.exe +0 -0
  61. package/qwin-x86.exe +0 -0
  62. package/qwin.exe +0 -0
  63. package/lib/abort.ts +0 -69
  64. package/lib/assert.ts +0 -7
  65. package/lib/bitmap.ts +0 -39
  66. package/lib/cache-utils.ts +0 -40
  67. package/lib/certs.ts +0 -258
  68. package/lib/dpi.ts +0 -31
  69. package/lib/dumpRects.ts +0 -34
  70. package/lib/exec-log.ts +0 -30
  71. package/lib/fetch.ts +0 -589
  72. package/lib/ffi/bind.ts +0 -540
  73. package/lib/ffi/ctype.ts +0 -371
  74. package/lib/ffi/index.ts +0 -6
  75. package/lib/ffi/struct.ts +0 -780
  76. package/lib/http-common.ts +0 -441
  77. package/lib/http-server.ts +0 -604
  78. package/lib/polyfill.ts +0 -171
  79. package/lib/react-qw/components/index.ts +0 -17
  80. package/lib/react-qw/index.ts +0 -96
  81. package/lib/react-qw/layout.ts +0 -111
  82. package/lib/react-qw/nmhdr.ts +0 -7
  83. package/lib/react-qw/props.ts +0 -41
  84. package/lib/react-qw/reconciler.ts +0 -379
  85. package/lib/stream.ts +0 -22
  86. package/lib/text-codec.ts +0 -171
  87. package/lib/text-measure.ts +0 -44
  88. package/lib/url.ts +0 -201
  89. package/lib/websocket.ts +0 -600
  90. package/lib/windows/comctl32.ts +0 -20
  91. package/lib/windows/comdlg32.ts +0 -10
  92. package/lib/windows/ntdll.ts +0 -11
  93. package/lib/windows/ole32.ts +0 -9
  94. package/lib/windows/structs.ts +0 -807
  95. package/lib/windows/version.ts +0 -35
package/lib/websocket.ts DELETED
@@ -1,600 +0,0 @@
1
- import '../lib/polyfill.js'
2
- import * as sock from 'sock'
3
- import * as wolfssl from 'wolfssl'
4
- import * as os from 'os'
5
- import { FdEvent, ReturnCode, SniType, VerifyMode, WolfsslErrorCode } from '../constants'
6
-
7
- // ── Constants ──
8
-
9
- const MAGIC_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
10
-
11
- enum State {
12
- CONNECTING = 0,
13
- OPEN = 1,
14
- CLOSING = 2,
15
- CLOSED = 3,
16
- }
17
-
18
- enum Opcode {
19
- CONTINUATION = 0x0,
20
- TEXT = 0x1,
21
- BINARY = 0x2,
22
- CLOSE = 0x8,
23
- PING = 0x9,
24
- PONG = 0xA,
25
- }
26
-
27
- // ── Random key generation ──
28
-
29
- function generateKey(): string {
30
- const bytes = new Uint8Array(16)
31
- crypto.getRandomValues(bytes)
32
- return btoa(String.fromCharCode(...bytes))
33
- }
34
-
35
- async function computeAccept(key: string): Promise<string> {
36
- const data = new TextEncoder().encode(key + MAGIC_GUID)
37
- const hash = await crypto.subtle.digest('SHA-1', data)
38
- const hashBytes = new Uint8Array(hash)
39
- return btoa(String.fromCharCode(...hashBytes))
40
- }
41
-
42
- // ── Frame helpers ──
43
-
44
- function createFrame(opcode: number, payload: Uint8Array): ArrayBuffer {
45
- const maskingKey = new Uint8Array(4)
46
- for (let i = 0; i < 4; i++) maskingKey[i] = (Math.random() * 256) | 0
47
-
48
- let headerSize: number
49
- if (payload.length < 126) {
50
- headerSize = 6
51
- } else if (payload.length < 65536) {
52
- headerSize = 8
53
- } else {
54
- headerSize = 14
55
- }
56
-
57
- const buf = new ArrayBuffer(headerSize + payload.length)
58
- const view = new Uint8Array(buf)
59
- let off = 0
60
-
61
- view[off++] = 0x80 | opcode
62
- view[off++] = 0x80 | (payload.length < 126 ? payload.length :
63
- payload.length < 65536 ? 126 : 127)
64
-
65
- if (payload.length >= 126 && payload.length < 65536) {
66
- view[off++] = (payload.length >> 8) & 0xFF
67
- view[off++] = payload.length & 0xFF
68
- } else if (payload.length >= 65536) {
69
- const len = payload.length
70
- const hi = (len / 0x100000000) >>> 0
71
- const lo = len >>> 0
72
- view[off++] = (hi >> 24) & 0xFF
73
- view[off++] = (hi >> 16) & 0xFF
74
- view[off++] = (hi >> 8) & 0xFF
75
- view[off++] = hi & 0xFF
76
- view[off++] = (lo >> 24) & 0xFF
77
- view[off++] = (lo >> 16) & 0xFF
78
- view[off++] = (lo >> 8) & 0xFF
79
- view[off++] = lo & 0xFF
80
- }
81
-
82
- view[off++] = maskingKey[0]!
83
- view[off++] = maskingKey[1]!
84
- view[off++] = maskingKey[2]!
85
- view[off++] = maskingKey[3]!
86
-
87
- for (let i = 0; i < payload.length; i++) {
88
- view[off++] = payload[i]! ^ maskingKey[i % 4]!
89
- }
90
-
91
- return buf
92
- }
93
-
94
- function createCloseFrame(code: number, reason: string): ArrayBuffer {
95
- const reasonBytes = new Uint8Array([(code >> 8) & 0xFF, code & 0xFF, ...new TextEncoder().encode(reason)])
96
- return createFrame(Opcode.CLOSE, reasonBytes)
97
- }
98
-
99
- // ── Frame parser (returns null if incomplete) ──
100
-
101
- interface ParsedFrame {
102
- opcode: number
103
- payload: Uint8Array
104
- fin: boolean
105
- totalLen: number
106
- }
107
-
108
- function tryParseFrame(buffer: Uint8Array): ParsedFrame | null {
109
- if (buffer.length < 2) return null
110
-
111
- const b0 = buffer[0]!
112
- const b1 = buffer[1]!
113
- const fin = (b0 & 0x80) !== 0
114
- const opcode = b0 & 0x0F
115
- const masked = (b1 & 0x80) !== 0
116
- let payloadLen = b1 & 0x7F
117
- let offset = 2
118
-
119
- if (payloadLen === 126) {
120
- if (buffer.length < 4) return null
121
- payloadLen = (buffer[2]! << 8) | buffer[3]!
122
- offset = 4
123
- } else if (payloadLen === 127) {
124
- if (buffer.length < 10) return null
125
- let hi = 0, lo = 0
126
- for (let i = 0; i < 4; i++) hi = (hi * 256 + buffer[offset + i]!) >>> 0
127
- for (let i = 4; i < 8; i++) lo = (lo * 256 + buffer[offset + i]!) >>> 0
128
- payloadLen = hi * 0x100000000 + lo
129
- offset = 10
130
- }
131
-
132
- if (masked) offset += 4
133
-
134
- const totalLen = offset + payloadLen
135
- if (buffer.length < totalLen) return null
136
-
137
- let payload: Uint8Array
138
- if (masked) {
139
- const maskKey = buffer.slice(offset - 4, offset)
140
- payload = new Uint8Array(payloadLen)
141
- for (let i = 0; i < payloadLen; i++) {
142
- payload[i] = buffer[offset + i]! ^ maskKey[i % 4]!
143
- }
144
- } else {
145
- payload = buffer.slice(offset, offset + payloadLen)
146
- }
147
-
148
- return { opcode, payload, fin, totalLen }
149
- }
150
-
151
- // ── WebSocket class ──
152
-
153
- interface WebSocketOptions {
154
- headers?: Record<string, string>
155
- /** Non-standard: when false, TLS certificate verification is skipped
156
- * (mirrors Node's tls.connect rejectUnauthorized option). */
157
- rejectUnauthorized?: boolean
158
- }
159
-
160
-
161
-
162
- class WebSocketImpl {
163
- readonly url: string
164
- readyState: State = State.CONNECTING
165
- onopen: ((event: Event) => void) | null = null
166
- onclose: ((event: CloseEvent) => void) | null = null
167
- onerror: ((event: Event) => void) | null = null
168
- onmessage: ((event: MessageEvent) => void) | null = null
169
-
170
- private _options: WebSocketOptions
171
- private _sock: sock.SockHandle | null = null
172
- private _ssl: wolfssl.WOLFSSL | null = null
173
- private _ctx: wolfssl.WOLFSSL_CTX | null = null
174
- private _readBuffer: Uint8Array = new Uint8Array(0)
175
- private _state: State = State.CONNECTING
176
- private _processingHandshake: boolean = false
177
- static readonly CONNECTING = State.CONNECTING
178
- static readonly OPEN = State.OPEN
179
- static readonly CLOSING = State.CLOSING
180
- static readonly CLOSED = State.CLOSED
181
-
182
- private _closeCode: number = 1005
183
- private _closeReason: string = ''
184
-
185
- constructor(url: string, options?: WebSocketOptions) {
186
- this.url = url
187
- this._options = options || {}
188
- this._connect()
189
- }
190
-
191
- send(data: string | ArrayBuffer | Uint8Array): void {
192
- if (this._state !== State.OPEN) return
193
-
194
- let payload: Uint8Array
195
- if (typeof data === 'string') {
196
- payload = new TextEncoder().encode(data)
197
- const frame = createFrame(Opcode.TEXT, payload)
198
- this._sendRaw(frame)
199
- } else if (data instanceof ArrayBuffer) {
200
- payload = new Uint8Array(data)
201
- const frame = createFrame(Opcode.BINARY, payload)
202
- this._sendRaw(frame)
203
- } else if (data instanceof Uint8Array) {
204
- const frame = createFrame(Opcode.BINARY, data)
205
- this._sendRaw(frame)
206
- }
207
- }
208
-
209
- close(code?: number, reason?: string): void {
210
- if (this._state === State.CLOSED || this._state === State.CLOSING) return
211
- this._state = State.CLOSING
212
-
213
- const closeCode = code || 1000
214
- const closeReason = reason || ''
215
- this._closeCode = closeCode
216
- this._closeReason = closeReason
217
- const frame = createCloseFrame(closeCode, closeReason)
218
- this._sendRaw(frame)
219
-
220
- this._cleanup()
221
- this._setState(State.CLOSED)
222
- }
223
-
224
- private _connect(): void {
225
- let url: URL
226
- try { url = new URL(this.url) } catch {
227
- const self = this
228
- os.setTimeout(() => {
229
- self._fireError(new Error('Invalid WebSocket URL: ' + self.url))
230
- self._setState(State.CLOSED)
231
- }, 0)
232
- return
233
- }
234
- if (url.protocol !== 'ws:' && url.protocol !== 'wss:') {
235
- const self = this
236
- os.setTimeout(() => {
237
- self._fireError(new Error('Unsupported WebSocket scheme: ' + url.protocol))
238
- self._setState(State.CLOSED)
239
- }, 0)
240
- return
241
- }
242
- const host = url.hostname
243
- const hostHeader = host.includes(':') ? `[${host}]` : host
244
- const isWSS = url.protocol === 'wss:'
245
- const port = url.port ? parseInt(url.port, 10) : (isWSS ? 443 : 80)
246
- const path = url.pathname + (url.search || '')
247
-
248
- const requestKey = generateKey()
249
-
250
- const customHeadersList: string[] = []
251
- let hasUserAgent = false
252
- if (this._options.headers) {
253
- for (const name in this._options.headers) {
254
- const value = this._options.headers[name]
255
- customHeadersList.push(name + ': ' + value + '\r\n')
256
- if (name.toLowerCase() === 'user-agent') hasUserAgent = true
257
- }
258
- }
259
- const customHeaders = customHeadersList.join('')
260
-
261
- const request = (
262
- 'GET ' + path + ' HTTP/1.1\r\n' +
263
- 'Host: ' + hostHeader + ':' + port + '\r\n' +
264
- 'Upgrade: websocket\r\n' +
265
- 'Connection: Upgrade\r\n' +
266
- 'Sec-WebSocket-Key: ' + requestKey + '\r\n' +
267
- 'Sec-WebSocket-Version: 13\r\n' +
268
- (hasUserAgent ? '' : 'User-Agent: ' + navigator.userAgent + '\r\n') +
269
- customHeaders +
270
- '\r\n'
271
- )
272
-
273
- let state: 'resolve' | 'connect' | 'handshake' | 'request' | 'open' = 'resolve'
274
- let headerBuffer = ''
275
- let resolved = false
276
-
277
- const cleanup = (): void => {
278
- if (this._ssl) { wolfssl.wolfSSL_free(this._ssl); this._ssl = null }
279
- if (this._ctx) { wolfssl.wolfSSL_CTX_free(this._ctx); this._ctx = null }
280
- if (this._sock !== null && this._sock >= 0) { sock.closesocket(this._sock); this._sock = null }
281
- }
282
-
283
- const doError = (err: Error): void => {
284
- if (resolved) return
285
- resolved = true
286
- cleanup()
287
- this._fireError(err)
288
- if (this._state !== State.CLOSED) this._setState(State.CLOSED)
289
- }
290
-
291
- this._sock = sock.socket()
292
- if (this._sock < 0) {
293
- const self = this
294
- os.setTimeout(() => {
295
- self._fireError(new Error('Failed to create socket'))
296
- if (self._state !== State.CLOSED) self._setState(State.CLOSED)
297
- }, 0)
298
- return
299
- }
300
- const fd = this._sock
301
-
302
- sock.set_on_event(fd, async (event: { lNetworkEvents: number; iErrorCode: number[] }) => {
303
- if (this._processingHandshake) return
304
- if (resolved && state === 'open') {
305
- if (event.lNetworkEvents & FdEvent.FD_READ) {
306
- this._onData()
307
- }
308
- if (event.lNetworkEvents & FdEvent.FD_CLOSE) {
309
- this._cleanup()
310
- this._setState(State.CLOSED)
311
- }
312
- return
313
- }
314
-
315
- if (event.lNetworkEvents & FdEvent.FD_CONNECT) {
316
- const errCode = event.iErrorCode[0]
317
- if (errCode !== 0) {
318
- doError(new Error('Connection failed: ' + errCode))
319
- return
320
- }
321
- if (isWSS) {
322
- const method = wolfssl.wolfTLSv1_2_client_method()
323
- this._ctx = wolfssl.wolfSSL_CTX_new(method)
324
- if (!this._ctx) { doError(new Error('SSL_CTX_new failed')); return }
325
- if (this._options.rejectUnauthorized === false) {
326
- wolfssl.wolfSSL_CTX_set_verify(this._ctx, VerifyMode.SSL_VERIFY_NONE)
327
- } else {
328
- wolfssl.wolfSSL_CTX_set_verify(this._ctx, VerifyMode.SSL_VERIFY_PEER)
329
- wolfssl.loadTrustedCerts(this._ctx)
330
- }
331
- this._ssl = wolfssl.wolfSSL_new(this._ctx)
332
- if (!this._ssl) { doError(new Error('SSL_new failed')); return }
333
- wolfssl.wolfSSL_set_fd(this._ssl, sock.get_fd(fd))
334
- const sniHost = host
335
- if (sniHost) {
336
- wolfssl.wolfSSL_UseSNI(this._ssl, SniType.WOLFSSL_SNI_HOST_NAME, sniHost)
337
- if (this._options.rejectUnauthorized !== false) {
338
- wolfssl.wolfSSL_check_domain_name(this._ssl, sniHost)
339
- }
340
- }
341
- state = 'handshake'
342
- } else {
343
- this._sendRawStr(request)
344
- state = 'request'
345
- }
346
- }
347
-
348
- if ((event.lNetworkEvents & FdEvent.FD_READ) || (event.lNetworkEvents & FdEvent.FD_WRITE)) {
349
- if (state === 'handshake') {
350
- if (!this._ssl) { doError(new Error('TLS not initialized')); return }
351
- const ret = wolfssl.wolfSSL_connect(this._ssl)
352
- if (ret === ReturnCode.SSL_SUCCESS) {
353
- this._sendRawStr(request)
354
- state = 'request'
355
- } else {
356
- const err = wolfssl.wolfSSL_get_error(this._ssl, ret)
357
- if (err !== WolfsslErrorCode.WOLFSSL_ERROR_WANT_READ &&
358
- err !== WolfsslErrorCode.WOLFSSL_ERROR_WANT_WRITE) {
359
- doError(new Error('TLS handshake failed: ' + err))
360
- }
361
- }
362
- }
363
- else if (state === 'request') {
364
- while (true) {
365
- let data: ArrayBuffer | null
366
- if (isWSS && this._ssl) {
367
- const buf = new ArrayBuffer(8192)
368
- const n = wolfssl.wolfSSL_read(this._ssl, buf)
369
- if (n > 0) {
370
- data = buf.slice(0, n)
371
- } else {
372
- const err = wolfssl.wolfSSL_get_error(this._ssl, n)
373
- if (err === WolfsslErrorCode.WOLFSSL_ERROR_WANT_READ ||
374
- err === WolfsslErrorCode.WOLFSSL_ERROR_WANT_WRITE) break
375
- if (n === 0 || err === WolfsslErrorCode.WOLFSSL_ERROR_ZERO_RETURN) break
376
- doError(new Error('TLS read failed: ' + err))
377
- return
378
- }
379
- } else if (this._sock !== null && this._sock >= 0) {
380
- data = sock.recv(this._sock, 8192)
381
- } else { break }
382
- if (!data || data.byteLength === 0) break
383
- headerBuffer += _ab2str(data)
384
- const headerEnd = headerBuffer.indexOf('\r\n\r\n')
385
- if (headerEnd >= 0) {
386
- const headerPart = headerBuffer.slice(0, headerEnd)
387
- const lines = headerPart.split('\r\n')
388
- const statusLine = lines[0]!
389
- const statusParts = statusLine.split(' ')
390
- if (statusParts.length < 2) {
391
- doError(new Error('Invalid HTTP status line: ' + statusLine))
392
- return
393
- }
394
- const statusCode = parseInt(statusParts[1]!, 10)
395
- if (statusCode !== 101) {
396
- doError(new Error('WebSocket handshake failed: HTTP ' + statusCode))
397
- return
398
- }
399
-
400
- let acceptHeader = ''
401
- for (let i = 1; i < lines.length; i++) {
402
- const line = lines[i]!
403
- const colonIdx2 = line.indexOf(':')
404
- if (colonIdx2 >= 0) {
405
- const name = line.slice(0, colonIdx2).toLowerCase().trim()
406
- if (name === 'sec-websocket-accept') {
407
- acceptHeader = line.slice(colonIdx2 + 1).trim()
408
- break
409
- }
410
- }
411
- }
412
- if (!acceptHeader) {
413
- doError(new Error('WebSocket handshake missing Sec-WebSocket-Accept'))
414
- return
415
- }
416
-
417
- this._processingHandshake = true
418
- const expectedAccept = await computeAccept(requestKey)
419
- if (acceptHeader !== expectedAccept) {
420
- doError(new Error('WebSocket handshake invalid Sec-WebSocket-Accept'))
421
- this._processingHandshake = false
422
- return
423
- }
424
-
425
- state = 'open'
426
- resolved = true
427
- this._processingHandshake = false
428
- this._setState(State.OPEN)
429
- break
430
- }
431
- }
432
- }
433
- }
434
-
435
- if (event.lNetworkEvents & FdEvent.FD_CLOSE) {
436
- if (state !== 'open') {
437
- doError(new Error('Connection closed'))
438
- }
439
- }
440
- })
441
-
442
- const ip = sock.resolve(host)
443
- if (!ip) {
444
- cleanup()
445
- const self = this
446
- os.setTimeout(() => {
447
- self._fireError(new Error('DNS resolution failed for: ' + host))
448
- if (self._state !== State.CLOSED) self._setState(State.CLOSED)
449
- }, 0)
450
- return
451
- }
452
- sock.connect(fd, ip, port)
453
- }
454
-
455
- private _sendRaw(buf: ArrayBuffer): void {
456
- if (this._sock === null || this._sock < 0) return
457
- if (this._ssl) {
458
- wolfssl.wolfSSL_write(this._ssl, buf)
459
- } else {
460
- sock.send(this._sock, buf)
461
- }
462
- }
463
-
464
- private _sendRawStr(str: string): void {
465
- const buf = new ArrayBuffer(str.length)
466
- const view = new Uint8Array(buf)
467
- for (let i = 0; i < str.length; i++) view[i] = str.charCodeAt(i) & 0xFF
468
- this._sendRaw(buf)
469
- }
470
-
471
- private _onData(): void {
472
- while (true) {
473
- let data: ArrayBuffer | null
474
- if (this._ssl) {
475
- const buf = new ArrayBuffer(8192)
476
- const n = wolfssl.wolfSSL_read(this._ssl, buf)
477
- if (n > 0) {
478
- data = buf.slice(0, n)
479
- } else {
480
- const err = wolfssl.wolfSSL_get_error(this._ssl, n)
481
- if (err === WolfsslErrorCode.WOLFSSL_ERROR_WANT_READ ||
482
- err === WolfsslErrorCode.WOLFSSL_ERROR_WANT_WRITE) break
483
- if (n === 0 || err === WolfsslErrorCode.WOLFSSL_ERROR_ZERO_RETURN) break
484
- this._fireError(new Error('TLS read failed: ' + err))
485
- if (this._state !== State.CLOSED) this._setState(State.CLOSED)
486
- return
487
- }
488
- } else if (this._sock !== null && this._sock >= 0) {
489
- data = sock.recv(this._sock, 8192)
490
- } else { break }
491
- if (!data || data.byteLength === 0) break
492
-
493
- const newBuf = new Uint8Array(this._readBuffer.length + data.byteLength)
494
- newBuf.set(this._readBuffer)
495
- newBuf.set(new Uint8Array(data), this._readBuffer.length)
496
- this._readBuffer = newBuf
497
-
498
- while (true) {
499
- const frame = tryParseFrame(this._readBuffer)
500
- if (!frame) break
501
-
502
- this._readBuffer = this._readBuffer.slice(frame.totalLen)
503
-
504
- if (frame.opcode === Opcode.TEXT || frame.opcode === Opcode.BINARY) {
505
- const event = new MessageEvent('message', { data: frame.opcode === Opcode.TEXT ? _ab2str(frame.payload.slice(0).buffer) : frame.payload.slice(0).buffer })
506
- this._dispatchEvent('message', event)
507
- } else if (frame.opcode === Opcode.PING) {
508
- const pong = createFrame(Opcode.PONG, frame.payload)
509
- this._sendRaw(pong)
510
- } else if (frame.opcode === Opcode.PONG) {
511
- } else if (frame.opcode === Opcode.CLOSE) {
512
- if (frame.payload.length >= 2) {
513
- this._closeCode = (frame.payload[0]! << 8) | frame.payload[1]!
514
- this._closeReason = _ab2str(frame.payload.slice(2).buffer)
515
- }
516
- this._cleanup()
517
- this._setState(State.CLOSED)
518
- return
519
- }
520
- }
521
- }
522
- }
523
-
524
- private _setState(state: State): void {
525
- if (this._state === state) return
526
- this.readyState = state
527
- this._state = state
528
-
529
- if (state === State.OPEN) {
530
- this._dispatchEvent('open', new Event('open'))
531
- } else if (state === State.CLOSED) {
532
- const event = new CloseEvent('close', { code: this._closeCode, reason: this._closeReason, wasClean: true })
533
- this._dispatchEvent('close', event)
534
- }
535
- }
536
-
537
- private _dispatchEvent(type: string, event: Event | MessageEvent | CloseEvent): void {
538
- if (type === 'open' && this.onopen) this.onopen(event as Event)
539
- else if (type === 'close' && this.onclose) this.onclose(event as CloseEvent)
540
- else if (type === 'error' && this.onerror) this.onerror(event as Event)
541
- else if (type === 'message' && this.onmessage) this.onmessage(event as MessageEvent)
542
- }
543
-
544
- private _fireError(err: Error): void {
545
- console.error('WebSocket error:', err.message)
546
- this._dispatchEvent('error', new Event('error'))
547
- }
548
-
549
- private _cleanup(): void {
550
- if (this._ssl) { wolfssl.wolfSSL_free(this._ssl); this._ssl = null }
551
- if (this._ctx) { wolfssl.wolfSSL_CTX_free(this._ctx); this._ctx = null }
552
- if (this._sock !== null && this._sock >= 0) { sock.closesocket(this._sock); this._sock = null }
553
- }
554
- }
555
-
556
- // ── Event/MessageEvent/CloseEvent polyfills ──
557
-
558
- class Event {
559
- readonly type: string
560
- constructor(type: string, _init?: unknown) { this.type = type }
561
- }
562
-
563
- class MessageEvent {
564
- readonly type: string
565
- readonly data: unknown
566
- constructor(type: string, init: { data: unknown }) {
567
- this.type = type
568
- this.data = init.data
569
- }
570
- }
571
-
572
- class CloseEvent {
573
- readonly type: string
574
- readonly code: number
575
- readonly reason: string
576
- readonly wasClean: boolean
577
- constructor(type: string, init: { code?: number; reason?: string; wasClean?: boolean }) {
578
- this.type = type
579
- this.code = init.code || 0
580
- this.reason = init.reason || ''
581
- this.wasClean = init.wasClean || false
582
- }
583
- }
584
-
585
- // ── Utility ──
586
-
587
- function _ab2str(buf: ArrayBuffer): string {
588
- return new TextDecoder('utf-8').decode(buf)
589
- }
590
-
591
- // ── Global declarations ──
592
-
593
- declare global {
594
- interface WebSocket extends WebSocketImpl {}
595
- var WebSocket: typeof WebSocketImpl
596
- }
597
-
598
- // ── Register globals ──
599
-
600
- globalThis.WebSocket = WebSocketImpl
@@ -1,20 +0,0 @@
1
- // comctl32 绑定(ImageList 系列;HIMAGELIST 不透明句柄走 <HIMAGELIST>ptr 自产自收,
2
- // Add 的 hbm 位与 gdi32 的 <HGDIOBJ>ptr 同型互认——CreateBitmap 产物直传)
3
- import { bind } from '../ffi/bind.js'
4
-
5
- // dll 名部分应用(工厂转调保泛型 infer,见 lib/windows/user32.ts 头注释)
6
- const b = <const S extends string>(name: string, sig: S) => bind('comctl32.dll', name, sig)
7
- /** 建图像列表;配对 ImageListDestroy
8
- * @returns 图像列表句柄;失败 → NULL
9
- * @param args_0 cx/cy 图像尺寸 @param args_2 flags ILC_* 组合
10
- * @param args_3 cInitial 初始容量 @param args_4 cGrow 增长步长 */
11
- export const ImageListCreate = /*@__PURE__*/ b('ImageList_Create', 'i32 i32 u32 i32 i32 -> <HIMAGELIST>ptr')
12
- /** 加位图进图像列表
13
- * @returns 新索引(-1 失败)
14
- * @param args_0 himl 图像列表句柄
15
- * @param args_1 hbmImage 位图句柄(gdi32 <HGDIOBJ>ptr 产物,如 CreateCompatibleBitmap)
16
- * @param args_2 hbmMask 掩码位图;32bpp 图像传 NULL */
17
- export const ImageListAdd = /*@__PURE__*/ b('ImageList_Add', '<HIMAGELIST>ptr <HGDIOBJ>ptr <HGDIOBJ>ptr -> i32')
18
- /** 销毁图像列表
19
- * @returns 成功 → 非 0 */
20
- export const ImageListDestroy = /*@__PURE__*/ b('ImageList_Destroy', '<HIMAGELIST>ptr -> i32')
@@ -1,10 +0,0 @@
1
- // comdlg32 绑定(通用文件对话框;GetOpenFileName 无 A/W 混用——一律 W 版)
2
- import { bind } from '../ffi/bind.js'
3
-
4
- // dll 名部分应用(工厂转调保泛型 infer,见 lib/windows/user32.ts 头注释)
5
- const b = <const S extends string>(name: string, sig: S) => bind('comdlg32.dll', name, sig)
6
-
7
- /** 打开/保存文件对话框
8
- * @returns 用户确认 → 非 0(lpstrFile 缓冲即选中路径),取消/出错 → 0
9
- * @param args_0 pOpenfn OPENFILENAMEW.encode(...).ptr(lStructSize 必须 = OPENFILENAMEW.size,见 structs.ts) */
10
- export const GetOpenFileName = /*@__PURE__*/ b('GetOpenFileNameW', '<OPENFILENAMEW>ptr -> u32')
@@ -1,11 +0,0 @@
1
- // ntdll 绑定(仅 RtlGetVersion——绕过 GetVersionEx 的兼容性谎言取真实版本)
2
- import { bind } from '../ffi/bind.js'
3
-
4
- // dll 名部分应用(工厂转调保泛型 infer,见 lib/windows/user32.ts 头注释)
5
- const b = <const S extends string>(name: string, sig: S) => bind('ntdll.dll', name, sig)
6
-
7
- /** 取真实 OS 版本;缓冲必须用 OSVERSIONINFO_148(148B 特制布局,
8
- * 标准 OSVERSIONINFOW 会越界写坏调用方堆,见 structs.ts)
9
- * @returns 0 = 成功
10
- * @param args_0 lpVersionInformation OSVERSIONINFO_148.encode(...).ptr 出参缓冲 */
11
- export const RtlGetVersion = /*@__PURE__*/ b('RtlGetVersion', '<OSVERSIONINFO_148>ptr -> i32')
@@ -1,9 +0,0 @@
1
- // ole32 绑定(COM 内存管理;仅 CoTaskMemFree——shell 对话框返回的 PIDL 需它释放)
2
- import { bind } from '../ffi/bind.js'
3
-
4
- // dll 名部分应用(工厂转调保泛型 infer,见 lib/windows/user32.ts 头注释)
5
- const b = <const S extends string>(name: string, sig: S) => bind('ole32.dll', name, sig)
6
-
7
- /** 释放 CoTaskMemAlloc 分配的内存(SHBrowseForFolder 返回的 PIDL 等)
8
- * @param args_0 pv CoTaskMem 分配的指针(0/NULL 安全) */
9
- export const CoTaskMemFree = /*@__PURE__*/ b('CoTaskMemFree', '<>ptr -> void')