quickwin 3.0.1 → 3.0.3

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 (163) hide show
  1. package/README.en.md +3 -0
  2. package/README.md +2 -0
  3. package/package.json +2 -3
  4. package/qwin-nowasm-x86.exe +0 -0
  5. package/qwin-nowasm.exe +0 -0
  6. package/qwin-x86.exe +0 -0
  7. package/qwin.exe +0 -0
  8. package/examples/PdfCanvas.js +0 -38
  9. package/examples/PdfCanvas.tsx +0 -54
  10. package/examples/execd/main.js +0 -23379
  11. package/examples/execd/tray.js +0 -192
  12. package/examples/execd/worker.js +0 -122
  13. package/examples/pdf_preview2.js +0 -398
  14. package/examples/pdf_preview2.ts +0 -353
  15. package/examples/pdf_viewer.js +0 -22515
  16. package/examples/pdf_viewer.tsx +0 -228
  17. package/examples/test_gallery.js +0 -18692
  18. package/examples/test_gallery.tsx +0 -291
  19. package/examples/test_react_lazy.js +0 -18560
  20. package/examples/test_react_lazy.tsx +0 -65
  21. package/examples/test_react_listbox.js +0 -18562
  22. package/examples/test_react_listbox.tsx +0 -73
  23. package/examples/test_root_window.js +0 -18532
  24. package/examples/test_root_window.tsx +0 -41
  25. package/examples/test_tab.js +0 -18563
  26. package/examples/test_tab.tsx +0 -77
  27. package/examples/tray_demo.js +0 -86
  28. package/examples/tray_demo.tsx +0 -89
  29. package/test/add.wasm +0 -0
  30. package/test/bench_ffi_callraw.js +0 -235
  31. package/test/bench_ffi_callraw.ts +0 -235
  32. package/test/bench_ffi_overhead.js +0 -139
  33. package/test/bench_ffi_overhead.ts +0 -141
  34. package/test/bench_sendmessage.js +0 -104
  35. package/test/bench_sendmessage.ts +0 -100
  36. package/test/bench_sendmessage_nonnull.js +0 -187
  37. package/test/bench_sendmessage_nonnull.ts +0 -188
  38. package/test/complex.wasm +0 -0
  39. package/test/complex_imports.wasm +0 -0
  40. package/test/debug/http_server_e2e.js +0 -31
  41. package/test/debug/minwasm.js +0 -52
  42. package/test/debug/mupdf_debug.js +0 -86
  43. package/test/debug/wasm.js +0 -122
  44. package/test/debug/wasm_export_debug.js +0 -54
  45. package/test/debug/wasm_names.js +0 -36
  46. package/test/example.pdf +0 -0
  47. package/test/global_imports.wasm +0 -0
  48. package/test/import_func.wasm +0 -0
  49. package/test/imports.wasm +0 -0
  50. package/test/mupdf-cdn.js +0 -40
  51. package/test/mupdf-cdn.ts +0 -43
  52. package/test/run.js +0 -111
  53. package/test/run.ts +0 -116
  54. package/test/sjlj.wasm +0 -0
  55. package/test/test_basic.js +0 -7
  56. package/test/test_basic.ts +0 -9
  57. package/test/test_basic_fetch.js +0 -63
  58. package/test/test_basic_fetch.ts +0 -59
  59. package/test/test_brotli.js +0 -48
  60. package/test/test_brotli.ts +0 -52
  61. package/test/test_fetch_cache.js +0 -169
  62. package/test/test_fetch_cache.ts +0 -187
  63. package/test/test_ffi.js +0 -157
  64. package/test/test_ffi.ts +0 -170
  65. package/test/test_ffi_abi.js +0 -290
  66. package/test/test_ffi_abi.ts +0 -274
  67. package/test/test_ffi_array.js +0 -116
  68. package/test/test_ffi_array.ts +0 -141
  69. package/test/test_ffi_bind.js +0 -656
  70. package/test/test_ffi_bind.ts +0 -670
  71. package/test/test_ffi_struct.js +0 -779
  72. package/test/test_ffi_struct.ts +0 -828
  73. package/test/test_ffi_struct_layout.js +0 -495
  74. package/test/test_ffi_struct_layout.ts +0 -543
  75. package/test/test_ffi_user32.js +0 -103
  76. package/test/test_ffi_user32.ts +0 -113
  77. package/test/test_ffi_windows.js +0 -172
  78. package/test/test_ffi_windows.ts +0 -187
  79. package/test/test_files.js +0 -102
  80. package/test/test_files.ts +0 -121
  81. package/test/test_frame_encoding.js +0 -128
  82. package/test/test_frame_encoding.ts +0 -132
  83. package/test/test_gdi_draw.js +0 -681
  84. package/test/test_gdi_draw.ts +0 -725
  85. package/test/test_helper.js +0 -91
  86. package/test/test_helper.ts +0 -88
  87. package/test/test_http_import.js +0 -96
  88. package/test/test_http_import.ts +0 -93
  89. package/test/test_http_server.js +0 -214
  90. package/test/test_http_server.ts +0 -211
  91. package/test/test_import_dir.js +0 -4
  92. package/test/test_import_dir.ts +0 -5
  93. package/test/test_ipv6.js +0 -134
  94. package/test/test_ipv6.ts +0 -130
  95. package/test/test_jsx.js +0 -1314
  96. package/test/test_meta_url.js +0 -3
  97. package/test/test_meta_url.ts +0 -4
  98. package/test/test_mupdf_render.js +0 -51
  99. package/test/test_mupdf_render.ts +0 -55
  100. package/test/test_mupdf_twice.js +0 -62
  101. package/test/test_mupdf_twice.ts +0 -65
  102. package/test/test_mupdf_wasm.js +0 -39
  103. package/test/test_mupdf_wasm.ts +0 -32
  104. package/test/test_net_event.js +0 -57
  105. package/test/test_net_event.ts +0 -56
  106. package/test/test_net_fetch.js +0 -384
  107. package/test/test_net_fetch.ts +0 -373
  108. package/test/test_net_websocket.js +0 -180
  109. package/test/test_net_websocket.ts +0 -164
  110. package/test/test_polyfill.js +0 -144
  111. package/test/test_polyfill.ts +0 -159
  112. package/test/test_printer.js +0 -137
  113. package/test/test_printer.ts +0 -148
  114. package/test/test_proc.js +0 -141
  115. package/test/test_proc.ts +0 -163
  116. package/test/test_react_complex.js +0 -18678
  117. package/test/test_react_counter.js +0 -18555
  118. package/test/test_react_flex.js +0 -18871
  119. package/test/test_react_hidden.js +0 -18560
  120. package/test/test_react_listview_link.js +0 -18590
  121. package/test/test_react_notify.js +0 -18797
  122. package/test/test_react_render.js +0 -18550
  123. package/test/test_registry.js +0 -74
  124. package/test/test_registry.ts +0 -95
  125. package/test/test_sysinfo.js +0 -122
  126. package/test/test_sysinfo.ts +0 -141
  127. package/test/test_url.js +0 -173
  128. package/test/test_url.ts +0 -183
  129. package/test/test_wasm_basic.js +0 -85
  130. package/test/test_wasm_basic.ts +0 -73
  131. package/test/test_wasm_import_global.js +0 -41
  132. package/test/test_wasm_import_global.ts +0 -45
  133. package/test/test_wasm_sjlj.js +0 -145
  134. package/test/test_wasm_sjlj.ts +0 -125
  135. package/test/test_wasm_types.js +0 -97
  136. package/test/test_wasm_types.ts +0 -124
  137. package/test/test_wolfssl_read.js +0 -203
  138. package/test/test_wolfssl_read.ts +0 -184
  139. package/test/test_worker.js +0 -21
  140. package/test/test_worker.ts +0 -24
  141. package/test/test_worker_concurrent.js +0 -45
  142. package/test/test_worker_concurrent.ts +0 -56
  143. package/test/test_worker_data_url.js +0 -46
  144. package/test/test_worker_data_url.ts +0 -51
  145. package/test/test_worker_fetch.js +0 -26
  146. package/test/test_worker_fetch.ts +0 -27
  147. package/test/test_worker_net.js +0 -69
  148. package/test/test_worker_net.ts +0 -66
  149. package/test/test_worker_wasm_concurrent.js +0 -44
  150. package/test/test_worker_wasm_concurrent.ts +0 -45
  151. package/test/types.wasm +0 -0
  152. package/test/worker_fetch.js +0 -13
  153. package/test/worker_fetch.ts +0 -13
  154. package/test/worker_helper.js +0 -1
  155. package/test/worker_helper.ts +0 -1
  156. package/test/worker_http.js +0 -18
  157. package/test/worker_http.ts +0 -20
  158. package/test/worker_import_lib.js +0 -12
  159. package/test/worker_import_lib.ts +0 -13
  160. package/test/worker_module.js +0 -16
  161. package/test/worker_module.ts +0 -17
  162. package/test/worker_wasm_concurrent.js +0 -22
  163. package/test/worker_wasm_concurrent.ts +0 -22
@@ -1,121 +0,0 @@
1
- import { WCHAR } from '../lib/ffi/bind.js'
2
- import { NULL, PtrArrayBuffer } from '../lib/ffi/ctype.js'
3
- import {
4
- CloseHandle, CopyFile, CreateDirectory, CreateFile, DeleteFile,
5
- FindClose, FindFirstFile, FindNextFile, GetFileAttributes, GetFileSize,
6
- GetTempPath, MoveFileEx, ReadFile, RemoveDirectory, SetFilePointer, WriteFile,
7
- } from '../lib/windows/kernel32.js'
8
- import { WIN32_FIND_DATAW } from '../lib/windows/structs.js'
9
- import { Tester } from './test_helper.js'
10
- import { FileCreation, FileSeekFrom } from '../constants'
11
-
12
- const GENERIC_READ = 0x80000000
13
- const GENERIC_WRITE = 0x40000000
14
- const FILE_ATTRIBUTE_DIRECTORY = 0x10
15
- const INVALID32 = 0xffffffff
16
-
17
- // ASCII payload ↔ UTF-16LE 缓冲互转(REG_SZ 同型,测试内联)
18
- function toWide(s: string): PtrArrayBuffer<string> {
19
- const p = new PtrArrayBuffer(s.length * 2)
20
- const dv = new DataView(p)
21
- for (let i = 0; i < s.length; i++) dv.setUint16(i * 2, s.charCodeAt(i), true)
22
- return p
23
- }
24
- function fromWide(p: PtrArrayBuffer<string>, chars: number): string {
25
- const dv = new DataView(p)
26
- let out = ''
27
- for (let i = 0; i < chars; i++) out += String.fromCharCode(dv.getUint16(i * 2, true))
28
- return out
29
- }
30
-
31
- export const suite = {
32
- name: 'files',
33
- run: (t: Tester) => {
34
- t.section('GetTempPath + CreateDirectory')
35
- const tmpW = WCHAR.alloc(260)
36
- const tmpLen = GetTempPath(260, tmpW)
37
- t.checkTrue(`temp path non-empty (${tmpLen})`, tmpLen > 0)
38
- const dir = `${WCHAR.decode(tmpW)}QuickWinTest` // GetTempPath 尾带反斜杠
39
- // 目录可能残留自上次中断的 run:已存在(且是目录)则静默复用
40
- if (CreateDirectory(dir, NULL) === 0 &&
41
- (GetFileAttributes(dir) & FILE_ATTRIBUTE_DIRECTORY) === 0) {
42
- t.checkTrue('CreateDirectory', false)
43
- return
44
- }
45
- const pathA = `${dir}\\a.txt`
46
- const pathB = `${dir}\\b.txt`
47
- const pathC = `${dir}\\c.txt`
48
- const pathCn = `${dir}\\中文文件.txt`
49
-
50
- t.section('CreateFile + WriteFile: write payload')
51
- const hW = CreateFile(pathA, GENERIC_WRITE, 0, NULL,
52
- FileCreation.CREATE_ALWAYS, 0x80 /* FILE_ATTRIBUTE_NORMAL */, NULL)
53
- t.checkTrue(`write handle valid (${hW})`, hW !== -1) // 失败 = INVALID_HANDLE_VALUE(-1)
54
- const payload = 'hello files'
55
- const wData = toWide(payload)
56
- const pWr = new PtrArrayBuffer(4)
57
- t.checkTrue('WriteFile ok', WriteFile(hW, wData, payload.length * 2, pWr, NULL) !== 0)
58
- t.check('bytes written', payload.length * 2, new DataView(pWr).getUint32(0, true))
59
- t.checkTrue('CloseHandle (writer)', CloseHandle(hW) !== 0)
60
-
61
- t.section('CreateFile(READ) + GetFileSize + SetFilePointer + ReadFile')
62
- const hR = CreateFile(pathA, GENERIC_READ, 0, NULL,
63
- FileCreation.OPEN_EXISTING, 0x80, NULL)
64
- t.checkTrue(`read handle valid (${hR})`, hR !== -1)
65
- t.check('GetFileSize', payload.length * 2, GetFileSize(hR, NULL))
66
- t.check('SetFilePointer BEGIN → 0', 0, SetFilePointer(hR, 0, NULL, FileSeekFrom.BEGIN))
67
- const rData = new PtrArrayBuffer(payload.length * 2)
68
- const pRd = new PtrArrayBuffer(4)
69
- t.checkTrue('ReadFile ok', ReadFile(hR, rData, payload.length * 2, pRd, NULL) !== 0)
70
- t.check('read roundtrip', payload, fromWide(rData, payload.length))
71
- // seek 到 END-4 验证负偏移 + 读尾 4 字节
72
- t.check('SetFilePointer END-4', payload.length * 2 - 4,
73
- SetFilePointer(hR, -4, NULL, FileSeekFrom.END))
74
- const rTail = new PtrArrayBuffer(8)
75
- ReadFile(hR, rTail, 4, pRd, NULL)
76
- t.check('seeked tail', payload.slice(-2), fromWide(rTail, 2))
77
- CloseHandle(hR)
78
-
79
- t.section('CopyFile + MoveFileEx + GetFileAttributes')
80
- const hB = CreateFile(pathB, GENERIC_WRITE, 0, NULL,
81
- FileCreation.CREATE_ALWAYS, 0x80, NULL)
82
- const bData = toWide('bb')
83
- WriteFile(hB, bData, 4, pWr, NULL)
84
- CloseHandle(hB)
85
- t.checkTrue('CopyFile ok', CopyFile(pathB, pathC, 0) !== 0)
86
- const hC = CreateFile(pathC, GENERIC_READ, 0, NULL,
87
- FileCreation.OPEN_EXISTING, 0x80, NULL)
88
- t.check('copied size', 4, GetFileSize(hC, NULL))
89
- t.checkTrue('CloseHandle (copy reader)', CloseHandle(hC) !== 0)
90
- t.checkTrue('MoveFileEx replace ok',
91
- MoveFileEx(pathB, pathC, 0x1 /* MOVEFILE_REPLACE_EXISTING */) !== 0)
92
- t.check('moved: source gone', INVALID32, GetFileAttributes(pathB))
93
- t.checkTrue('dest is file (not dir)',
94
- (GetFileAttributes(pathC) & FILE_ATTRIBUTE_DIRECTORY) === 0)
95
-
96
- t.section('FindFirstFile/FindNextFile: enumerate *.txt incl. CJK name')
97
- const hCn = CreateFile(pathCn, GENERIC_WRITE, 0, NULL,
98
- FileCreation.CREATE_ALWAYS, 0x80, NULL)
99
- CloseHandle(hCn) // 0 字节中文名文件
100
- const fd = WIN32_FIND_DATAW.alloc()
101
- const hFind = FindFirstFile(`${dir}\\a.txt`, fd.ptr)
102
- t.checkTrue(`FindFirstFile ok (${hFind})`, hFind !== -1)
103
- t.check('found name', 'a.txt', WIN32_FIND_DATAW.decode(fd).cFileName)
104
- t.checkTrue('FindNextFile exhausted = 0', FindNextFile(hFind, fd.ptr) === 0)
105
- t.checkTrue('FindClose', FindClose(hFind) !== 0)
106
- let count = 0
107
- const hEnum = FindFirstFile(`${dir}\\*.txt`, fd.ptr)
108
- if (hEnum !== -1) {
109
- count = 1
110
- while (FindNextFile(hEnum, fd.ptr) !== 0) count++
111
- FindClose(hEnum)
112
- }
113
- t.check('enum *.txt count (a/c/CJK)', 3, count)
114
-
115
- t.section('DeleteFile + RemoveDirectory: cleanup')
116
- t.checkTrue('DeleteFile ×3', DeleteFile(pathA) !== 0 && DeleteFile(pathC) !== 0
117
- && DeleteFile(pathCn) !== 0)
118
- t.checkTrue('RemoveDirectory', RemoveDirectory(dir) !== 0)
119
- t.check('dir gone', INVALID32, GetFileAttributes(dir))
120
- },
121
- }
@@ -1,128 +0,0 @@
1
- import * as std from 'std';
2
- export const suite = {
3
- name: 'wasm-frame-encoding',
4
- run: (t) => {
5
- function createFrameHeader(payloadLen) {
6
- let headerSize = payloadLen < 126 ? 6 : (payloadLen < 65536 ? 8 : 14);
7
- let buf = new ArrayBuffer(headerSize);
8
- let view = new Uint8Array(buf);
9
- let off = 0;
10
- view[off++] = 0x81;
11
- if (payloadLen < 126) {
12
- view[off++] = 0x80 | payloadLen;
13
- }
14
- else if (payloadLen < 65536) {
15
- view[off++] = 0x80 | 126;
16
- view[off++] = (payloadLen >> 8) & 0xFF;
17
- view[off++] = payloadLen & 0xFF;
18
- }
19
- else {
20
- view[off++] = 0x80 | 127;
21
- const len = payloadLen;
22
- const hi = Math.floor(len / 0x100000000) >>> 0;
23
- const lo = len >>> 0;
24
- view[off++] = (hi >> 24) & 0xFF;
25
- view[off++] = (hi >> 16) & 0xFF;
26
- view[off++] = (hi >> 8) & 0xFF;
27
- view[off++] = hi & 0xFF;
28
- view[off++] = (lo >> 24) & 0xFF;
29
- view[off++] = (lo >> 16) & 0xFF;
30
- view[off++] = (lo >> 8) & 0xFF;
31
- view[off++] = lo & 0xFF;
32
- }
33
- return view;
34
- }
35
- function tryParseFrameLen(data) {
36
- if (data.length < 2)
37
- return null;
38
- const b1 = data[1];
39
- let payloadLen = b1 & 0x7F;
40
- let offset = 2;
41
- if (payloadLen === 126) {
42
- if (data.length < 4)
43
- return null;
44
- payloadLen = (data[2] << 8) | data[3];
45
- }
46
- else if (payloadLen === 127) {
47
- if (data.length < 10)
48
- return null;
49
- let hi = 0, lo = 0;
50
- for (let i = 0; i < 4; i++)
51
- hi = (hi * 256 + data[offset + i]) >>> 0;
52
- for (let i = 4; i < 8; i++)
53
- lo = (lo * 256 + data[offset + i]) >>> 0;
54
- payloadLen = hi * 0x100000000 + lo;
55
- }
56
- return payloadLen;
57
- }
58
- function assert(name, ok) {
59
- if (ok) {
60
- t.ok++;
61
- std.printf(' PASS: %s\n', name);
62
- }
63
- else {
64
- t.fail++;
65
- std.printf(' FAIL: %s\n', name);
66
- }
67
- }
68
- // small frame (100 bytes)
69
- t.section('inline length (<126)');
70
- let h = createFrameHeader(100);
71
- assert('length=100', h[1] === (0x80 | 100));
72
- assert('parse 100', tryParseFrameLen(h) === 100);
73
- // 1 (edge case)
74
- h = createFrameHeader(1);
75
- assert('length=1', h[1] === (0x80 | 1));
76
- assert('parse 1', tryParseFrameLen(h) === 1);
77
- // 125 (max inline)
78
- h = createFrameHeader(125);
79
- assert('length=125', h[1] === (0x80 | 125));
80
- assert('parse 125', tryParseFrameLen(h) === 125);
81
- // 126 (enters 16-bit extended)
82
- t.section('16-bit extended length (126–65535)');
83
- h = createFrameHeader(126);
84
- assert('126 marker', h[1] === (0x80 | 126));
85
- assert('126 value', h[2] === 0 && h[3] === 126);
86
- assert('parse 126', tryParseFrameLen(h) === 126);
87
- // 65535 (max 16-bit)
88
- h = createFrameHeader(65535);
89
- assert('65535 marker', h[1] === (0x80 | 126));
90
- assert('65535 hi byte', h[2] === 0xFF);
91
- assert('65535 lo byte', h[3] === 0xFF);
92
- assert('parse 65535', tryParseFrameLen(h) === 65535);
93
- // 65536 (enters 64-bit extended)
94
- t.section('64-bit extended length (>=65536)');
95
- h = createFrameHeader(65536);
96
- assert('65536 marker', h[1] === (0x80 | 127));
97
- assert('parse 65536', tryParseFrameLen(h) === 65536);
98
- // 66000
99
- h = createFrameHeader(66000);
100
- assert('66000 marker', h[1] === (0x80 | 127));
101
- assert('parse 66000', tryParseFrameLen(h) === 66000);
102
- // 70000 — verify exact bytes
103
- h = createFrameHeader(70000);
104
- assert('70000 marker', h[1] === (0x80 | 127));
105
- // 70000 = 0x11170, big-endian 8 bytes: 00 00 00 00 00 01 11 70
106
- assert('70000 bytes big-endian', h[2] === 0x00 && h[3] === 0x00 && h[4] === 0x00 && h[5] === 0x00 &&
107
- h[6] === 0x00 && h[7] === 0x01 && h[8] === 0x11 && h[9] === 0x70);
108
- assert('parse 70000', tryParseFrameLen(h) === 70000);
109
- // Large value near 2^32 boundary
110
- t.section('large values');
111
- h = createFrameHeader(0xABCD1234);
112
- assert('0xABCD1234 marker', h[1] === (0x80 | 127));
113
- assert('parse 0xABCD1234', tryParseFrameLen(h) === 0xABCD1234);
114
- assert('MSB non-zero', h[2] === 0x00 && h[3] === 0x00 && h[4] === 0x00 && h[5] === 0x00 &&
115
- h[6] === 0xAB && h[7] === 0xCD && h[8] === 0x12 && h[9] === 0x34);
116
- // 0x100000001 (just above 2^32)
117
- h = createFrameHeader(0x100000001);
118
- assert('2^32+1 parse', tryParseFrameLen(h) === 0x100000001);
119
- assert('2^32+1 bytes', h[2] === 0x00 && h[3] === 0x00 && h[4] === 0x00 && h[5] === 0x01 &&
120
- h[6] === 0x00 && h[7] === 0x00 && h[8] === 0x00 && h[9] === 0x01);
121
- // Full 8-byte roundtrip: 0x0123456789ABCDEF
122
- // This exceeds Number's safe integer range (2^53) slightly,
123
- // but our test value 0x0123456789ABCDEF = 81985529216486895 < 2^53 ✓
124
- const bigVal = 0x0123456789ABCDEF;
125
- h = createFrameHeader(bigVal);
126
- assert('big val parse', tryParseFrameLen(h) === bigVal);
127
- }
128
- };
@@ -1,132 +0,0 @@
1
- import * as std from 'std'
2
- import { Tester } from './test_helper.js'
3
-
4
- export const suite = {
5
- name: 'wasm-frame-encoding',
6
- run: (t: Tester) => {
7
- function createFrameHeader(payloadLen: number): Uint8Array {
8
- let headerSize = payloadLen < 126 ? 6 : (payloadLen < 65536 ? 8 : 14)
9
- let buf = new ArrayBuffer(headerSize)
10
- let view = new Uint8Array(buf)
11
- let off = 0
12
- view[off++] = 0x81
13
- if (payloadLen < 126) {
14
- view[off++] = 0x80 | payloadLen
15
- } else if (payloadLen < 65536) {
16
- view[off++] = 0x80 | 126
17
- view[off++] = (payloadLen >> 8) & 0xFF
18
- view[off++] = payloadLen & 0xFF
19
- } else {
20
- view[off++] = 0x80 | 127
21
- const len = payloadLen
22
- const hi = Math.floor(len / 0x100000000) >>> 0
23
- const lo = len >>> 0
24
- view[off++] = (hi >> 24) & 0xFF
25
- view[off++] = (hi >> 16) & 0xFF
26
- view[off++] = (hi >> 8) & 0xFF
27
- view[off++] = hi & 0xFF
28
- view[off++] = (lo >> 24) & 0xFF
29
- view[off++] = (lo >> 16) & 0xFF
30
- view[off++] = (lo >> 8) & 0xFF
31
- view[off++] = lo & 0xFF
32
- }
33
- return view
34
- }
35
-
36
- function tryParseFrameLen(data: Uint8Array): number | null {
37
- if (data.length < 2) return null
38
- const b1 = data[1]!
39
- let payloadLen = b1 & 0x7F
40
- let offset = 2
41
- if (payloadLen === 126) {
42
- if (data.length < 4) return null
43
- payloadLen = (data[2]! << 8) | data[3]!
44
- } else if (payloadLen === 127) {
45
- if (data.length < 10) return null
46
- let hi = 0, lo = 0
47
- for (let i = 0; i < 4; i++) hi = (hi * 256 + data[offset + i]!) >>> 0
48
- for (let i = 4; i < 8; i++) lo = (lo * 256 + data[offset + i]!) >>> 0
49
- payloadLen = hi * 0x100000000 + lo
50
- }
51
- return payloadLen
52
- }
53
-
54
- function assert(name: string, ok: boolean): void {
55
- if (ok) { t.ok++; std.printf(' PASS: %s\n', name) }
56
- else { t.fail++; std.printf(' FAIL: %s\n', name) }
57
- }
58
-
59
- // small frame (100 bytes)
60
- t.section('inline length (<126)')
61
- let h = createFrameHeader(100)
62
- assert('length=100', h[1] === (0x80 | 100))
63
- assert('parse 100', tryParseFrameLen(h) === 100)
64
-
65
- // 1 (edge case)
66
- h = createFrameHeader(1)
67
- assert('length=1', h[1] === (0x80 | 1))
68
- assert('parse 1', tryParseFrameLen(h) === 1)
69
-
70
- // 125 (max inline)
71
- h = createFrameHeader(125)
72
- assert('length=125', h[1] === (0x80 | 125))
73
- assert('parse 125', tryParseFrameLen(h) === 125)
74
-
75
- // 126 (enters 16-bit extended)
76
- t.section('16-bit extended length (126–65535)')
77
- h = createFrameHeader(126)
78
- assert('126 marker', h[1] === (0x80 | 126))
79
- assert('126 value', h[2] === 0 && h[3] === 126)
80
- assert('parse 126', tryParseFrameLen(h) === 126)
81
-
82
- // 65535 (max 16-bit)
83
- h = createFrameHeader(65535)
84
- assert('65535 marker', h[1] === (0x80 | 126))
85
- assert('65535 hi byte', h[2] === 0xFF)
86
- assert('65535 lo byte', h[3] === 0xFF)
87
- assert('parse 65535', tryParseFrameLen(h) === 65535)
88
-
89
- // 65536 (enters 64-bit extended)
90
- t.section('64-bit extended length (>=65536)')
91
- h = createFrameHeader(65536)
92
- assert('65536 marker', h[1] === (0x80 | 127))
93
- assert('parse 65536', tryParseFrameLen(h) === 65536)
94
-
95
- // 66000
96
- h = createFrameHeader(66000)
97
- assert('66000 marker', h[1] === (0x80 | 127))
98
- assert('parse 66000', tryParseFrameLen(h) === 66000)
99
-
100
- // 70000 — verify exact bytes
101
- h = createFrameHeader(70000)
102
- assert('70000 marker', h[1] === (0x80 | 127))
103
- // 70000 = 0x11170, big-endian 8 bytes: 00 00 00 00 00 01 11 70
104
- assert('70000 bytes big-endian',
105
- h[2] === 0x00 && h[3] === 0x00 && h[4] === 0x00 && h[5] === 0x00 &&
106
- h[6] === 0x00 && h[7] === 0x01 && h[8] === 0x11 && h[9] === 0x70)
107
- assert('parse 70000', tryParseFrameLen(h) === 70000)
108
-
109
- // Large value near 2^32 boundary
110
- t.section('large values')
111
- h = createFrameHeader(0xABCD1234)
112
- assert('0xABCD1234 marker', h[1] === (0x80 | 127))
113
- assert('parse 0xABCD1234', tryParseFrameLen(h) === 0xABCD1234)
114
- assert('MSB non-zero',
115
- h[2] === 0x00 && h[3] === 0x00 && h[4] === 0x00 && h[5] === 0x00 &&
116
- h[6] === 0xAB && h[7] === 0xCD && h[8] === 0x12 && h[9] === 0x34)
117
-
118
- // 0x100000001 (just above 2^32)
119
- h = createFrameHeader(0x100000001)
120
- assert('2^32+1 parse', tryParseFrameLen(h) === 0x100000001)
121
- assert('2^32+1 bytes',
122
- h[2] === 0x00 && h[3] === 0x00 && h[4] === 0x00 && h[5] === 0x01 &&
123
- h[6] === 0x00 && h[7] === 0x00 && h[8] === 0x00 && h[9] === 0x01)
124
-
125
- // Full 8-byte roundtrip: 0x0123456789ABCDEF
126
- // This exceeds Number's safe integer range (2^53) slightly,
127
- // but our test value 0x0123456789ABCDEF = 81985529216486895 < 2^53 ✓
128
- const bigVal = 0x0123456789ABCDEF
129
- h = createFrameHeader(bigVal)
130
- assert('big val parse', tryParseFrameLen(h) === bigVal)
131
- }
132
- }