buninu-browser 0.4.0 → 0.5.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 (99) hide show
  1. package/README.md +22 -1
  2. package/frontends/wayland/README.md +50 -21
  3. package/frontends/wayland/index.js +14 -0
  4. package/frontends/wayland/input.js +24 -5
  5. package/frontends/wayland/urlbar.js +9 -5
  6. package/lib/audio/shared-connection.js +31 -0
  7. package/lib/cdp-server.js +15 -2
  8. package/lib/happy-dom/inert-link.js +26 -0
  9. package/lib/happy-dom/node-iterator-removal.js +36 -0
  10. package/lib/happy-dom/node-replacement.js +60 -0
  11. package/lib/happy-dom/parser.js +4 -1
  12. package/lib/headless-shell.js +7 -4
  13. package/lib/layout/text-layout.js +4 -2
  14. package/lib/paint/display-list.js +2 -1
  15. package/lib/qml/README.md +456 -0
  16. package/lib/qml/builtins.js +76 -5
  17. package/lib/qml/canvas.js +76 -0
  18. package/lib/qml/document.js +47 -24
  19. package/lib/qml/fonts.js +69 -0
  20. package/lib/qml/host.js +28 -0
  21. package/lib/qml/loader.js +7 -3
  22. package/lib/qml/models.js +1 -1
  23. package/lib/qml/reactive.js +26 -3
  24. package/lib/qml/runtime.js +263 -41
  25. package/lib/qml/shader/fragment.js +83 -0
  26. package/lib/qml/shader/qsb.js +27 -0
  27. package/lib/qml/shader/renderer.js +39 -0
  28. package/lib/qml/shader/runtime.js +61 -0
  29. package/lib/qml/shapes.js +9 -1
  30. package/lib/qml/shortcuts.js +65 -0
  31. package/lib/qml/textures.js +4 -1
  32. package/lib/qml/window-constraints.js +16 -0
  33. package/lib/renderer/bindings.js +110 -4
  34. package/lib/renderer/canvas-2d.js +16 -0
  35. package/lib/renderer/document-selection.js +19 -0
  36. package/lib/renderer/host.js +14 -11
  37. package/lib/renderer/main.js +2 -0
  38. package/lib/renderer/page-realm.js +4 -9
  39. package/lib/renderer/page-renderer.js +283 -39
  40. package/lib/renderer/pointer-move.js +5 -3
  41. package/lib/renderer/render-interval.js +9 -0
  42. package/lib/style/computed-style.js +8 -2
  43. package/package.json +1 -1
  44. package/test/audio-connection-lifetime.test.js +46 -0
  45. package/test/canvas-paint.test.js +8 -0
  46. package/test/compare-node-iterator.js +42 -0
  47. package/test/computed-style.test.js +12 -0
  48. package/test/document-selection.test.js +27 -0
  49. package/test/double-click.test.js +85 -0
  50. package/test/fixtures/canvas-damage.js +40 -0
  51. package/test/fixtures/fake-renderer.js +1 -0
  52. package/test/fixtures/fractional-text-scale.js +38 -0
  53. package/test/fixtures/node-iterator-cases.js +59 -0
  54. package/test/fixtures/node-iterator-chromium.json +315 -0
  55. package/test/fixtures/omastorm-helpers/Dockerfile +35 -0
  56. package/test/fixtures/omastorm-helpers/check.mjs +56 -0
  57. package/test/fixtures/omastorm-helpers/launch.mjs +24 -0
  58. package/test/fixtures/omastorm-helpers/prepare.mjs +17 -0
  59. package/test/fixtures/omastorm-helpers/runtime.mjs +32 -0
  60. package/test/fixtures/pointer-paint-batching.js +23 -0
  61. package/test/fixtures/qml-fonts/main.qml +10 -0
  62. package/test/fixtures/qml-locale/check.mjs +6 -0
  63. package/test/fixtures/qml-locale/main.qml +8 -0
  64. package/test/fixtures/qml-shader/grab.qml +14 -0
  65. package/test/fixtures/qml-shader/gradient.frag +5 -0
  66. package/test/fixtures/qml-shader/main.qml +14 -0
  67. package/test/fixtures/qml-shader/texture-grab.qml +25 -0
  68. package/test/fixtures/qml-shader/texture-size.frag +5 -0
  69. package/test/fixtures/qml-shader-check.mjs +24 -0
  70. package/test/fixtures/title-no-paint.js +20 -0
  71. package/test/fractional-text-scale.test.js +6 -0
  72. package/test/inert-link.test.js +37 -0
  73. package/test/manual-double-click.html +21 -0
  74. package/test/manual-mouse-buttons.html +18 -0
  75. package/test/manual-omastorm-engine.mjs +19 -0
  76. package/test/manual-omastorm-shaders.mjs +28 -0
  77. package/test/manual-omastorm-software.mjs +25 -0
  78. package/test/manual-pointer-scroll.html +43 -0
  79. package/test/node-iterator.test.js +81 -0
  80. package/test/page-scripts.test.js +116 -1
  81. package/test/pointer-drag.test.js +104 -0
  82. package/test/qml-canvas.test.js +21 -0
  83. package/test/qml-connections-timing.test.js +22 -0
  84. package/test/qml-controls-window.test.js +182 -0
  85. package/test/qml-fonts.test.js +31 -0
  86. package/test/qml-grid-multiline.test.js +48 -0
  87. package/test/qml-locale.test.js +45 -0
  88. package/test/qml-nonvisual-visible.test.js +19 -0
  89. package/test/qml-shader-runtime.test.js +6 -0
  90. package/test/qml-shortcuts.test.js +39 -0
  91. package/test/qml-socket.test.js +60 -0
  92. package/test/qml-software-shader.test.js +55 -0
  93. package/test/qml-window-update.test.js +36 -0
  94. package/test/render-interval.test.js +33 -0
  95. package/test/text-layout.test.js +15 -0
  96. package/test/title-no-paint.test.js +6 -0
  97. package/test/wayland-scroll.test.js +40 -0
  98. package/test/wayland-urlbar.test.js +23 -0
  99. package/test/window-resize.test.js +29 -0
@@ -0,0 +1,315 @@
1
+ [
2
+ ["div","remove",0,false,"root",false,"b","b","b"],
3
+ ["div","remove",0,true,"root",true,"root","root","b"],
4
+ ["div","remove",1,false,"root",false,"b","b","b"],
5
+ ["div","remove",1,true,"b",true,"b","b","b"],
6
+ ["div","remove",2,false,"root",false,"b","b","b"],
7
+ ["div","remove",2,true,"b",true,"b","b","b"],
8
+ ["div","remove",3,false,"b",false,null,"b","b"],
9
+ ["div","remove",3,true,"b",true,"b","b","b"],
10
+ ["div","replace",0,false,"root",false,"x","x","x,b"],
11
+ ["div","replace",0,true,"root",true,"root","root","x,b"],
12
+ ["div","replace",1,false,"root",false,"x","x","x,b"],
13
+ ["div","replace",1,true,"b",true,"b","b","x,b"],
14
+ ["div","replace",2,false,"root",false,"x","x","x,b"],
15
+ ["div","replace",2,true,"b",true,"b","b","x,b"],
16
+ ["div","replace",3,false,"b",false,null,"b","x,b"],
17
+ ["div","replace",3,true,"b",true,"b","b","x,b"],
18
+ ["div","replaceWith",0,false,"root",false,"x","x","x,b"],
19
+ ["div","replaceWith",0,true,"root",true,"root","root","x,b"],
20
+ ["div","replaceWith",1,false,"root",false,"x","x","x,b"],
21
+ ["div","replaceWith",1,true,"b",true,"b","b","x,b"],
22
+ ["div","replaceWith",2,false,"root",false,"x","x","x,b"],
23
+ ["div","replaceWith",2,true,"b",true,"b","b","x,b"],
24
+ ["div","replaceWith",3,false,"b",false,null,"b","x,b"],
25
+ ["div","replaceWith",3,true,"b",true,"b","b","x,b"],
26
+ ["div","self",0,false,"root",false,"a","a","a,b"],
27
+ ["div","self",0,true,"root",true,"root","root","a,b"],
28
+ ["div","self",1,false,"root",false,"a","a","a,b"],
29
+ ["div","self",1,true,"b",true,"b","b","a,b"],
30
+ ["div","self",2,false,"root",false,"a","a","a,b"],
31
+ ["div","self",2,true,"b",true,"b","b","a,b"],
32
+ ["div","self",3,false,"b",false,null,"b","a,b"],
33
+ ["div","self",3,true,"b",true,"b","b","a,b"],
34
+ ["div","sibling",0,false,"root",false,"b","b","b"],
35
+ ["div","sibling",0,true,"root",true,"root","root","b"],
36
+ ["div","sibling",1,false,"root",false,"b","b","b"],
37
+ ["div","sibling",1,true,"a",true,"a","a","b"],
38
+ ["div","sibling",2,false,"root",false,"b","b","b"],
39
+ ["div","sibling",2,true,"nested",true,"nested","nested","b"],
40
+ ["div","sibling",3,false,"root",false,"b","b","b"],
41
+ ["div","sibling",3,true,"root",false,"b","b","b"],
42
+ ["div","fragment",0,false,"root",false,"x","x","x,y,b"],
43
+ ["div","fragment",0,true,"root",true,"root","root","x,y,b"],
44
+ ["div","fragment",1,false,"root",false,"x","x","x,y,b"],
45
+ ["div","fragment",1,true,"b",true,"b","b","x,y,b"],
46
+ ["div","fragment",2,false,"root",false,"x","x","x,y,b"],
47
+ ["div","fragment",2,true,"b",true,"b","b","x,y,b"],
48
+ ["div","fragment",3,false,"b",false,null,"b","x,y,b"],
49
+ ["div","fragment",3,true,"b",true,"b","b","x,y,b"],
50
+ ["div","descendant",0,false,"root",false,"nested","nested","nested,b"],
51
+ ["div","descendant",0,true,"root",true,"root","root","nested,b"],
52
+ ["div","descendant",1,false,"root",false,"nested","nested","nested,b"],
53
+ ["div","descendant",1,true,"b",true,"b","b","nested,b"],
54
+ ["div","descendant",2,false,"root",false,"nested","nested","nested,b"],
55
+ ["div","descendant",2,true,"b",true,"b","b","nested,b"],
56
+ ["div","descendant",3,false,"b",false,null,"b","nested,b"],
57
+ ["div","descendant",3,true,"b",true,"b","b","nested,b"],
58
+ ["div","multiple",0,false,"root",false,"x","x","x,a,b"],
59
+ ["div","multiple",0,true,"root",true,"root","root","x,a,b"],
60
+ ["div","multiple",1,false,"root",false,"x","x","x,a,b"],
61
+ ["div","multiple",1,true,"root",false,"x","x","x,a,b"],
62
+ ["div","multiple",2,false,"root",false,"x","x","x,a,b"],
63
+ ["div","multiple",2,true,"root",false,"x","x","x,a,b"],
64
+ ["div","multiple",3,false,"root",false,"x","x","x,a,b"],
65
+ ["div","multiple",3,true,"root",false,"x","x","x,a,b"],
66
+ ["form","remove",0,false,"root",false,"b","b","b"],
67
+ ["form","remove",0,true,"root",true,"root","root","b"],
68
+ ["form","remove",1,false,"root",false,"b","b","b"],
69
+ ["form","remove",1,true,"b",true,"b","b","b"],
70
+ ["form","remove",2,false,"root",false,"b","b","b"],
71
+ ["form","remove",2,true,"b",true,"b","b","b"],
72
+ ["form","remove",3,false,"b",false,null,"b","b"],
73
+ ["form","remove",3,true,"b",true,"b","b","b"],
74
+ ["form","replace",0,false,"root",false,"x","x","x,b"],
75
+ ["form","replace",0,true,"root",true,"root","root","x,b"],
76
+ ["form","replace",1,false,"root",false,"x","x","x,b"],
77
+ ["form","replace",1,true,"b",true,"b","b","x,b"],
78
+ ["form","replace",2,false,"root",false,"x","x","x,b"],
79
+ ["form","replace",2,true,"b",true,"b","b","x,b"],
80
+ ["form","replace",3,false,"b",false,null,"b","x,b"],
81
+ ["form","replace",3,true,"b",true,"b","b","x,b"],
82
+ ["form","replaceWith",0,false,"root",false,"x","x","x,b"],
83
+ ["form","replaceWith",0,true,"root",true,"root","root","x,b"],
84
+ ["form","replaceWith",1,false,"root",false,"x","x","x,b"],
85
+ ["form","replaceWith",1,true,"b",true,"b","b","x,b"],
86
+ ["form","replaceWith",2,false,"root",false,"x","x","x,b"],
87
+ ["form","replaceWith",2,true,"b",true,"b","b","x,b"],
88
+ ["form","replaceWith",3,false,"b",false,null,"b","x,b"],
89
+ ["form","replaceWith",3,true,"b",true,"b","b","x,b"],
90
+ ["form","self",0,false,"root",false,"a","a","a,b"],
91
+ ["form","self",0,true,"root",true,"root","root","a,b"],
92
+ ["form","self",1,false,"root",false,"a","a","a,b"],
93
+ ["form","self",1,true,"b",true,"b","b","a,b"],
94
+ ["form","self",2,false,"root",false,"a","a","a,b"],
95
+ ["form","self",2,true,"b",true,"b","b","a,b"],
96
+ ["form","self",3,false,"b",false,null,"b","a,b"],
97
+ ["form","self",3,true,"b",true,"b","b","a,b"],
98
+ ["form","sibling",0,false,"root",false,"b","b","b"],
99
+ ["form","sibling",0,true,"root",true,"root","root","b"],
100
+ ["form","sibling",1,false,"root",false,"b","b","b"],
101
+ ["form","sibling",1,true,"a",true,"a","a","b"],
102
+ ["form","sibling",2,false,"root",false,"b","b","b"],
103
+ ["form","sibling",2,true,"nested",true,"nested","nested","b"],
104
+ ["form","sibling",3,false,"root",false,"b","b","b"],
105
+ ["form","sibling",3,true,"root",false,"b","b","b"],
106
+ ["form","fragment",0,false,"root",false,"x","x","x,y,b"],
107
+ ["form","fragment",0,true,"root",true,"root","root","x,y,b"],
108
+ ["form","fragment",1,false,"root",false,"x","x","x,y,b"],
109
+ ["form","fragment",1,true,"b",true,"b","b","x,y,b"],
110
+ ["form","fragment",2,false,"root",false,"x","x","x,y,b"],
111
+ ["form","fragment",2,true,"b",true,"b","b","x,y,b"],
112
+ ["form","fragment",3,false,"b",false,null,"b","x,y,b"],
113
+ ["form","fragment",3,true,"b",true,"b","b","x,y,b"],
114
+ ["form","descendant",0,false,"root",false,"nested","nested","nested,b"],
115
+ ["form","descendant",0,true,"root",true,"root","root","nested,b"],
116
+ ["form","descendant",1,false,"root",false,"nested","nested","nested,b"],
117
+ ["form","descendant",1,true,"b",true,"b","b","nested,b"],
118
+ ["form","descendant",2,false,"root",false,"nested","nested","nested,b"],
119
+ ["form","descendant",2,true,"b",true,"b","b","nested,b"],
120
+ ["form","descendant",3,false,"b",false,null,"b","nested,b"],
121
+ ["form","descendant",3,true,"b",true,"b","b","nested,b"],
122
+ ["form","multiple",0,false,"root",false,"x","x","x,a,b"],
123
+ ["form","multiple",0,true,"root",true,"root","root","x,a,b"],
124
+ ["form","multiple",1,false,"root",false,"x","x","x,a,b"],
125
+ ["form","multiple",1,true,"root",false,"x","x","x,a,b"],
126
+ ["form","multiple",2,false,"root",false,"x","x","x,a,b"],
127
+ ["form","multiple",2,true,"root",false,"x","x","x,a,b"],
128
+ ["form","multiple",3,false,"root",false,"x","x","x,a,b"],
129
+ ["form","multiple",3,true,"root",false,"x","x","x,a,b"],
130
+ ["select","remove",0,false,"root",false,"b","b","b"],
131
+ ["select","remove",0,true,"root",true,"root","root","b"],
132
+ ["select","remove",1,false,"root",false,"b","b","b"],
133
+ ["select","remove",1,true,"b",true,"b","b","b"],
134
+ ["select","remove",2,false,"root",false,"b","b","b"],
135
+ ["select","remove",2,true,"b",true,"b","b","b"],
136
+ ["select","remove",3,false,"b",false,null,"b","b"],
137
+ ["select","remove",3,true,"b",true,"b","b","b"],
138
+ ["select","replace",0,false,"root",false,"x","x","x,b"],
139
+ ["select","replace",0,true,"root",true,"root","root","x,b"],
140
+ ["select","replace",1,false,"root",false,"x","x","x,b"],
141
+ ["select","replace",1,true,"b",true,"b","b","x,b"],
142
+ ["select","replace",2,false,"root",false,"x","x","x,b"],
143
+ ["select","replace",2,true,"b",true,"b","b","x,b"],
144
+ ["select","replace",3,false,"b",false,null,"b","x,b"],
145
+ ["select","replace",3,true,"b",true,"b","b","x,b"],
146
+ ["select","replaceWith",0,false,"root",false,"x","x","x,b"],
147
+ ["select","replaceWith",0,true,"root",true,"root","root","x,b"],
148
+ ["select","replaceWith",1,false,"root",false,"x","x","x,b"],
149
+ ["select","replaceWith",1,true,"b",true,"b","b","x,b"],
150
+ ["select","replaceWith",2,false,"root",false,"x","x","x,b"],
151
+ ["select","replaceWith",2,true,"b",true,"b","b","x,b"],
152
+ ["select","replaceWith",3,false,"b",false,null,"b","x,b"],
153
+ ["select","replaceWith",3,true,"b",true,"b","b","x,b"],
154
+ ["select","self",0,false,"root",false,"a","a","a,b"],
155
+ ["select","self",0,true,"root",true,"root","root","a,b"],
156
+ ["select","self",1,false,"root",false,"a","a","a,b"],
157
+ ["select","self",1,true,"b",true,"b","b","a,b"],
158
+ ["select","self",2,false,"root",false,"a","a","a,b"],
159
+ ["select","self",2,true,"b",true,"b","b","a,b"],
160
+ ["select","self",3,false,"b",false,null,"b","a,b"],
161
+ ["select","self",3,true,"b",true,"b","b","a,b"],
162
+ ["select","sibling",0,false,"root",false,"b","b","b"],
163
+ ["select","sibling",0,true,"root",true,"root","root","b"],
164
+ ["select","sibling",1,false,"root",false,"b","b","b"],
165
+ ["select","sibling",1,true,"a",true,"a","a","b"],
166
+ ["select","sibling",2,false,"root",false,"b","b","b"],
167
+ ["select","sibling",2,true,"nested",true,"nested","nested","b"],
168
+ ["select","sibling",3,false,"root",false,"b","b","b"],
169
+ ["select","sibling",3,true,"root",false,"b","b","b"],
170
+ ["select","fragment",0,false,"root",false,"x","x","x,y,b"],
171
+ ["select","fragment",0,true,"root",true,"root","root","x,y,b"],
172
+ ["select","fragment",1,false,"root",false,"x","x","x,y,b"],
173
+ ["select","fragment",1,true,"b",true,"b","b","x,y,b"],
174
+ ["select","fragment",2,false,"root",false,"x","x","x,y,b"],
175
+ ["select","fragment",2,true,"b",true,"b","b","x,y,b"],
176
+ ["select","fragment",3,false,"b",false,null,"b","x,y,b"],
177
+ ["select","fragment",3,true,"b",true,"b","b","x,y,b"],
178
+ ["select","descendant",0,false,"root",false,"nested","nested","nested,b"],
179
+ ["select","descendant",0,true,"root",true,"root","root","nested,b"],
180
+ ["select","descendant",1,false,"root",false,"nested","nested","nested,b"],
181
+ ["select","descendant",1,true,"b",true,"b","b","nested,b"],
182
+ ["select","descendant",2,false,"root",false,"nested","nested","nested,b"],
183
+ ["select","descendant",2,true,"b",true,"b","b","nested,b"],
184
+ ["select","descendant",3,false,"b",false,null,"b","nested,b"],
185
+ ["select","descendant",3,true,"b",true,"b","b","nested,b"],
186
+ ["select","multiple",0,false,"root",false,"x","x","x,a,b"],
187
+ ["select","multiple",0,true,"root",true,"root","root","x,a,b"],
188
+ ["select","multiple",1,false,"root",false,"x","x","x,a,b"],
189
+ ["select","multiple",1,true,"root",false,"x","x","x,a,b"],
190
+ ["select","multiple",2,false,"root",false,"x","x","x,a,b"],
191
+ ["select","multiple",2,true,"root",false,"x","x","x,a,b"],
192
+ ["select","multiple",3,false,"root",false,"x","x","x,a,b"],
193
+ ["select","multiple",3,true,"root",false,"x","x","x,a,b"],
194
+ ["mask","0",0],
195
+ ["mask","1",1],
196
+ ["mask","-1",4294967295],
197
+ ["mask","4294967297",1],
198
+ ["mask","NaN",0],
199
+ ["mask","Infinity",0],
200
+ ["mask","1",1],
201
+ ["mask","null",0],
202
+ ["mask","1","TypeError"],
203
+ ["mask","1","TypeError"],
204
+ ["mask","Symbol(x)","TypeError"],
205
+ ["filter","1",true],
206
+ ["filter","65537",true],
207
+ ["filter","-65535",true],
208
+ ["filter","NaN",false],
209
+ ["filter","Infinity",false],
210
+ ["filter","1",true],
211
+ ["filter","null",false],
212
+ ["filter","1","TypeError"],
213
+ ["filter","1","TypeError"],
214
+ ["filter","Symbol(x)","TypeError"],
215
+ ["walk","element",0,"accept","",""],
216
+ ["walk","element",0,"reject","",""],
217
+ ["walk","element",0,"skip","",""],
218
+ ["walk","element",0,"alternating","",""],
219
+ ["walk","element",1,"accept","1,1","1,1"],
220
+ ["walk","element",1,"reject","",""],
221
+ ["walk","element",1,"skip","",""],
222
+ ["walk","element",1,"alternating","",""],
223
+ ["walk","element",4,"accept","3","3"],
224
+ ["walk","element",4,"reject","",""],
225
+ ["walk","element",4,"skip","",""],
226
+ ["walk","element",4,"alternating","3","3"],
227
+ ["walk","element",128,"accept","8","8"],
228
+ ["walk","element",128,"reject","",""],
229
+ ["walk","element",128,"skip","",""],
230
+ ["walk","element",128,"alternating","8","8"],
231
+ ["walk","element",4294967295,"accept","1,1,3,8","8,3,1,1"],
232
+ ["walk","element",4294967295,"reject","",""],
233
+ ["walk","element",4294967295,"skip","",""],
234
+ ["walk","element",4294967295,"alternating","3,8","8,3"],
235
+ ["walk","fragment",0,"accept","",""],
236
+ ["walk","fragment",0,"reject","",""],
237
+ ["walk","fragment",0,"skip","",""],
238
+ ["walk","fragment",0,"alternating","",""],
239
+ ["walk","fragment",1,"accept","1","1"],
240
+ ["walk","fragment",1,"reject","",""],
241
+ ["walk","fragment",1,"skip","",""],
242
+ ["walk","fragment",1,"alternating","",""],
243
+ ["walk","fragment",4,"accept","3","3"],
244
+ ["walk","fragment",4,"reject","",""],
245
+ ["walk","fragment",4,"skip","",""],
246
+ ["walk","fragment",4,"alternating","3","3"],
247
+ ["walk","fragment",128,"accept","8","8"],
248
+ ["walk","fragment",128,"reject","",""],
249
+ ["walk","fragment",128,"skip","",""],
250
+ ["walk","fragment",128,"alternating","8","8"],
251
+ ["walk","fragment",4294967295,"accept","11,1,3,8","8,3,1,11"],
252
+ ["walk","fragment",4294967295,"reject","",""],
253
+ ["walk","fragment",4294967295,"skip","",""],
254
+ ["walk","fragment",4294967295,"alternating","11,3,8","8,3,11"],
255
+ ["walk","text",0,"accept","",""],
256
+ ["walk","text",0,"reject","",""],
257
+ ["walk","text",0,"skip","",""],
258
+ ["walk","text",0,"alternating","",""],
259
+ ["walk","text",1,"accept","",""],
260
+ ["walk","text",1,"reject","",""],
261
+ ["walk","text",1,"skip","",""],
262
+ ["walk","text",1,"alternating","",""],
263
+ ["walk","text",4,"accept","3","3"],
264
+ ["walk","text",4,"reject","",""],
265
+ ["walk","text",4,"skip","",""],
266
+ ["walk","text",4,"alternating","3","3"],
267
+ ["walk","text",128,"accept","",""],
268
+ ["walk","text",128,"reject","",""],
269
+ ["walk","text",128,"skip","",""],
270
+ ["walk","text",128,"alternating","",""],
271
+ ["walk","text",4294967295,"accept","3","3"],
272
+ ["walk","text",4294967295,"reject","",""],
273
+ ["walk","text",4294967295,"skip","",""],
274
+ ["walk","text",4294967295,"alternating","3","3"],
275
+ ["walk","comment",0,"accept","",""],
276
+ ["walk","comment",0,"reject","",""],
277
+ ["walk","comment",0,"skip","",""],
278
+ ["walk","comment",0,"alternating","",""],
279
+ ["walk","comment",1,"accept","",""],
280
+ ["walk","comment",1,"reject","",""],
281
+ ["walk","comment",1,"skip","",""],
282
+ ["walk","comment",1,"alternating","",""],
283
+ ["walk","comment",4,"accept","",""],
284
+ ["walk","comment",4,"reject","",""],
285
+ ["walk","comment",4,"skip","",""],
286
+ ["walk","comment",4,"alternating","",""],
287
+ ["walk","comment",128,"accept","8","8"],
288
+ ["walk","comment",128,"reject","",""],
289
+ ["walk","comment",128,"skip","",""],
290
+ ["walk","comment",128,"alternating","8","8"],
291
+ ["walk","comment",4294967295,"accept","8","8"],
292
+ ["walk","comment",4294967295,"reject","",""],
293
+ ["walk","comment",4294967295,"skip","",""],
294
+ ["walk","comment",4294967295,"alternating","8","8"],
295
+ ["walk","doctype",0,"accept","",""],
296
+ ["walk","doctype",0,"reject","",""],
297
+ ["walk","doctype",0,"skip","",""],
298
+ ["walk","doctype",0,"alternating","",""],
299
+ ["walk","doctype",1,"accept","",""],
300
+ ["walk","doctype",1,"reject","",""],
301
+ ["walk","doctype",1,"skip","",""],
302
+ ["walk","doctype",1,"alternating","",""],
303
+ ["walk","doctype",4,"accept","",""],
304
+ ["walk","doctype",4,"reject","",""],
305
+ ["walk","doctype",4,"skip","",""],
306
+ ["walk","doctype",4,"alternating","",""],
307
+ ["walk","doctype",128,"accept","",""],
308
+ ["walk","doctype",128,"reject","",""],
309
+ ["walk","doctype",128,"skip","",""],
310
+ ["walk","doctype",128,"alternating","",""],
311
+ ["walk","doctype",4294967295,"accept","10","10"],
312
+ ["walk","doctype",4294967295,"reject","",""],
313
+ ["walk","doctype",4294967295,"skip","",""],
314
+ ["walk","doctype",4294967295,"alternating","10","10"]
315
+ ]
@@ -0,0 +1,35 @@
1
+ # Build context: buninu-browser root. Single-stage, js-udocker-compatible syntax.
2
+ FROM oven/bun:1.4.4
3
+ ENV DEBIAN_FRONTEND=noninteractive
4
+ ENV HOME=/root
5
+ ENV LC_ALL=C.UTF-8
6
+ RUN set -eu; if [ -f /usr/bin/perl ] && [ ! -e /usr/bin/perl5.40.1 ]; then cp /usr/bin/perl /usr/bin/perl5.40.1; fi
7
+ RUN set -eu; apt-get update; apt-get install -y --no-install-recommends ca-certificates curl libgcc-s1; apt-get clean
8
+ RUN set -eu; mkdir -p /opt/omastorm; curl -fL --retry 3 https://codeload.github.com/wesleygrimes/omastorm/tar.gz/492e97841146bd9d6d9f7a3064e5e1ae9840cc68 -o /tmp/omastorm.tar.gz; tar -xzf /tmp/omastorm.tar.gz --strip-components=1 -C /opt/omastorm; rm /tmp/omastorm.tar.gz
9
+ RUN set -eu; cd /opt/omastorm; XDG_DATA_HOME=/usr/local/share bash scripts/fetch-engine.sh; ln -sfn /usr/local/share/omastorm/bin/omastorm-engine /usr/local/bin/omastorm-engine
10
+ RUN set -eu; mkdir -p /usr/local/share/fonts/omastorm; curl -fL --retry 3 https://raw.githubusercontent.com/ryanoasis/nerd-fonts/v3.4.0/patched-fonts/JetBrainsMono/Ligatures/Regular/JetBrainsMonoNerdFontMono-Regular.ttf -o /usr/local/share/fonts/omastorm/JetBrainsMonoNerdFontMono-Regular.ttf; curl -fL --retry 3 https://raw.githubusercontent.com/ryanoasis/nerd-fonts/v3.4.0/patched-fonts/JetBrainsMono/Ligatures/Regular/OFL.txt -o /usr/local/share/fonts/omastorm/OFL.txt
11
+ COPY index.js /opt/buninu-browser/index.js
12
+ COPY buninu-browser.js /opt/buninu-browser/buninu-browser.js
13
+ COPY frontends /opt/buninu-browser/frontends
14
+ COPY usr /opt/buninu-browser/usr
15
+ COPY lib /opt/buninu-browser/lib
16
+ COPY vendor /opt/buninu-browser/vendor
17
+ COPY LICENSES /opt/buninu-browser/LICENSES
18
+ COPY LICENSE /opt/buninu-browser/LICENSE
19
+ COPY THIRD_PARTY_NOTICES.md /opt/buninu-browser/THIRD_PARTY_NOTICES.md
20
+ COPY package.json /opt/buninu-browser/package.json
21
+ COPY test/fixtures/omastorm-helpers /usr/local/lib/omastorm-helpers
22
+ ENV OMASTORM_ROOT=/opt/omastorm
23
+ ENV OMASTORM_ENGINE_BINARY=/usr/local/bin/omastorm-engine
24
+ ENV QT_QPA_FONTDIR=/usr/local/share/fonts/omastorm
25
+ ENV XDG_RUNTIME_DIR=/tmp
26
+ ENV WAYLAND_DISPLAY=/tmp/wayland-buninu
27
+ ENV XDG_CONFIG_HOME=/root/.config
28
+ ENV XDG_DATA_HOME=/root/.local/share
29
+ ENV XDG_STATE_HOME=/root/.local/state
30
+ ENV XDG_CACHE_HOME=/root/.cache
31
+ RUN bun /usr/local/lib/omastorm-helpers/prepare.mjs /opt/omastorm
32
+ RUN bun /usr/local/lib/omastorm-helpers/check.mjs
33
+ WORKDIR /root
34
+ ENTRYPOINT []
35
+ CMD ["bun", "/usr/local/lib/omastorm-helpers/launch.mjs"]
@@ -0,0 +1,56 @@
1
+ // Build-time smoke test: no Wayland socket, GPU, Rust compiler or native Qt.
2
+ import {strict as assert} from 'node:assert';
3
+ import {mkdtemp,rm} from 'node:fs/promises';
4
+ import {pathToFileURL} from 'node:url';
5
+ import {startEngine} from './runtime.mjs';
6
+ const root=process.env.OMASTORM_ROOT||'/opt/omastorm';
7
+ const browser=process.env.BUNINU_BROWSER_ROOT||'/opt/buninu-browser';
8
+ assert.equal(Bun.version,'1.4.4','Expected the pinned oven/bun:1.4.4 runtime');
9
+ for(const name of ['TextureCheck.qml','RadarMap.qml']) {
10
+ const source=await Bun.file(root+'/ui/'+name).text();
11
+ assert(!source.includes('GraphicsInfo.api === GraphicsInfo.Software'),'Software policy was not prepared');
12
+ assert(await Bun.file(root+'/ui/'+name+'.upstream').exists(),'Missing upstream backup');
13
+ }
14
+ const {loadGraphics}=await import(pathToFileURL(browser+'/lib/renderer/page-renderer.js').href);
15
+ const {fragmentSource}=await import(pathToFileURL(browser+'/lib/qml/shader/qsb.js').href);
16
+ const {compileFragment}=await import(pathToFileURL(browser+'/lib/qml/shader/fragment.js').href);
17
+ const {CanvasKit}=await loadGraphics();
18
+ for(const name of ['radar','tile','grid','texture-check']) {
19
+ const compiled=compileFragment(CanvasKit,fragmentSource(await Bun.file(root+'/ui/shaders/'+name+'.frag.qsb').bytes()));
20
+ compiled.effect.delete();
21
+ }
22
+ const font=CanvasKit.Typeface.MakeTypefaceFromData(await Bun.file(process.env.QT_QPA_FONTDIR+'/JetBrainsMonoNerdFontMono-Regular.ttf').bytes());
23
+ assert(font,'Font cannot be decoded');
24
+ assert([...font.getGlyphIDs('󰐊󰏤󰍉󰌾󰌌')].every(id=>id!==0),'Nerd icons missing');font.delete();
25
+ const help=Bun.spawn([process.env.OMASTORM_ENGINE_BINARY||'/usr/local/bin/omastorm-engine','--help'],{stdout:'pipe',stderr:'pipe'});
26
+ const [helpOut,helpErr,helpCode]=await Promise.all([new Response(help.stdout).text(),new Response(help.stderr).text(),help.exited]);
27
+ assert(helpCode===1 && (helpOut+helpErr).includes('Usage: omastorm-engine'),'Official engine could not execute');
28
+ // During js-udocker build the unbound ROOT/tmp path may exceed AF_UNIX's
29
+ // native path limit. Exercise the socket after binding host TMPDIR to /tmp.
30
+ if(process.argv.includes('--engine')) {
31
+ const engine=await startEngine();
32
+ try {
33
+ await new Promise((resolve,reject)=>{
34
+ let connection,buffer='';
35
+ const timer=setTimeout(()=>{connection?.end();reject(Error('No engine hello'));},10000);
36
+ Bun.connect({unix:engine.socket,socket:{
37
+ open(s){connection=s;},
38
+ data(s,data){buffer+=Buffer.from(data).toString();const i=buffer.indexOf('\n');if(i<0)return;
39
+ try{const hello=JSON.parse(buffer.slice(0,i));assert.equal(hello.type,'hello');assert(hello.sites?.length>0);clearTimeout(timer);s.end();resolve();}
40
+ catch(e){clearTimeout(timer);s.end();reject(e);}},
41
+ error(s,e){clearTimeout(timer);reject(e);},
42
+ }}).catch(e=>{clearTimeout(timer);reject(e);});
43
+ });
44
+ }finally{await engine.close();}
45
+ }
46
+ const scratch=await mkdtemp('/tmp/omastorm-build-check-');
47
+ const {createBrowser}=await import(pathToFileURL(browser+'/lib/headless-shell.js').href);
48
+ const page=await createBrowser({spareRenderer:false});
49
+ try {
50
+ const qml=scratch+'/main.qml';
51
+ await Bun.write(qml,'import QtQuick\nRectangle {width:320;height:120;color:"white";Text {text:"Omastorm 󰐊 󰍉";font.family:"monospace";color:"black"}}');
52
+ await page.context.navigate(pathToFileURL(qml).href);
53
+ assert((await page.context.evaluate('document.body.innerText')).includes('Omastorm'),'QML did not render');
54
+ assert((await page.context.screenshot({format:'png'})).length>100,'Empty screenshot');
55
+ }finally{page.close();await rm(scratch,{recursive:true,force:true});}
56
+ console.log('PASS: Bun 1.4.4, official engine executable, four software shaders, Nerd Font icons and QML screenshot'+(process.argv.includes('--engine')?', engine hello/site list':''));
@@ -0,0 +1,24 @@
1
+ import {pathToFileURL} from 'node:url';
2
+ import {stat} from 'node:fs/promises';
3
+ import {startEngine,waylandPath} from './runtime.mjs';
4
+ const socket=waylandPath();
5
+ if(!await stat(socket).then(s=>s.isSocket(),()=>false))throw Error('Start Land and bind its socket to '+socket);
6
+ const root=process.env.OMASTORM_ROOT||'/opt/omastorm';
7
+ const browser=process.env.BUNINU_BROWSER_ROOT||'/opt/buninu-browser';
8
+ let engine,app,stopping=false;
9
+ const stop=()=>{stopping=true;app?.close();};
10
+ for(const signal of ['SIGINT','SIGTERM','SIGHUP'])process.on(signal,stop);
11
+ try {
12
+ engine=await startEngine();
13
+ // Set before importing the renderer/QML host, which snapshots environment.
14
+ Object.assign(process.env,engine.env,{WAYLAND_DISPLAY:socket,OMASTORM_ROOT:root});
15
+ const {launch}=await import(pathToFileURL(browser+'/frontends/wayland/index.js').href);
16
+ if(!stopping){
17
+ app=await launch({url:pathToFileURL(root+'/ui/shell.qml').href,socket,width:960,height:680,chrome:false});
18
+ if(stopping)app.close();
19
+ await Promise.race([app.done,engine.child.exited.then(code=>{throw Error('Omastorm engine stopped: '+code);})]);
20
+ }
21
+ }finally{
22
+ app?.close();await engine?.close();
23
+ for(const signal of ['SIGINT','SIGTERM','SIGHUP'])process.off(signal,stop);
24
+ }
@@ -0,0 +1,17 @@
1
+ // Explicit app experiment, never a browser/renderer special case.
2
+ import {readFile,writeFile,copyFile} from 'node:fs/promises';
3
+ import {resolve} from 'node:path';
4
+ export async function prepare(root) {
5
+ const replacements=[
6
+ ['TextureCheck.qml', / if \(GraphicsInfo\.api === GraphicsInfo\.Software\) \{\n fail\("Radar requires GPU rendering \(OpenGL\/Vulkan\)\."\);\n return;\n \}\n/],
7
+ ['RadarMap.qml', / Component\.onCompleted: if \(GraphicsInfo\.api === GraphicsInfo\.Software\) map\.graphicsError = "Radar requires GPU rendering \(OpenGL\/Vulkan\)\."\n/],
8
+ ];
9
+ // Validate both before changing either. Keep originals for inspection.
10
+ const sources=await Promise.all(replacements.map(async([name,pattern])=>{
11
+ const path=resolve(root,'ui',name),source=await readFile(path,'utf8');
12
+ if(!pattern.test(source))throw Error('Upstream software policy changed; review '+name);
13
+ return {path,source,pattern};
14
+ }));
15
+ for(const {path,source,pattern} of sources){await copyFile(path,path+'.upstream');await writeFile(path,source.replace(pattern,''));}
16
+ }
17
+ if(import.meta.main)await prepare(resolve(process.argv[2]||'/opt/omastorm'));
@@ -0,0 +1,32 @@
1
+ import {mkdtemp,rm,stat} from 'node:fs/promises';
2
+ import {resolve,isAbsolute} from 'node:path';
3
+ export async function startEngine() {
4
+ const runtime=await mkdtemp('/tmp/omastorm-buninu-');
5
+ const engine=process.env.OMASTORM_ENGINE_BINARY||'/usr/local/bin/omastorm-engine';
6
+ const env={...process.env,XDG_RUNTIME_DIR:runtime,OMASTORM_ENGINE_BINARY:engine};
7
+ let child;
8
+ const close=async()=>{
9
+ if(child && child.exitCode===null){
10
+ child.kill('SIGTERM');
11
+ const timer=setTimeout(()=>{if(child.exitCode===null)child.kill('SIGKILL');},3000);
12
+ try{await child.exited;}finally{clearTimeout(timer);}
13
+ }
14
+ await rm(runtime,{recursive:true,force:true});
15
+ };
16
+ try {
17
+ child=Bun.spawn([engine,'serve'],{env,stdin:'ignore',stdout:'inherit',stderr:'inherit'});
18
+ const socket=runtime+'/omastorm/engine.sock';
19
+ const deadline=Date.now()+15000;
20
+ while(true){
21
+ if(child.exitCode!==null)throw Error('Omastorm engine exited: '+child.exitCode);
22
+ if(await stat(socket).then(s=>s.isSocket(),()=>false))break;
23
+ if(Date.now()>deadline)throw Error('Omastorm engine socket did not become ready');
24
+ await Bun.sleep(50);
25
+ }
26
+ return {env,socket,child,close};
27
+ }catch(e){await close();throw e;}
28
+ }
29
+ export function waylandPath(env=process.env){
30
+ const path=env.WAYLAND_DISPLAY||'/tmp/wayland-buninu';
31
+ return isAbsolute(path)?path:resolve(env.XDG_RUNTIME_DIR||'/tmp',path);
32
+ }
@@ -0,0 +1,23 @@
1
+ import {strict as assert} from 'node:assert';
2
+ import {createPageRenderer} from '../../lib/renderer/page-renderer.js';
3
+ let frames=0;
4
+ const r=await createPageRenderer({onFrame:()=>frames++});
5
+ try {
6
+ r.resize(400,300,1);
7
+ r.setScripting('host');
8
+ await r.loadDocument({url:'https://paint.test/',contentType:'text/html',source:`
9
+ <body style="margin:0"><canvas width="400" height="300"></canvas><script>
10
+ globalThis.moves=0;
11
+ const c=document.querySelector('canvas'),ctx=c.getContext('2d');
12
+ c.onmousemove=e=>{moves++;ctx.fillRect(e.clientX,e.clientY,2,2)};
13
+ </script>`});
14
+ await r.whenLoaded();
15
+ await Bun.sleep(100);
16
+ frames=0;
17
+ for(let i=0;i<50;i++)r.move(20+i,30);
18
+ assert.equal(frames,0,'input must not synchronously rasterize each motion');
19
+ await Bun.sleep(100);
20
+ assert.ok(frames>0 && frames<50,'queued canvas changes must reach the compositor');
21
+ assert.equal(await r.evaluate('moves'),50,'all drawing points must be delivered');
22
+ assert.equal(await r.evaluate("document.querySelector('canvas').getContext('2d').getImageData(69,30,1,1).data[3]"),255);
23
+ } finally {r.dispose()}
@@ -0,0 +1,10 @@
1
+ import QtQuick
2
+ import Quickshell
3
+ FloatingWindow {
4
+ width: 600; height: 200; color: "#18202a"
5
+ Text { x: 20; y: 20; text: "Text: 󰐊 󰏤 󰍉 󰌾 󰌌"; font.family: "monospace"; font.pixelSize: 32; color: "white" }
6
+ Canvas {
7
+ x:20; y:90; width:560; height:80
8
+ onPaint: { let c=getContext("2d"); c.font="32px monospace"; c.fillStyle="white"; c.fillText("Canvas: 󰐊 󰏤 󰍉 󰌾 󰌌",0,40); }
9
+ }
10
+ }
@@ -0,0 +1,6 @@
1
+ import {createBrowser} from '../../../lib/headless-shell.js';
2
+ const b=await createBrowser({spareRenderer:false});
3
+ try {
4
+ await b.context.navigate(new URL('main.qml',import.meta.url).href);
5
+ console.log(JSON.stringify(await b.context.evaluate('localeResult')));
6
+ } finally {b.close();}
@@ -0,0 +1,8 @@
1
+ import QtQuick
2
+ import Quickshell
3
+ ShellRoot {
4
+ Component.onCompleted: {
5
+ var l=Qt.locale();
6
+ globalThis.localeResult={name:l.name,measurement:l.measurementSystem,date:l.dateFormat(Locale.ShortFormat),time:l.timeFormat(Locale.ShortFormat)};
7
+ }
8
+ }
@@ -0,0 +1,14 @@
1
+ import QtQuick
2
+ Rectangle {
3
+ id:root;width:64;height:64;color:"red"
4
+ Canvas {
5
+ id:reader;width:1;height:1;visible:false
6
+ onImageLoaded:{
7
+ var image=getContext("2d").createImageData(globalThis.grabUrl);
8
+ globalThis.grabPixels=Array.from(image.data).slice(0,4);
9
+ unloadImage(globalThis.grabUrl);
10
+ globalThis.unloaded=!isImageLoaded(globalThis.grabUrl);
11
+ }
12
+ }
13
+ Component.onCompleted:Qt.callLater(function(){root.grabToImage(function(result){globalThis.grabUrl=result.url;reader.loadImage(result.url);},Qt.size(16,16));})
14
+ }
@@ -0,0 +1,5 @@
1
+ #version 440
2
+ layout(location=0) in vec2 qt_TexCoord0;
3
+ layout(location=0) out vec4 fragColor;
4
+ layout(std140,binding=0) uniform buf {mat4 qt_Matrix;float qt_Opacity;float phase;};
5
+ void main(){fragColor=vec4(qt_TexCoord0.x,qt_TexCoord0.y,phase,1.0)*qt_Opacity;}
@@ -0,0 +1,14 @@
1
+ import QtQuick
2
+ Rectangle {
3
+ width: 640; height: 420; color: "#161b22"
4
+ Text { x:20; y:12; text:"Software ShaderEffect / click the gradient"; color:"white"; font.pixelSize:20 }
5
+ ShaderEffect {
6
+ id: shader
7
+ x:20; y:52; width:600; height:320
8
+ property real phase:0.2
9
+ fragmentShader:"gradient.frag"
10
+ MouseArea { anchors.fill:parent; onClicked:shader.phase=shader.phase < 0.5 ? 0.9 : 0.2 }
11
+ Component.onCompleted:globalThis.testShader=shader
12
+ }
13
+ Text { x:20; y:385; text:shader.status===1 ? "CPU raster / blue = "+shader.phase : shader.log; color:"#58d5dd";font.pixelSize:16 }
14
+ }
@@ -0,0 +1,25 @@
1
+ import QtQuick
2
+ Rectangle {
3
+ width:64;height:64;color:"black"
4
+ Image {
5
+ id:input;visible:false
6
+ source:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAADCAIAAAA2iEnWAAAAEElEQVR4nGP4z8AARAwoFABE0AX7pM/egAAAAABJRU5ErkJggg=="
7
+ }
8
+ ShaderEffect {
9
+ id:probe;width:16;height:16
10
+ property var source:input
11
+ property vector2d expected:Qt.vector2d(2,3)
12
+ fragmentShader:"texture-size.frag"
13
+ }
14
+ Canvas {
15
+ id:reader;width:1;height:1;visible:false
16
+ onImageLoaded:{
17
+ globalThis.grabPixels=Array.from(getContext("2d").createImageData(globalThis.grabUrl).data).slice(0,4);
18
+ unloadImage(globalThis.grabUrl);
19
+ globalThis.unloaded=!isImageLoaded(globalThis.grabUrl);
20
+ }
21
+ }
22
+ Timer {interval:100;running:true;repeat:true;onTriggered:{
23
+ if(input.status===Image.Ready && probe.status===ShaderEffect.Compiled){stop();probe.grabToImage(function(result){globalThis.grabUrl=result.url;reader.loadImage(result.url);},Qt.size(16,16));}
24
+ }}
25
+ }
@@ -0,0 +1,5 @@
1
+ #version 440
2
+ layout(location=0) out vec4 fragColor;
3
+ layout(binding=1) uniform sampler2D source;
4
+ layout(std140,binding=0) uniform buf {vec2 expected;};
5
+ void main(){fragColor=textureSize(source,0)==ivec2(expected)?vec4(0,1,0,1):vec4(1,0,0,1);}