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.
Files changed (78) hide show
  1. package/README.en.md +204 -204
  2. package/README.md +203 -203
  3. package/examples/PdfCanvas.tsx +83 -83
  4. package/examples/exec_server.ts +35 -35
  5. package/examples/pdf_preview2.ts +375 -375
  6. package/examples/pdf_viewer.tsx +279 -279
  7. package/examples/test_gallery.tsx +285 -285
  8. package/examples/test_react_lazy.tsx +63 -63
  9. package/examples/test_react_listbox.tsx +71 -71
  10. package/examples/test_root_window.tsx +41 -41
  11. package/examples/test_tab.tsx +75 -75
  12. package/examples/tray_demo.tsx +81 -81
  13. package/lib/assert.ts +6 -6
  14. package/lib/cache-utils.ts +40 -40
  15. package/lib/dumpRects.ts +25 -25
  16. package/lib/fetch.ts +502 -502
  17. package/lib/http-common.ts +399 -399
  18. package/lib/http-server.ts +424 -424
  19. package/lib/polyfill.ts +171 -171
  20. package/lib/react-qw/components/index.ts +17 -17
  21. package/lib/react-qw/index.ts +90 -90
  22. package/lib/react-qw/jsx.d.ts +34 -34
  23. package/lib/react-qw/layout.ts +111 -111
  24. package/lib/react-qw/props.ts +36 -36
  25. package/lib/react-qw/reconciler.ts +373 -373
  26. package/lib/stream.ts +21 -21
  27. package/lib/text-codec.ts +171 -171
  28. package/lib/text-measure.ts +54 -54
  29. package/lib/url.ts +201 -201
  30. package/lib/vendor/web-streams/ponyfill.d.mts +829 -829
  31. package/lib/vendor/web-streams/ponyfill.mjs +8 -8
  32. package/lib/websocket.js +8 -0
  33. package/lib/websocket.ts +563 -555
  34. package/package.json +50 -44
  35. package/qwin-nowasm-x86.exe +0 -0
  36. package/qwin-nowasm.exe +0 -0
  37. package/qwin-x86.exe +0 -0
  38. package/qwin.exe +0 -0
  39. package/test/run.ts +96 -96
  40. package/test/test_basic.ts +9 -9
  41. package/test/test_basic_fetch.ts +33 -33
  42. package/test/test_brotli.ts +52 -52
  43. package/test/test_fetch_cache.ts +187 -187
  44. package/test/test_ffi.ts +174 -174
  45. package/test/test_frame_encoding.ts +132 -132
  46. package/test/test_helper.ts +80 -80
  47. package/test/test_http_import.ts +74 -74
  48. package/test/test_http_server.ts +136 -136
  49. package/test/test_import_dir.ts +5 -5
  50. package/test/test_ipv6.ts +129 -129
  51. package/test/test_meta_url.ts +4 -4
  52. package/test/test_mupdf_render.ts +74 -74
  53. package/test/test_mupdf_twice.ts +81 -81
  54. package/test/test_mupdf_wasm.ts +30 -30
  55. package/test/test_net_event.ts +55 -55
  56. package/test/test_net_fetch.ts +238 -238
  57. package/test/test_net_websocket.ts +164 -164
  58. package/test/test_polyfill.ts +159 -159
  59. package/test/test_url.ts +183 -183
  60. package/test/test_wasm_basic.ts +73 -73
  61. package/test/test_wasm_import_global.ts +45 -45
  62. package/test/test_wasm_sjlj.ts +125 -125
  63. package/test/test_wasm_types.ts +124 -124
  64. package/test/test_worker.ts +24 -24
  65. package/test/test_worker_fetch.ts +27 -27
  66. package/test/test_worker_net.ts +54 -54
  67. package/test/test_worker_wasm_concurrent.ts +45 -45
  68. package/test/worker_fetch.ts +13 -13
  69. package/test/worker_helper.ts +1 -1
  70. package/test/worker_http.ts +20 -20
  71. package/test/worker_import_lib.ts +13 -13
  72. package/test/worker_module.ts +17 -17
  73. package/test/worker_wasm_concurrent.ts +22 -22
  74. package/tsconfig.json +27 -27
  75. package/vendor/mupdf-wasm/mupdf-wasm.d.ts +571 -571
  76. package/vendor/mupdf-wasm/mupdf-wasm.js +2749 -2749
  77. package/vendor/mupdf-wasm/mupdf.d.ts +939 -939
  78. package/vendor/mupdf-wasm/mupdf.js +3317 -3317
package/test/test_url.ts CHANGED
@@ -1,183 +1,183 @@
1
- import { Tester } from './test_helper.js'
2
- import '../lib/url.js'
3
-
4
- export const suite = {
5
- name: 'url',
6
- run: (t: Tester) => {
7
- t.section('http parse')
8
- const u = new URL('http://example.com')
9
- t.check('href', 'http://example.com/', u.href)
10
- t.check('protocol', 'http:', u.protocol)
11
- t.check('hostname', 'example.com', u.hostname)
12
- t.check('port', '', u.port)
13
- t.check('pathname', '/', u.pathname)
14
- t.check('host', 'example.com', u.host)
15
- t.check('origin', 'http://example.com', u.origin)
16
-
17
- t.section('full http')
18
- const u2 = new URL('https://user:pass@host.com:443/path/to?q=1&r=2#frag')
19
- t.check('protocol', 'https:', u2.protocol)
20
- t.check('username', 'user', u2.username)
21
- t.check('password', 'pass', u2.password)
22
- t.check('hostname', 'host.com', u2.hostname)
23
- t.check('port', '443', u2.port)
24
- t.check('pathname', '/path/to', u2.pathname)
25
- t.check('search', '?q=1&r=2', u2.search)
26
- t.check('hash', '#frag', u2.hash)
27
- t.check('host', 'host.com:443', u2.host)
28
-
29
- t.section('query string params')
30
- t.check('get q', '1', u2.searchParams.get('q'))
31
- t.check('get r', '2', u2.searchParams.get('r'))
32
- t.check('has q', true, u2.searchParams.has('q'))
33
- t.check('has x', false, u2.searchParams.has('x'))
34
-
35
- t.section('relative resolution')
36
- const b = new URL('./add.wasm', 'http://example.com/base/')
37
- t.check('relative path', 'http://example.com/base/add.wasm', b.href)
38
- const b2 = new URL('../other', 'http://example.com/base/')
39
- t.check('up one dir', 'http://example.com/other', b2.href)
40
- const b3 = new URL('/abs', 'http://example.com/base/')
41
- t.check('absolute path', 'http://example.com/abs', b3.href)
42
- const b4 = new URL('//other.com:8080/path', 'http://example.com/base/')
43
- t.check('protocol-relative', 'http://other.com:8080/path', b4.href)
44
-
45
- t.section('file URL')
46
- const f = new URL('file:///C:/Users/test/file.js')
47
- t.check('protocol', 'file:', f.protocol)
48
- t.check('hostname', '', f.hostname)
49
- t.check('pathname', '/C:/Users/test/file.js', f.pathname)
50
-
51
- t.section('file relative resolution')
52
- const f2 = new URL('./add.wasm', 'file:///C:/Users/test/helper.js')
53
- t.check('file relative', 'file:///C:/Users/test/add.wasm', f2.href)
54
- const f3 = new URL('../other.wasm', 'file:///C:/Users/test/sub/helper.js')
55
- t.check('file up dir', 'file:///C:/Users/test/other.wasm', f3.href)
56
-
57
- t.section('URLSearchParams')
58
- const p = new URLSearchParams('a=1&b=2&a=3')
59
- t.check('get a', '1', p.get('a'))
60
- t.check('getAll a', 2, p.getAll('a').length)
61
- t.check('get b', '2', p.get('b'))
62
- t.check('has c', false, p.has('c'))
63
- t.check('size', 3, p.size)
64
-
65
- t.section('URLSearchParams set/append/delete')
66
- const p2 = new URLSearchParams()
67
- p2.append('key', 'val1')
68
- p2.append('key', 'val2')
69
- t.check('append 2', 2, p2.getAll('key').length)
70
- p2.set('key', 'new')
71
- t.check('set replaces', 1, p2.getAll('key').length)
72
- t.check('set value', 'new', p2.get('key'))
73
- p2.append('x', 'y')
74
- p2.delete('x')
75
- t.check('delete', false, p2.has('x'))
76
-
77
- t.section('URLSearchParams toString')
78
- const p3 = new URLSearchParams('q=hello&r=world')
79
- t.check('toString', 'q=hello&r=world', p3.toString())
80
-
81
- t.section('URLSearchParams iterator')
82
- const p4 = new URLSearchParams('a=1&b=2')
83
- const keys: string[] = []
84
- for (const k of p4.keys()) keys.push(k)
85
- t.check('keys', 'a,b', keys.join(','))
86
-
87
- t.section('URL toJSON')
88
- const j = new URL('http://example.com/path')
89
- t.check('toJSON', 'http://example.com/path', j.toJSON())
90
-
91
- t.section('URL toString')
92
- t.check('toString', 'http://example.com/path', j.toString())
93
-
94
- t.section('IPv6')
95
- const v6 = new URL('http://[::1]:8080/path')
96
- t.check('hostname', '::1', v6.hostname)
97
- t.check('port', '8080', v6.port)
98
- t.check('host', '[::1]:8080', v6.host)
99
- t.check('pathname', '/path', v6.pathname)
100
- const v6b = new URL('http://[2001:db8::1]/')
101
- t.check('IPv6 no port', '2001:db8::1', v6b.hostname)
102
- t.check('IPv6 host', '[2001:db8::1]', v6b.host)
103
- const v6c = new URL('http://[::1]:8080')
104
- t.check('IPv6 origin', 'http://[::1]:8080', v6c.origin)
105
-
106
- t.section('ws/wss')
107
- const ws = new URL('ws://example.com/socket')
108
- t.check('ws protocol', 'ws:', ws.protocol)
109
- t.check('ws hostname', 'example.com', ws.hostname)
110
- t.check('ws pathname', '/socket', ws.pathname)
111
- const wss = new URL('wss://secure.com:9090/chat')
112
- t.check('wss port', '9090', wss.port)
113
-
114
- t.section('relative fragment/query')
115
- const rf = new URL('#top', 'http://example.com/path')
116
- t.check('fragment-only', 'http://example.com/path#top', rf.href)
117
- const rq = new URL('?q=1', 'http://example.com/path')
118
- t.check('query-only', 'http://example.com/path?q=1', rq.href)
119
- const rqf = new URL('?a=1#hash', 'http://example.com/path')
120
- t.check('query+frag', 'http://example.com/path?a=1#hash', rqf.href)
121
-
122
- t.section('path normalization')
123
- const np1 = new URL('a/../../other', 'http://example.com/base/')
124
- t.check('multi up', 'http://example.com/other', np1.href)
125
- const np2 = new URL('/../other', 'http://example.com/base/')
126
- t.check('root up', 'http://example.com/other', np2.href)
127
- const np3 = new URL('.', 'http://example.com/base/')
128
- t.check('dot only', 'http://example.com/base', np3.href)
129
- const np4 = new URL('', 'http://example.com/base/')
130
- t.check('empty relative', 'http://example.com/base/', np4.href)
131
-
132
- t.section('IP address')
133
- const ip = new URL('http://127.0.0.1:8080/path')
134
- t.check('ip hostname', '127.0.0.1', ip.hostname)
135
- t.check('ip port', '8080', ip.port)
136
-
137
- t.section('URLSearchParams values/entries/forEach')
138
- const pv = new URLSearchParams('a=1&b=2')
139
- const vals: string[] = []
140
- for (const v of pv.values()) vals.push(v)
141
- t.check('values', '1,2', vals.join(','))
142
- const entries: string[] = []
143
- for (const [k, v] of pv.entries()) entries.push(k + '=' + v)
144
- t.check('entries', 'a=1,b=2', entries.join(','))
145
- let forEachStr = ''
146
- pv.forEach((v, k) => { forEachStr += k + '=' + v + '|' })
147
- t.check('forEach', 'a=1|b=2|', forEachStr)
148
- const ps = new URLSearchParams('b=2&a=1&c=3')
149
- ps.sort()
150
- t.check('sort', 'a=1&b=2&c=3', ps.toString())
151
-
152
- t.section('URLSearchParams edge cases')
153
- const pe1 = new URLSearchParams('a=1&b')
154
- t.check('empty value', '', pe1.get('b'))
155
- const pe2 = new URLSearchParams('?a=1&b=2')
156
- t.check('leading ?', '1', pe2.get('a'))
157
- const pe3 = new URLSearchParams([['x', '10'], ['y', '20']] as any)
158
- t.check('array init', '10', pe3.get('x'))
159
- t.check('array init 2', '20', pe3.get('y'))
160
- t.check('array size', 2, pe3.size)
161
-
162
- t.section('encoded chars')
163
- const enc = new URL('http://example.com/hello%20world')
164
- t.check('encoded pathname', '/hello%20world', enc.pathname)
165
- const encq = new URL('http://example.com/path?q=a+b&r=%25')
166
- t.check('encoded query +→space', 'a b', encq.searchParams.get('q'))
167
- t.check('encoded query %25', '%', encq.searchParams.get('r'))
168
-
169
- t.section('null/undefined base')
170
- let threw = false
171
- try { new URL('/path', null as any) } catch { threw = true }
172
- t.check('null base throws', true, threw)
173
- threw = false
174
- try { new URL('relative') } catch { threw = true }
175
- t.check('no base throws', true, threw)
176
-
177
- t.section('data URL')
178
- const d = new URL('data:text/plain,hello')
179
- t.check('data protocol', 'data:', d.protocol)
180
- t.check('data hostname', '', d.hostname)
181
- t.check('data pathname', 'text/plain,hello', d.pathname)
182
- }
183
- }
1
+ import { Tester } from './test_helper.js'
2
+ import '../lib/url.js'
3
+
4
+ export const suite = {
5
+ name: 'url',
6
+ run: (t: Tester) => {
7
+ t.section('http parse')
8
+ const u = new URL('http://example.com')
9
+ t.check('href', 'http://example.com/', u.href)
10
+ t.check('protocol', 'http:', u.protocol)
11
+ t.check('hostname', 'example.com', u.hostname)
12
+ t.check('port', '', u.port)
13
+ t.check('pathname', '/', u.pathname)
14
+ t.check('host', 'example.com', u.host)
15
+ t.check('origin', 'http://example.com', u.origin)
16
+
17
+ t.section('full http')
18
+ const u2 = new URL('https://user:pass@host.com:443/path/to?q=1&r=2#frag')
19
+ t.check('protocol', 'https:', u2.protocol)
20
+ t.check('username', 'user', u2.username)
21
+ t.check('password', 'pass', u2.password)
22
+ t.check('hostname', 'host.com', u2.hostname)
23
+ t.check('port', '443', u2.port)
24
+ t.check('pathname', '/path/to', u2.pathname)
25
+ t.check('search', '?q=1&r=2', u2.search)
26
+ t.check('hash', '#frag', u2.hash)
27
+ t.check('host', 'host.com:443', u2.host)
28
+
29
+ t.section('query string params')
30
+ t.check('get q', '1', u2.searchParams.get('q'))
31
+ t.check('get r', '2', u2.searchParams.get('r'))
32
+ t.check('has q', true, u2.searchParams.has('q'))
33
+ t.check('has x', false, u2.searchParams.has('x'))
34
+
35
+ t.section('relative resolution')
36
+ const b = new URL('./add.wasm', 'http://example.com/base/')
37
+ t.check('relative path', 'http://example.com/base/add.wasm', b.href)
38
+ const b2 = new URL('../other', 'http://example.com/base/')
39
+ t.check('up one dir', 'http://example.com/other', b2.href)
40
+ const b3 = new URL('/abs', 'http://example.com/base/')
41
+ t.check('absolute path', 'http://example.com/abs', b3.href)
42
+ const b4 = new URL('//other.com:8080/path', 'http://example.com/base/')
43
+ t.check('protocol-relative', 'http://other.com:8080/path', b4.href)
44
+
45
+ t.section('file URL')
46
+ const f = new URL('file:///C:/Users/test/file.js')
47
+ t.check('protocol', 'file:', f.protocol)
48
+ t.check('hostname', '', f.hostname)
49
+ t.check('pathname', '/C:/Users/test/file.js', f.pathname)
50
+
51
+ t.section('file relative resolution')
52
+ const f2 = new URL('./add.wasm', 'file:///C:/Users/test/helper.js')
53
+ t.check('file relative', 'file:///C:/Users/test/add.wasm', f2.href)
54
+ const f3 = new URL('../other.wasm', 'file:///C:/Users/test/sub/helper.js')
55
+ t.check('file up dir', 'file:///C:/Users/test/other.wasm', f3.href)
56
+
57
+ t.section('URLSearchParams')
58
+ const p = new URLSearchParams('a=1&b=2&a=3')
59
+ t.check('get a', '1', p.get('a'))
60
+ t.check('getAll a', 2, p.getAll('a').length)
61
+ t.check('get b', '2', p.get('b'))
62
+ t.check('has c', false, p.has('c'))
63
+ t.check('size', 3, p.size)
64
+
65
+ t.section('URLSearchParams set/append/delete')
66
+ const p2 = new URLSearchParams()
67
+ p2.append('key', 'val1')
68
+ p2.append('key', 'val2')
69
+ t.check('append 2', 2, p2.getAll('key').length)
70
+ p2.set('key', 'new')
71
+ t.check('set replaces', 1, p2.getAll('key').length)
72
+ t.check('set value', 'new', p2.get('key'))
73
+ p2.append('x', 'y')
74
+ p2.delete('x')
75
+ t.check('delete', false, p2.has('x'))
76
+
77
+ t.section('URLSearchParams toString')
78
+ const p3 = new URLSearchParams('q=hello&r=world')
79
+ t.check('toString', 'q=hello&r=world', p3.toString())
80
+
81
+ t.section('URLSearchParams iterator')
82
+ const p4 = new URLSearchParams('a=1&b=2')
83
+ const keys: string[] = []
84
+ for (const k of p4.keys()) keys.push(k)
85
+ t.check('keys', 'a,b', keys.join(','))
86
+
87
+ t.section('URL toJSON')
88
+ const j = new URL('http://example.com/path')
89
+ t.check('toJSON', 'http://example.com/path', j.toJSON())
90
+
91
+ t.section('URL toString')
92
+ t.check('toString', 'http://example.com/path', j.toString())
93
+
94
+ t.section('IPv6')
95
+ const v6 = new URL('http://[::1]:8080/path')
96
+ t.check('hostname', '::1', v6.hostname)
97
+ t.check('port', '8080', v6.port)
98
+ t.check('host', '[::1]:8080', v6.host)
99
+ t.check('pathname', '/path', v6.pathname)
100
+ const v6b = new URL('http://[2001:db8::1]/')
101
+ t.check('IPv6 no port', '2001:db8::1', v6b.hostname)
102
+ t.check('IPv6 host', '[2001:db8::1]', v6b.host)
103
+ const v6c = new URL('http://[::1]:8080')
104
+ t.check('IPv6 origin', 'http://[::1]:8080', v6c.origin)
105
+
106
+ t.section('ws/wss')
107
+ const ws = new URL('ws://example.com/socket')
108
+ t.check('ws protocol', 'ws:', ws.protocol)
109
+ t.check('ws hostname', 'example.com', ws.hostname)
110
+ t.check('ws pathname', '/socket', ws.pathname)
111
+ const wss = new URL('wss://secure.com:9090/chat')
112
+ t.check('wss port', '9090', wss.port)
113
+
114
+ t.section('relative fragment/query')
115
+ const rf = new URL('#top', 'http://example.com/path')
116
+ t.check('fragment-only', 'http://example.com/path#top', rf.href)
117
+ const rq = new URL('?q=1', 'http://example.com/path')
118
+ t.check('query-only', 'http://example.com/path?q=1', rq.href)
119
+ const rqf = new URL('?a=1#hash', 'http://example.com/path')
120
+ t.check('query+frag', 'http://example.com/path?a=1#hash', rqf.href)
121
+
122
+ t.section('path normalization')
123
+ const np1 = new URL('a/../../other', 'http://example.com/base/')
124
+ t.check('multi up', 'http://example.com/other', np1.href)
125
+ const np2 = new URL('/../other', 'http://example.com/base/')
126
+ t.check('root up', 'http://example.com/other', np2.href)
127
+ const np3 = new URL('.', 'http://example.com/base/')
128
+ t.check('dot only', 'http://example.com/base', np3.href)
129
+ const np4 = new URL('', 'http://example.com/base/')
130
+ t.check('empty relative', 'http://example.com/base/', np4.href)
131
+
132
+ t.section('IP address')
133
+ const ip = new URL('http://127.0.0.1:8080/path')
134
+ t.check('ip hostname', '127.0.0.1', ip.hostname)
135
+ t.check('ip port', '8080', ip.port)
136
+
137
+ t.section('URLSearchParams values/entries/forEach')
138
+ const pv = new URLSearchParams('a=1&b=2')
139
+ const vals: string[] = []
140
+ for (const v of pv.values()) vals.push(v)
141
+ t.check('values', '1,2', vals.join(','))
142
+ const entries: string[] = []
143
+ for (const [k, v] of pv.entries()) entries.push(k + '=' + v)
144
+ t.check('entries', 'a=1,b=2', entries.join(','))
145
+ let forEachStr = ''
146
+ pv.forEach((v, k) => { forEachStr += k + '=' + v + '|' })
147
+ t.check('forEach', 'a=1|b=2|', forEachStr)
148
+ const ps = new URLSearchParams('b=2&a=1&c=3')
149
+ ps.sort()
150
+ t.check('sort', 'a=1&b=2&c=3', ps.toString())
151
+
152
+ t.section('URLSearchParams edge cases')
153
+ const pe1 = new URLSearchParams('a=1&b')
154
+ t.check('empty value', '', pe1.get('b'))
155
+ const pe2 = new URLSearchParams('?a=1&b=2')
156
+ t.check('leading ?', '1', pe2.get('a'))
157
+ const pe3 = new URLSearchParams([['x', '10'], ['y', '20']] as any)
158
+ t.check('array init', '10', pe3.get('x'))
159
+ t.check('array init 2', '20', pe3.get('y'))
160
+ t.check('array size', 2, pe3.size)
161
+
162
+ t.section('encoded chars')
163
+ const enc = new URL('http://example.com/hello%20world')
164
+ t.check('encoded pathname', '/hello%20world', enc.pathname)
165
+ const encq = new URL('http://example.com/path?q=a+b&r=%25')
166
+ t.check('encoded query +→space', 'a b', encq.searchParams.get('q'))
167
+ t.check('encoded query %25', '%', encq.searchParams.get('r'))
168
+
169
+ t.section('null/undefined base')
170
+ let threw = false
171
+ try { new URL('/path', null as any) } catch { threw = true }
172
+ t.check('null base throws', true, threw)
173
+ threw = false
174
+ try { new URL('relative') } catch { threw = true }
175
+ t.check('no base throws', true, threw)
176
+
177
+ t.section('data URL')
178
+ const d = new URL('data:text/plain,hello')
179
+ t.check('data protocol', 'data:', d.protocol)
180
+ t.check('data hostname', '', d.hostname)
181
+ t.check('data pathname', 'text/plain,hello', d.pathname)
182
+ }
183
+ }
@@ -1,73 +1,73 @@
1
- import { Tester, readWasmFile } from './test_helper.js'
2
-
3
- export const suite = {
4
- name: 'wasm-basic',
5
- run: (t: Tester) => {
6
- t.section('validate')
7
- t.check('empty buffer', false, WebAssembly.validate(new Uint8Array([]).buffer))
8
- t.check('invalid bytes', false, WebAssembly.validate(new Uint8Array([1, 2, 3]).buffer))
9
- const wasmBuf = readWasmFile('./add.wasm')
10
- if (!wasmBuf) { t.fail++; return }
11
- t.check('valid add.wasm', true, WebAssembly.validate(wasmBuf))
12
-
13
- t.section('Module')
14
- var mod: WebAssembly.Module | null = null
15
- try {
16
- mod = new WebAssembly.Module(wasmBuf)
17
- t.check('Module constructor', true, mod instanceof WebAssembly.Module)
18
- } catch (e) { t.fail++ }
19
-
20
- t.section('Module.exports')
21
- if (mod) {
22
- try {
23
- const exps = WebAssembly.Module.exports(mod)
24
- t.check('exports count', 1, exps.length)
25
- t.check('export name', 'add', exps[0]!.name)
26
- t.check('export kind', 'function', exps[0]!.kind)
27
- } catch (e) { t.fail++ }
28
- }
29
-
30
- t.section('Instance (add.wasm)')
31
- if (mod) {
32
- try {
33
- const inst = new WebAssembly.Instance<{ add: (a: number, b: number) => number }>(mod)
34
- const iExp = inst.exports
35
- t.check('Instance created', true, inst instanceof WebAssembly.Instance)
36
- t.check('add(1, 2)', 3, iExp.add(1, 2))
37
- t.check('add(10, 20)', 30, iExp.add(10, 20))
38
- t.check('add(-5, 3)', -2, iExp.add(-5, 3))
39
- } catch (e) { t.fail++ }
40
- }
41
-
42
- t.section('complex.wasm')
43
- const complexBuf = readWasmFile('./complex.wasm')
44
- if (complexBuf) {
45
- try {
46
- const cmod = new WebAssembly.Module(complexBuf)
47
- const cinst = new WebAssembly.Instance<{ add: (a: number, b: number) => number; sub: (a: number, b: number) => number; mul: (a: number, b: number) => number; factorial: (n: number) => number }>(cmod)
48
- const cExp = cinst.exports
49
- t.check('add(3, 4)', 7, cExp.add(3, 4))
50
- t.check('sub(10, 3)', 7, cExp.sub(10, 3))
51
- t.check('mul(6, 7)', 42, cExp.mul(6, 7))
52
- t.check('factorial(0)', 1, cExp.factorial(0))
53
- t.check('factorial(5)', 120, cExp.factorial(5))
54
- t.check('factorial(10)', 3628800, cExp.factorial(10))
55
- } catch (e) { t.fail++ }
56
- }
57
-
58
- t.section('import function')
59
- const importFuncBuf = readWasmFile('./import_func.wasm')
60
- if (importFuncBuf) {
61
- try {
62
- const ifmod = new WebAssembly.Module(importFuncBuf)
63
- const ifinst = new WebAssembly.Instance<{ add_via_import: (a: number, b: number) => number }>(ifmod, {
64
- env: { imported_add: (a: number, b: number) => a + b }
65
- })
66
- const ifExp = ifinst.exports
67
- t.check('add_via_import(3, 4)', 7, ifExp.add_via_import(3, 4))
68
- t.check('add_via_import(10, 20)', 30, ifExp.add_via_import(10, 20))
69
- t.check('add_via_import(-5, 3)', -2, ifExp.add_via_import(-5, 3))
70
- } catch (e) { t.fail++ }
71
- }
72
- }
73
- }
1
+ import { Tester, readWasmFile } from './test_helper.js'
2
+
3
+ export const suite = {
4
+ name: 'wasm-basic',
5
+ run: (t: Tester) => {
6
+ t.section('validate')
7
+ t.check('empty buffer', false, WebAssembly.validate(new Uint8Array([]).buffer))
8
+ t.check('invalid bytes', false, WebAssembly.validate(new Uint8Array([1, 2, 3]).buffer))
9
+ const wasmBuf = readWasmFile('./add.wasm')
10
+ if (!wasmBuf) { t.fail++; return }
11
+ t.check('valid add.wasm', true, WebAssembly.validate(wasmBuf))
12
+
13
+ t.section('Module')
14
+ var mod: WebAssembly.Module | null = null
15
+ try {
16
+ mod = new WebAssembly.Module(wasmBuf)
17
+ t.check('Module constructor', true, mod instanceof WebAssembly.Module)
18
+ } catch (e) { t.fail++ }
19
+
20
+ t.section('Module.exports')
21
+ if (mod) {
22
+ try {
23
+ const exps = WebAssembly.Module.exports(mod)
24
+ t.check('exports count', 1, exps.length)
25
+ t.check('export name', 'add', exps[0]!.name)
26
+ t.check('export kind', 'function', exps[0]!.kind)
27
+ } catch (e) { t.fail++ }
28
+ }
29
+
30
+ t.section('Instance (add.wasm)')
31
+ if (mod) {
32
+ try {
33
+ const inst = new WebAssembly.Instance<{ add: (a: number, b: number) => number }>(mod)
34
+ const iExp = inst.exports
35
+ t.check('Instance created', true, inst instanceof WebAssembly.Instance)
36
+ t.check('add(1, 2)', 3, iExp.add(1, 2))
37
+ t.check('add(10, 20)', 30, iExp.add(10, 20))
38
+ t.check('add(-5, 3)', -2, iExp.add(-5, 3))
39
+ } catch (e) { t.fail++ }
40
+ }
41
+
42
+ t.section('complex.wasm')
43
+ const complexBuf = readWasmFile('./complex.wasm')
44
+ if (complexBuf) {
45
+ try {
46
+ const cmod = new WebAssembly.Module(complexBuf)
47
+ const cinst = new WebAssembly.Instance<{ add: (a: number, b: number) => number; sub: (a: number, b: number) => number; mul: (a: number, b: number) => number; factorial: (n: number) => number }>(cmod)
48
+ const cExp = cinst.exports
49
+ t.check('add(3, 4)', 7, cExp.add(3, 4))
50
+ t.check('sub(10, 3)', 7, cExp.sub(10, 3))
51
+ t.check('mul(6, 7)', 42, cExp.mul(6, 7))
52
+ t.check('factorial(0)', 1, cExp.factorial(0))
53
+ t.check('factorial(5)', 120, cExp.factorial(5))
54
+ t.check('factorial(10)', 3628800, cExp.factorial(10))
55
+ } catch (e) { t.fail++ }
56
+ }
57
+
58
+ t.section('import function')
59
+ const importFuncBuf = readWasmFile('./import_func.wasm')
60
+ if (importFuncBuf) {
61
+ try {
62
+ const ifmod = new WebAssembly.Module(importFuncBuf)
63
+ const ifinst = new WebAssembly.Instance<{ add_via_import: (a: number, b: number) => number }>(ifmod, {
64
+ env: { imported_add: (a: number, b: number) => a + b }
65
+ })
66
+ const ifExp = ifinst.exports
67
+ t.check('add_via_import(3, 4)', 7, ifExp.add_via_import(3, 4))
68
+ t.check('add_via_import(10, 20)', 30, ifExp.add_via_import(10, 20))
69
+ t.check('add_via_import(-5, 3)', -2, ifExp.add_via_import(-5, 3))
70
+ } catch (e) { t.fail++ }
71
+ }
72
+ }
73
+ }
@@ -1,45 +1,45 @@
1
- import { Tester, readWasmFile } from './test_helper.js'
2
-
3
- type GlobalImportsExports = {
4
- get_offset: () => number
5
- compute: (x: number) => number
6
- run: (x: number) => number
7
- }
8
-
9
- export const suite = {
10
- name: 'wasm-import-global',
11
- run: (t: Tester) => {
12
- const giBuf = readWasmFile('./global_imports.wasm')
13
- if (!giBuf) { t.fail++; return }
14
- const giMod = new WebAssembly.Module(giBuf)
15
-
16
- t.section('import globals')
17
- var giInst: WebAssembly.Instance<GlobalImportsExports>
18
- try {
19
- giInst = new WebAssembly.Instance<GlobalImportsExports>(giMod, {
20
- env: {
21
- offset: new WebAssembly.Global({ value: 'i32', mutable: false }, 42),
22
- factor: new WebAssembly.Global({ value: 'f64', mutable: false }, 3.14),
23
- log: function (_x: number) { /* noop */ }
24
- }
25
- })
26
- } catch (e) {
27
- t.fail++; return
28
- }
29
- t.check('get_offset()', 42, giInst.exports.get_offset())
30
- t.check('compute(10)', 31.4, giInst.exports.compute(10))
31
- t.check('run(8)', 50, giInst.exports.run(8))
32
-
33
- t.section('second instance')
34
- var giInst2 = new WebAssembly.Instance<GlobalImportsExports>(giMod, {
35
- env: {
36
- offset: new WebAssembly.Global({ value: 'i32', mutable: false }, 100),
37
- factor: new WebAssembly.Global({ value: 'f64', mutable: false }, 2.0),
38
- log: function (_x: number) { /* noop */ }
39
- }
40
- })
41
- t.check('instance2 get_offset()', 100, giInst2.exports.get_offset())
42
- t.check('instance2 compute(5)', 10, giInst2.exports.compute(5))
43
- t.check('instance1 still get_offset()', 42, giInst.exports.get_offset())
44
- }
45
- }
1
+ import { Tester, readWasmFile } from './test_helper.js'
2
+
3
+ type GlobalImportsExports = {
4
+ get_offset: () => number
5
+ compute: (x: number) => number
6
+ run: (x: number) => number
7
+ }
8
+
9
+ export const suite = {
10
+ name: 'wasm-import-global',
11
+ run: (t: Tester) => {
12
+ const giBuf = readWasmFile('./global_imports.wasm')
13
+ if (!giBuf) { t.fail++; return }
14
+ const giMod = new WebAssembly.Module(giBuf)
15
+
16
+ t.section('import globals')
17
+ var giInst: WebAssembly.Instance<GlobalImportsExports>
18
+ try {
19
+ giInst = new WebAssembly.Instance<GlobalImportsExports>(giMod, {
20
+ env: {
21
+ offset: new WebAssembly.Global({ value: 'i32', mutable: false }, 42),
22
+ factor: new WebAssembly.Global({ value: 'f64', mutable: false }, 3.14),
23
+ log: function (_x: number) { /* noop */ }
24
+ }
25
+ })
26
+ } catch (e) {
27
+ t.fail++; return
28
+ }
29
+ t.check('get_offset()', 42, giInst.exports.get_offset())
30
+ t.check('compute(10)', 31.4, giInst.exports.compute(10))
31
+ t.check('run(8)', 50, giInst.exports.run(8))
32
+
33
+ t.section('second instance')
34
+ var giInst2 = new WebAssembly.Instance<GlobalImportsExports>(giMod, {
35
+ env: {
36
+ offset: new WebAssembly.Global({ value: 'i32', mutable: false }, 100),
37
+ factor: new WebAssembly.Global({ value: 'f64', mutable: false }, 2.0),
38
+ log: function (_x: number) { /* noop */ }
39
+ }
40
+ })
41
+ t.check('instance2 get_offset()', 100, giInst2.exports.get_offset())
42
+ t.check('instance2 compute(5)', 10, giInst2.exports.compute(5))
43
+ t.check('instance1 still get_offset()', 42, giInst.exports.get_offset())
44
+ }
45
+ }