@xincli/opentui-core 0.4.6

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 (476) hide show
  1. package/README.md +63 -0
  2. package/dev/keypress-debug-renderer.ts +148 -0
  3. package/dev/keypress-debug.ts +43 -0
  4. package/dev/print-env-vars.ts +32 -0
  5. package/dev/test-tmux-graphics-334.sh +68 -0
  6. package/dev/test-tmux-theme-queries.sh +151 -0
  7. package/dev/thai-debug-test.ts +68 -0
  8. package/dev/theme-mode.ts +290 -0
  9. package/docs/development.md +144 -0
  10. package/package.json +102 -0
  11. package/prebuilt/aarch64-android/libopentui.so +0 -0
  12. package/scripts/build-android.ts +226 -0
  13. package/scripts/build-native-termux.sh +525 -0
  14. package/scripts/build.ts +530 -0
  15. package/scripts/dist-test.ts +312 -0
  16. package/scripts/package-prebuilt.ts +110 -0
  17. package/scripts/publish.ts +60 -0
  18. package/scripts/test-node-hook.mjs +16 -0
  19. package/scripts/test-node.ts +241 -0
  20. package/scripts/vendor-deps.sh +73 -0
  21. package/src/NativeSpanFeed.ts +375 -0
  22. package/src/Renderable.ts +1878 -0
  23. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  24. package/src/animation/Timeline.test.ts +2709 -0
  25. package/src/animation/Timeline.ts +598 -0
  26. package/src/ansi.ts +22 -0
  27. package/src/audio.ts +479 -0
  28. package/src/benchmark/attenuation-benchmark.ts +81 -0
  29. package/src/benchmark/audio-playback-benchmark.ts +344 -0
  30. package/src/benchmark/box-draw-benchmark.ts +1042 -0
  31. package/src/benchmark/colormatrix-benchmark.ts +123 -0
  32. package/src/benchmark/gain-benchmark.ts +80 -0
  33. package/src/benchmark/latest-all-bench-run.json +707 -0
  34. package/src/benchmark/latest-async-bench-run.json +336 -0
  35. package/src/benchmark/latest-default-bench-run.json +657 -0
  36. package/src/benchmark/latest-large-bench-run.json +707 -0
  37. package/src/benchmark/latest-quick-bench-run.json +207 -0
  38. package/src/benchmark/layout-benchmark.ts +2547 -0
  39. package/src/benchmark/markdown-benchmark.ts +1796 -0
  40. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  41. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  42. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  43. package/src/benchmark/native-span-feed-compare.ts +280 -0
  44. package/src/benchmark/render-traversal-benchmark.ts +928 -0
  45. package/src/benchmark/text-buffer-render-benchmark.ts +874 -0
  46. package/src/benchmark/text-table-benchmark.ts +948 -0
  47. package/src/buffer.test.ts +292 -0
  48. package/src/buffer.ts +564 -0
  49. package/src/console.test.ts +629 -0
  50. package/src/console.ts +1253 -0
  51. package/src/edit-buffer.test.ts +1852 -0
  52. package/src/edit-buffer.ts +417 -0
  53. package/src/editor-view.test.ts +1056 -0
  54. package/src/editor-view.ts +290 -0
  55. package/src/index.ts +25 -0
  56. package/src/lib/KeyHandler.integration.test.ts +292 -0
  57. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  58. package/src/lib/KeyHandler.test.ts +662 -0
  59. package/src/lib/KeyHandler.ts +222 -0
  60. package/src/lib/RGBA.test.ts +60 -0
  61. package/src/lib/RGBA.ts +343 -0
  62. package/src/lib/ascii.font.ts +330 -0
  63. package/src/lib/border.test.ts +83 -0
  64. package/src/lib/border.ts +170 -0
  65. package/src/lib/bunfs.test.ts +27 -0
  66. package/src/lib/bunfs.ts +18 -0
  67. package/src/lib/clipboard.test.ts +63 -0
  68. package/src/lib/clipboard.ts +41 -0
  69. package/src/lib/clock.ts +35 -0
  70. package/src/lib/data-paths.test.ts +133 -0
  71. package/src/lib/data-paths.ts +109 -0
  72. package/src/lib/debounce.ts +106 -0
  73. package/src/lib/detect-links.test.ts +98 -0
  74. package/src/lib/detect-links.ts +56 -0
  75. package/src/lib/env.test.ts +228 -0
  76. package/src/lib/env.ts +209 -0
  77. package/src/lib/extmarks-history.ts +51 -0
  78. package/src/lib/extmarks-multiwidth.test.ts +324 -0
  79. package/src/lib/extmarks.test.ts +3547 -0
  80. package/src/lib/extmarks.ts +861 -0
  81. package/src/lib/fonts/block.json +405 -0
  82. package/src/lib/fonts/grid.json +265 -0
  83. package/src/lib/fonts/huge.json +741 -0
  84. package/src/lib/fonts/pallet.json +314 -0
  85. package/src/lib/fonts/shade.json +591 -0
  86. package/src/lib/fonts/slick.json +321 -0
  87. package/src/lib/fonts/tiny.json +69 -0
  88. package/src/lib/hast-styled-text.ts +59 -0
  89. package/src/lib/index.ts +22 -0
  90. package/src/lib/keybinding.internal.test.ts +342 -0
  91. package/src/lib/keybinding.internal.ts +182 -0
  92. package/src/lib/objects-in-viewport.test.ts +789 -0
  93. package/src/lib/objects-in-viewport.ts +153 -0
  94. package/src/lib/output.capture.ts +58 -0
  95. package/src/lib/parse.keypress-kitty.protocol.test.ts +347 -0
  96. package/src/lib/parse.keypress-kitty.test.ts +712 -0
  97. package/src/lib/parse.keypress-kitty.ts +470 -0
  98. package/src/lib/parse.keypress.test.ts +2020 -0
  99. package/src/lib/parse.keypress.ts +480 -0
  100. package/src/lib/parse.mouse.test.ts +552 -0
  101. package/src/lib/parse.mouse.ts +232 -0
  102. package/src/lib/paste.ts +18 -0
  103. package/src/lib/queue.ts +65 -0
  104. package/src/lib/render-geometry.ts +36 -0
  105. package/src/lib/renderable.validations.test.ts +87 -0
  106. package/src/lib/renderable.validations.ts +83 -0
  107. package/src/lib/scroll-acceleration.ts +98 -0
  108. package/src/lib/selection.ts +261 -0
  109. package/src/lib/singleton.ts +34 -0
  110. package/src/lib/stdin-parser.test.ts +2439 -0
  111. package/src/lib/stdin-parser.ts +2007 -0
  112. package/src/lib/styled-text.ts +178 -0
  113. package/src/lib/terminal-capability-detection.test.ts +226 -0
  114. package/src/lib/terminal-capability-detection.ts +98 -0
  115. package/src/lib/terminal-palette.test.ts +954 -0
  116. package/src/lib/terminal-palette.ts +441 -0
  117. package/src/lib/tree-sitter/assets/README.md +119 -0
  118. package/src/lib/tree-sitter/assets/javascript/highlights.scm +205 -0
  119. package/src/lib/tree-sitter/assets/javascript/tree-sitter-javascript.wasm +0 -0
  120. package/src/lib/tree-sitter/assets/markdown/highlights.scm +150 -0
  121. package/src/lib/tree-sitter/assets/markdown/injections.scm +27 -0
  122. package/src/lib/tree-sitter/assets/markdown/tree-sitter-markdown.wasm +0 -0
  123. package/src/lib/tree-sitter/assets/markdown_inline/highlights.scm +115 -0
  124. package/src/lib/tree-sitter/assets/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  125. package/src/lib/tree-sitter/assets/typescript/highlights.scm +604 -0
  126. package/src/lib/tree-sitter/assets/typescript/tree-sitter-typescript.wasm +0 -0
  127. package/src/lib/tree-sitter/assets/update.ts +360 -0
  128. package/src/lib/tree-sitter/assets/zig/highlights.scm +284 -0
  129. package/src/lib/tree-sitter/assets/zig/tree-sitter-zig.wasm +0 -0
  130. package/src/lib/tree-sitter/assets.d.ts +9 -0
  131. package/src/lib/tree-sitter/cache.test.ts +291 -0
  132. package/src/lib/tree-sitter/client.test.ts +1434 -0
  133. package/src/lib/tree-sitter/client.ts +847 -0
  134. package/src/lib/tree-sitter/default-parsers.ts +133 -0
  135. package/src/lib/tree-sitter/download-utils.ts +148 -0
  136. package/src/lib/tree-sitter/index.ts +75 -0
  137. package/src/lib/tree-sitter/parser.worker.ts +1098 -0
  138. package/src/lib/tree-sitter/parsers-config.ts +81 -0
  139. package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
  140. package/src/lib/tree-sitter/resolve-ft.ts +189 -0
  141. package/src/lib/tree-sitter/types.ts +132 -0
  142. package/src/lib/tree-sitter/update-assets.ts +10 -0
  143. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  144. package/src/lib/tree-sitter-styled-text.ts +314 -0
  145. package/src/lib/validate-dir-name.ts +55 -0
  146. package/src/lib/yoga.options.test.ts +628 -0
  147. package/src/lib/yoga.options.ts +346 -0
  148. package/src/native-event-worker-repro.test.ts +48 -0
  149. package/src/native-event-worker-repro.worker.ts +9 -0
  150. package/src/native-handle.test.ts +221 -0
  151. package/src/platform/ffi.test.ts +516 -0
  152. package/src/platform/ffi.ts +653 -0
  153. package/src/platform/runtime.test.ts +52 -0
  154. package/src/platform/runtime.ts +121 -0
  155. package/src/platform/test.ts +45 -0
  156. package/src/platform/worker-handler-cleanup.fixture.ts +12 -0
  157. package/src/platform/worker-onmessage-startup.fixture.ts +10 -0
  158. package/src/platform/worker-startup.fixture.ts +9 -0
  159. package/src/platform/worker.node-test.ts +153 -0
  160. package/src/platform/worker.ts +425 -0
  161. package/src/plugins/core-slot.ts +579 -0
  162. package/src/plugins/registry.ts +402 -0
  163. package/src/plugins/types.ts +46 -0
  164. package/src/post/effects.ts +948 -0
  165. package/src/post/filters.ts +512 -0
  166. package/src/post/matrices.ts +288 -0
  167. package/src/renderables/ASCIIFont.ts +219 -0
  168. package/src/renderables/Box.test.ts +474 -0
  169. package/src/renderables/Box.ts +353 -0
  170. package/src/renderables/Code.test.ts +2388 -0
  171. package/src/renderables/Code.ts +555 -0
  172. package/src/renderables/Diff.regression.test.ts +381 -0
  173. package/src/renderables/Diff.test.ts +3212 -0
  174. package/src/renderables/Diff.ts +1278 -0
  175. package/src/renderables/EditBufferRenderable.test.ts +288 -0
  176. package/src/renderables/EditBufferRenderable.ts +1152 -0
  177. package/src/renderables/FrameBuffer.ts +47 -0
  178. package/src/renderables/Input.test.ts +1310 -0
  179. package/src/renderables/Input.ts +273 -0
  180. package/src/renderables/LineNumberRenderable.ts +725 -0
  181. package/src/renderables/Markdown.ts +2144 -0
  182. package/src/renderables/ScrollBar.ts +423 -0
  183. package/src/renderables/ScrollBox.ts +903 -0
  184. package/src/renderables/Select.test.ts +1134 -0
  185. package/src/renderables/Select.ts +535 -0
  186. package/src/renderables/Slider.test.ts +456 -0
  187. package/src/renderables/Slider.ts +342 -0
  188. package/src/renderables/TabSelect.test.ts +238 -0
  189. package/src/renderables/TabSelect.ts +447 -0
  190. package/src/renderables/Text.selection-buffer.test.ts +118 -0
  191. package/src/renderables/Text.test.ts +2662 -0
  192. package/src/renderables/Text.ts +147 -0
  193. package/src/renderables/TextBufferRenderable.ts +504 -0
  194. package/src/renderables/TextNode.test.ts +1137 -0
  195. package/src/renderables/TextNode.ts +379 -0
  196. package/src/renderables/TextTable.test.ts +1411 -0
  197. package/src/renderables/TextTable.ts +1434 -0
  198. package/src/renderables/Textarea.ts +425 -0
  199. package/src/renderables/TimeToFirstDraw.ts +89 -0
  200. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  201. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  202. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  203. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  204. package/src/renderables/__tests__/Code.test.ts +55 -0
  205. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  206. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +827 -0
  207. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1906 -0
  208. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  209. package/src/renderables/__tests__/Markdown.code-colors.test.ts +288 -0
  210. package/src/renderables/__tests__/Markdown.test.ts +4175 -0
  211. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  212. package/src/renderables/__tests__/Textarea.buffer.test.ts +683 -0
  213. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  214. package/src/renderables/__tests__/Textarea.editing.test.ts +2120 -0
  215. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  216. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  217. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  218. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3275 -0
  219. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  220. package/src/renderables/__tests__/Textarea.rendering.test.ts +1927 -0
  221. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  222. package/src/renderables/__tests__/Textarea.selection.test.ts +1589 -0
  223. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  224. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  225. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  226. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  227. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  228. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  229. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  230. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  231. package/src/renderables/__tests__/markdown-parser.test.ts +241 -0
  232. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  233. package/src/renderables/composition/README.md +8 -0
  234. package/src/renderables/composition/VRenderable.ts +32 -0
  235. package/src/renderables/composition/constructs.ts +127 -0
  236. package/src/renderables/composition/vnode.ts +277 -0
  237. package/src/renderables/index.ts +23 -0
  238. package/src/renderables/markdown-parser.ts +79 -0
  239. package/src/renderer-theme-mode.ts +199 -0
  240. package/src/renderer.ts +4975 -0
  241. package/src/runtime-plugin-support-configure.ts +63 -0
  242. package/src/runtime-plugin-support.ts +13 -0
  243. package/src/runtime-plugin.ts +626 -0
  244. package/src/specs/terminal-startup.md +64 -0
  245. package/src/syntax-style.test.ts +841 -0
  246. package/src/syntax-style.ts +274 -0
  247. package/src/testing/README.md +219 -0
  248. package/src/testing/bun-test-node.ts +880 -0
  249. package/src/testing/capture-spans.test.ts +216 -0
  250. package/src/testing/integration.test.ts +276 -0
  251. package/src/testing/manual-clock.ts +117 -0
  252. package/src/testing/mock-keys.test.ts +1378 -0
  253. package/src/testing/mock-keys.ts +457 -0
  254. package/src/testing/mock-mouse.test.ts +218 -0
  255. package/src/testing/mock-mouse.ts +247 -0
  256. package/src/testing/mock-tree-sitter-client.ts +81 -0
  257. package/src/testing/spy.ts +13 -0
  258. package/src/testing/terminal-capabilities.ts +47 -0
  259. package/src/testing/test-recorder.test.ts +410 -0
  260. package/src/testing/test-recorder.ts +133 -0
  261. package/src/testing/test-renderer.ts +375 -0
  262. package/src/testing/test-renderer.wait.test.ts +278 -0
  263. package/src/testing/test-streams.ts +31 -0
  264. package/src/testing.ts +9 -0
  265. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  266. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  267. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  268. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  269. package/src/tests/allocator-stats.test.ts +53 -0
  270. package/src/tests/audio.test.ts +303 -0
  271. package/src/tests/destroy-during-render.test.ts +200 -0
  272. package/src/tests/destroy-on-exit.fixture.ts +36 -0
  273. package/src/tests/destroy-on-exit.test.ts +62 -0
  274. package/src/tests/ffi-borrowed-pointer-callsites.test.ts +153 -0
  275. package/src/tests/hover-cursor.test.ts +98 -0
  276. package/src/tests/native-backed-measurement-lifecycle.test.ts +133 -0
  277. package/src/tests/native-backed-measurement-parity.test.ts +322 -0
  278. package/src/tests/native-span-feed-async.test.ts +173 -0
  279. package/src/tests/native-span-feed-close.test.ts +120 -0
  280. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  281. package/src/tests/native-span-feed-edge-cases.test.ts +384 -0
  282. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  283. package/src/tests/opacity.test.ts +123 -0
  284. package/src/tests/renderable.snapshot.test.ts +524 -0
  285. package/src/tests/renderable.test.ts +1851 -0
  286. package/src/tests/renderer.clock.test.ts +270 -0
  287. package/src/tests/renderer.console-startup.test.ts +2151 -0
  288. package/src/tests/renderer.control.test.ts +458 -0
  289. package/src/tests/renderer.core-slot-binding.test.ts +962 -0
  290. package/src/tests/renderer.cursor.test.ts +26 -0
  291. package/src/tests/renderer.custom-stdout.test.ts +1112 -0
  292. package/src/tests/renderer.destroy-during-render.test.ts +147 -0
  293. package/src/tests/renderer.focus-restore.test.ts +257 -0
  294. package/src/tests/renderer.focus.test.ts +329 -0
  295. package/src/tests/renderer.idle.test.ts +219 -0
  296. package/src/tests/renderer.input.test.ts +2615 -0
  297. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  298. package/src/tests/renderer.lifecycle.test.ts +34 -0
  299. package/src/tests/renderer.mouse.test.ts +1315 -0
  300. package/src/tests/renderer.notifications.test.ts +27 -0
  301. package/src/tests/renderer.palette.test.ts +1199 -0
  302. package/src/tests/renderer.remote.test.ts +247 -0
  303. package/src/tests/renderer.render-stats.test.ts +146 -0
  304. package/src/tests/renderer.scrollback-surface.test.ts +474 -0
  305. package/src/tests/renderer.selection.test.ts +138 -0
  306. package/src/tests/renderer.slot-registry.test.ts +684 -0
  307. package/src/tests/renderer.tracker.test.ts +202 -0
  308. package/src/tests/renderer.useMouse.test.ts +83 -0
  309. package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
  310. package/src/tests/runtime-plugin-node-modules-import-like-string.fixture.ts +48 -0
  311. package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
  312. package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
  313. package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
  314. package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
  315. package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
  316. package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
  317. package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
  318. package/src/tests/runtime-plugin-support-configure.fixture.ts +31 -0
  319. package/src/tests/runtime-plugin-support-late-addition.fixture.ts +17 -0
  320. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  321. package/src/tests/runtime-plugin-support.test.ts +54 -0
  322. package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
  323. package/src/tests/runtime-plugin.fixture.ts +40 -0
  324. package/src/tests/runtime-plugin.test.ts +369 -0
  325. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  326. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  327. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  328. package/src/tests/scrollbox.test.ts +1895 -0
  329. package/src/tests/wrap-resize-perf.test.ts +276 -0
  330. package/src/tests/yoga-api-coverage.test.ts +409 -0
  331. package/src/tests/yoga-callback-stress.test.ts +122 -0
  332. package/src/tests/yoga-ffi.test.ts +117 -0
  333. package/src/tests/yoga-setters.test.ts +921 -0
  334. package/src/tests/yoga-upstream/YGAlignBaselineTest.test.ts +124 -0
  335. package/src/tests/yoga-upstream/YGComputedBorderTest.test.ts +27 -0
  336. package/src/tests/yoga-upstream/YGComputedMarginTest.test.ts +27 -0
  337. package/src/tests/yoga-upstream/YGComputedPaddingTest.test.ts +27 -0
  338. package/src/tests/yoga-upstream/YGDirtiedTest.test.ts +157 -0
  339. package/src/tests/yoga-upstream/YGErrataTest.test.ts +40 -0
  340. package/src/tests/yoga-upstream/YGFlexBasisAuto.test.ts +23 -0
  341. package/src/tests/yoga-upstream/YGHasNewLayout.test.ts +81 -0
  342. package/src/tests/yoga-upstream/YGMeasureCacheTest.test.ts +31 -0
  343. package/src/tests/yoga-upstream/YGMeasureTest.test.ts +70 -0
  344. package/src/tests/yoga-upstream/generated/YGAbsolutePositionTest.test.ts +1864 -0
  345. package/src/tests/yoga-upstream/generated/YGAlignContentTest.test.ts +5829 -0
  346. package/src/tests/yoga-upstream/generated/YGAlignItemsTest.test.ts +2444 -0
  347. package/src/tests/yoga-upstream/generated/YGAlignSelfTest.test.ts +293 -0
  348. package/src/tests/yoga-upstream/generated/YGAndroidNewsFeed.test.ts +315 -0
  349. package/src/tests/yoga-upstream/generated/YGAspectRatioTest.test.ts +231 -0
  350. package/src/tests/yoga-upstream/generated/YGAutoTest.test.ts +347 -0
  351. package/src/tests/yoga-upstream/generated/YGBorderTest.test.ts +256 -0
  352. package/src/tests/yoga-upstream/generated/YGBoxSizingTest.test.ts +2747 -0
  353. package/src/tests/yoga-upstream/generated/YGDimensionTest.test.ts +129 -0
  354. package/src/tests/yoga-upstream/generated/YGDisplayContentsTest.test.ts +109 -0
  355. package/src/tests/yoga-upstream/generated/YGDisplayTest.test.ts +1097 -0
  356. package/src/tests/yoga-upstream/generated/YGFlexDirectionTest.test.ts +4562 -0
  357. package/src/tests/yoga-upstream/generated/YGFlexTest.test.ts +677 -0
  358. package/src/tests/yoga-upstream/generated/YGFlexWrapTest.test.ts +2071 -0
  359. package/src/tests/yoga-upstream/generated/YGGapTest.test.ts +3303 -0
  360. package/src/tests/yoga-upstream/generated/YGIntrinsicSizeTest.test.ts +582 -0
  361. package/src/tests/yoga-upstream/generated/YGJustifyContentTest.test.ts +2150 -0
  362. package/src/tests/yoga-upstream/generated/YGMarginTest.test.ts +1963 -0
  363. package/src/tests/yoga-upstream/generated/YGMinMaxDimensionTest.test.ts +1446 -0
  364. package/src/tests/yoga-upstream/generated/YGPaddingTest.test.ts +354 -0
  365. package/src/tests/yoga-upstream/generated/YGPercentageTest.test.ts +1760 -0
  366. package/src/tests/yoga-upstream/generated/YGRoundingTest.test.ts +1161 -0
  367. package/src/tests/yoga-upstream/generated/YGSizeOverflowTest.test.ts +207 -0
  368. package/src/tests/yoga-upstream/generated/YGStaticPositionTest.test.ts +6338 -0
  369. package/src/tests/yoga-upstream/tools/MeasureCounter.ts +54 -0
  370. package/src/tests/yoga-upstream/tools/utils.ts +81 -0
  371. package/src/text-buffer-view.test.ts +722 -0
  372. package/src/text-buffer-view.ts +193 -0
  373. package/src/text-buffer.test.ts +512 -0
  374. package/src/text-buffer.ts +250 -0
  375. package/src/types.ts +199 -0
  376. package/src/utils.ts +88 -0
  377. package/src/yoga.ts +1146 -0
  378. package/src/zig/ansi.zig +502 -0
  379. package/src/zig/audio.zig +1206 -0
  380. package/src/zig/bench/README.md +50 -0
  381. package/src/zig/bench/buffer-color-blending_bench.zig +350 -0
  382. package/src/zig/bench/buffer-draw-box_bench.zig +786 -0
  383. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +894 -0
  384. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  385. package/src/zig/bench/editor-view_bench.zig +169 -0
  386. package/src/zig/bench/native-span-feed_bench.zig +107 -0
  387. package/src/zig/bench/rope-markers_bench.zig +713 -0
  388. package/src/zig/bench/rope_bench.zig +514 -0
  389. package/src/zig/bench/styled-text_bench.zig +476 -0
  390. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  391. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  392. package/src/zig/bench/text-chunk-graphemes_bench.zig +272 -0
  393. package/src/zig/bench/utf8_bench.zig +799 -0
  394. package/src/zig/bench-utils.zig +431 -0
  395. package/src/zig/bench.zig +223 -0
  396. package/src/zig/buffer-methods.zig +215 -0
  397. package/src/zig/buffer.zig +2515 -0
  398. package/src/zig/build.zig +700 -0
  399. package/src/zig/build.zig.zon +19 -0
  400. package/src/zig/edit-buffer.zig +900 -0
  401. package/src/zig/editor-view.zig +812 -0
  402. package/src/zig/event-bus.zig +28 -0
  403. package/src/zig/event-emitter.zig +65 -0
  404. package/src/zig/file-logger.zig +92 -0
  405. package/src/zig/grapheme.zig +838 -0
  406. package/src/zig/handles.zig +267 -0
  407. package/src/zig/lib.zig +2813 -0
  408. package/src/zig/link.zig +349 -0
  409. package/src/zig/logger.zig +43 -0
  410. package/src/zig/mem-registry.zig +126 -0
  411. package/src/zig/miniaudio_shim.c +21 -0
  412. package/src/zig/native-renderable.zig +112 -0
  413. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  414. package/src/zig/native-span-feed.zig +747 -0
  415. package/src/zig/renderer-output.zig +677 -0
  416. package/src/zig/renderer.zig +2106 -0
  417. package/src/zig/rope.zig +1220 -0
  418. package/src/zig/split-scrollback.zig +88 -0
  419. package/src/zig/syntax-style.zig +174 -0
  420. package/src/zig/terminal.zig +1652 -0
  421. package/src/zig/test.zig +82 -0
  422. package/src/zig/tests/README.md +18 -0
  423. package/src/zig/tests/ansi_test.zig +18 -0
  424. package/src/zig/tests/audio_test.zig +439 -0
  425. package/src/zig/tests/buffer-methods_test.zig +1111 -0
  426. package/src/zig/tests/buffer_test.zig +2926 -0
  427. package/src/zig/tests/edit-buffer-history_test.zig +299 -0
  428. package/src/zig/tests/edit-buffer_test.zig +1688 -0
  429. package/src/zig/tests/editor-view_test.zig +3454 -0
  430. package/src/zig/tests/event-emitter_test.zig +249 -0
  431. package/src/zig/tests/grapheme_test.zig +1329 -0
  432. package/src/zig/tests/handles_test.zig +123 -0
  433. package/src/zig/tests/link_test.zig +220 -0
  434. package/src/zig/tests/mem-registry_test.zig +473 -0
  435. package/src/zig/tests/memory_leak_regression_test.zig +234 -0
  436. package/src/zig/tests/native-renderable_test.zig +16 -0
  437. package/src/zig/tests/native-span-feed_test.zig +1266 -0
  438. package/src/zig/tests/renderer_test.zig +2604 -0
  439. package/src/zig/tests/rope-nested_test.zig +712 -0
  440. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  441. package/src/zig/tests/rope_test.zig +2362 -0
  442. package/src/zig/tests/segment-merge.test.zig +148 -0
  443. package/src/zig/tests/split-scrollback_test.zig +70 -0
  444. package/src/zig/tests/syntax-style_test.zig +558 -0
  445. package/src/zig/tests/terminal_test.zig +1489 -0
  446. package/src/zig/tests/test-renderer.zig +126 -0
  447. package/src/zig/tests/text-buffer-drawing_test.zig +3291 -0
  448. package/src/zig/tests/text-buffer-highlights_test.zig +706 -0
  449. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  450. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  451. package/src/zig/tests/text-buffer-selection_test.zig +1056 -0
  452. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  453. package/src/zig/tests/text-buffer-view_test.zig +3672 -0
  454. package/src/zig/tests/text-buffer_test.zig +2191 -0
  455. package/src/zig/tests/unicode-width-map.zon +3909 -0
  456. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  457. package/src/zig/tests/utf8_test.zig +4060 -0
  458. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  459. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  460. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  461. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  462. package/src/zig/tests/yoga_test.zig +65 -0
  463. package/src/zig/text-buffer-iterators.zig +496 -0
  464. package/src/zig/text-buffer-segment.zig +403 -0
  465. package/src/zig/text-buffer-view.zig +1428 -0
  466. package/src/zig/text-buffer.zig +1272 -0
  467. package/src/zig/utf8.zig +1954 -0
  468. package/src/zig/utils.zig +12 -0
  469. package/src/zig/uucode-stub.zig +76 -0
  470. package/src/zig/vendor/miniaudio/miniaudio.h +93468 -0
  471. package/src/zig/yoga.zig +658 -0
  472. package/src/zig-structs.ts +381 -0
  473. package/src/zig.ts +5260 -0
  474. package/tsconfig.build.json +17 -0
  475. package/tsconfig.json +27 -0
  476. package/tsconfig.node-test.json +138 -0
@@ -0,0 +1,349 @@
1
+ const std = @import("std");
2
+
3
+ pub const LinkPoolError = error{
4
+ OutOfMemory,
5
+ InvalidId,
6
+ WrongGeneration,
7
+ UrlTooLong,
8
+ };
9
+
10
+ // ID layout within 24 bits: [ generation (8 bits) | slot_index (16 bits) ]
11
+ pub const GEN_BITS: u5 = 8;
12
+ pub const SLOT_BITS: u5 = 16;
13
+ pub const GEN_MASK: u32 = (@as(u32, 1) << GEN_BITS) - 1;
14
+ pub const SLOT_MASK: u32 = (@as(u32, 1) << SLOT_BITS) - 1;
15
+ pub const MAX_URL_LENGTH: usize = 512;
16
+ const RETIRED_GENERATION = GEN_MASK + 1;
17
+
18
+ pub const IdPayload = u32;
19
+
20
+ const SlotHeader = extern struct {
21
+ len: u32,
22
+ refcount: u32,
23
+ generation: u32,
24
+ };
25
+
26
+ /// Simple link pool for storing URL strings with reusable IDs
27
+ pub const LinkPool = struct {
28
+ allocator: std.mem.Allocator,
29
+ slot_capacity: u32,
30
+ slots_per_page: u32,
31
+ slot_size_bytes: usize,
32
+ slots: std.ArrayListUnmanaged(u8),
33
+ free_list: std.ArrayListUnmanaged(u32),
34
+ num_slots: u32,
35
+ retired_slot_count: u32,
36
+ interned_live_ids: std.StringHashMapUnmanaged(IdPayload),
37
+
38
+ pub fn init(allocator: std.mem.Allocator) LinkPool {
39
+ const slot_capacity = MAX_URL_LENGTH;
40
+ const slots_per_page = 64;
41
+ const slot_size_bytes = @sizeOf(SlotHeader) + slot_capacity;
42
+ return .{
43
+ .allocator = allocator,
44
+ .slot_capacity = slot_capacity,
45
+ .slots_per_page = slots_per_page,
46
+ .slot_size_bytes = slot_size_bytes,
47
+ .slots = .{},
48
+ .free_list = .{},
49
+ .num_slots = 0,
50
+ .retired_slot_count = 0,
51
+ .interned_live_ids = .{},
52
+ };
53
+ }
54
+
55
+ pub fn deinit(self: *LinkPool) void {
56
+ var key_it = self.interned_live_ids.keyIterator();
57
+ while (key_it.next()) |key_ptr| {
58
+ self.allocator.free(@constCast(key_ptr.*));
59
+ }
60
+ self.interned_live_ids.deinit(self.allocator);
61
+
62
+ self.slots.deinit(self.allocator);
63
+ self.free_list.deinit(self.allocator);
64
+ self.* = undefined;
65
+ }
66
+
67
+ fn grow(self: *LinkPool) LinkPoolError!void {
68
+ const slot_count_max = SLOT_MASK + 1;
69
+ if (self.num_slots > slot_count_max - self.slots_per_page) return LinkPoolError.OutOfMemory;
70
+
71
+ const add_bytes = self.slot_size_bytes * self.slots_per_page;
72
+
73
+ try self.slots.ensureTotalCapacity(self.allocator, self.slots.items.len + add_bytes);
74
+ try self.slots.appendNTimes(self.allocator, 0, add_bytes);
75
+
76
+ var i: u32 = 0;
77
+ while (i < self.slots_per_page) : (i += 1) {
78
+ try self.free_list.append(self.allocator, self.num_slots + i);
79
+ }
80
+ self.num_slots += self.slots_per_page;
81
+ }
82
+
83
+ fn slotPtr(self: *LinkPool, slot_index: u32) *u8 {
84
+ const offset: usize = @as(usize, slot_index) * self.slot_size_bytes;
85
+ return &self.slots.items[offset];
86
+ }
87
+
88
+ fn slotHeaderPtr(p: *u8) *align(1) SlotHeader {
89
+ return @ptrCast(p);
90
+ }
91
+
92
+ fn packId(slot_index: u32, generation: u32) LinkPoolError!IdPayload {
93
+ if (slot_index > SLOT_MASK) return LinkPoolError.OutOfMemory;
94
+ return ((generation & GEN_MASK) << SLOT_BITS) | (slot_index & SLOT_MASK);
95
+ }
96
+
97
+ fn unpackId(id: IdPayload) struct { slot_index: u32, generation: u32 } {
98
+ return .{
99
+ .slot_index = id & SLOT_MASK,
100
+ .generation = (id >> SLOT_BITS) & GEN_MASK,
101
+ };
102
+ }
103
+
104
+ fn removeInternedLiveId(self: *LinkPool, url: []const u8, expected_id: IdPayload) void {
105
+ const live_id = self.interned_live_ids.get(url) orelse return;
106
+ if (live_id != expected_id) return;
107
+ if (self.interned_live_ids.fetchRemove(url)) |removed| {
108
+ self.allocator.free(@constCast(removed.key));
109
+ }
110
+ }
111
+
112
+ fn lookupOrInvalidate(self: *LinkPool, url: []const u8) ?IdPayload {
113
+ const live_id = self.interned_live_ids.get(url) orelse return null;
114
+
115
+ const live_url = self.get(live_id) catch {
116
+ self.removeInternedLiveId(url, live_id);
117
+ return null;
118
+ };
119
+
120
+ if (!std.mem.eql(u8, live_url, url)) {
121
+ self.removeInternedLiveId(url, live_id);
122
+ return null;
123
+ }
124
+
125
+ const live_refcount = self.getRefcount(live_id) catch {
126
+ self.removeInternedLiveId(url, live_id);
127
+ return null;
128
+ };
129
+
130
+ if (live_refcount == 0) {
131
+ self.removeInternedLiveId(url, live_id);
132
+ return null;
133
+ }
134
+
135
+ return live_id;
136
+ }
137
+
138
+ fn internLiveId(self: *LinkPool, id: IdPayload, url: []const u8) LinkPoolError!void {
139
+ if (self.lookupOrInvalidate(url) != null) {
140
+ return;
141
+ }
142
+
143
+ const owned_key = self.allocator.dupe(u8, url) catch return LinkPoolError.OutOfMemory;
144
+ errdefer self.allocator.free(owned_key);
145
+
146
+ if (self.interned_live_ids.fetchPut(self.allocator, owned_key, id) catch return LinkPoolError.OutOfMemory) |replaced| {
147
+ self.allocator.free(@constCast(replaced.key));
148
+ }
149
+ }
150
+
151
+ pub fn alloc(self: *LinkPool, url: []const u8) LinkPoolError!IdPayload {
152
+ if (url.len > self.slot_capacity) {
153
+ return LinkPoolError.UrlTooLong;
154
+ }
155
+
156
+ if (self.lookupOrInvalidate(url)) |live_id| {
157
+ return live_id;
158
+ }
159
+
160
+ if (self.free_list.items.len == 0) try self.grow();
161
+
162
+ const slot_index = self.free_list.pop().?;
163
+ const p = self.slotPtr(slot_index);
164
+ const header_ptr = slotHeaderPtr(p);
165
+
166
+ std.debug.assert(header_ptr.generation < GEN_MASK);
167
+ const new_generation = header_ptr.generation + 1;
168
+
169
+ header_ptr.* = .{
170
+ .len = @intCast(url.len),
171
+ .refcount = 0,
172
+ .generation = new_generation,
173
+ };
174
+
175
+ const data_ptr = @as([*]u8, @ptrCast(p)) + @sizeOf(SlotHeader);
176
+ @memcpy(data_ptr[0..url.len], url);
177
+
178
+ return packId(slot_index, new_generation);
179
+ }
180
+
181
+ pub fn incref(self: *LinkPool, id: IdPayload) LinkPoolError!void {
182
+ const unpacked = unpackId(id);
183
+ if (unpacked.slot_index >= self.num_slots) return LinkPoolError.InvalidId;
184
+
185
+ const p = self.slotPtr(unpacked.slot_index);
186
+ const header_ptr = slotHeaderPtr(p);
187
+
188
+ if (header_ptr.generation != unpacked.generation) {
189
+ return LinkPoolError.WrongGeneration;
190
+ }
191
+
192
+ const old_refcount = header_ptr.refcount;
193
+ header_ptr.refcount +%= 1;
194
+
195
+ if (old_refcount == 0) {
196
+ const live_url = try self.get(id);
197
+ try self.internLiveId(id, live_url);
198
+ }
199
+ }
200
+
201
+ pub fn decref(self: *LinkPool, id: IdPayload) LinkPoolError!void {
202
+ const unpacked = unpackId(id);
203
+ if (unpacked.slot_index >= self.num_slots) return LinkPoolError.InvalidId;
204
+
205
+ const p = self.slotPtr(unpacked.slot_index);
206
+ const header_ptr = slotHeaderPtr(p);
207
+
208
+ if (header_ptr.refcount == 0) return LinkPoolError.InvalidId;
209
+ if (header_ptr.generation != unpacked.generation) return LinkPoolError.WrongGeneration;
210
+
211
+ if (header_ptr.refcount == 1) {
212
+ const live_url = try self.get(id);
213
+ self.removeInternedLiveId(live_url, id);
214
+ }
215
+
216
+ header_ptr.refcount -%= 1;
217
+
218
+ if (header_ptr.refcount == 0) {
219
+ if (header_ptr.generation == GEN_MASK) {
220
+ header_ptr.generation = RETIRED_GENERATION;
221
+ self.retired_slot_count += 1;
222
+ } else {
223
+ try self.free_list.append(self.allocator, unpacked.slot_index);
224
+ }
225
+ }
226
+ }
227
+
228
+ pub fn get(self: *LinkPool, id: IdPayload) LinkPoolError![]const u8 {
229
+ const unpacked = unpackId(id);
230
+ if (unpacked.slot_index >= self.num_slots) return LinkPoolError.InvalidId;
231
+
232
+ const p = self.slotPtr(unpacked.slot_index);
233
+ const header_ptr = slotHeaderPtr(p);
234
+
235
+ if (header_ptr.generation != unpacked.generation) return LinkPoolError.WrongGeneration;
236
+
237
+ const data_ptr = @as([*]u8, @ptrCast(p)) + @sizeOf(SlotHeader);
238
+ return data_ptr[0..header_ptr.len];
239
+ }
240
+
241
+ pub fn getRefcount(self: *LinkPool, id: IdPayload) LinkPoolError!u32 {
242
+ const unpacked = unpackId(id);
243
+ if (unpacked.slot_index >= self.num_slots) return LinkPoolError.InvalidId;
244
+
245
+ const p = self.slotPtr(unpacked.slot_index);
246
+ const header_ptr = slotHeaderPtr(p);
247
+
248
+ if (header_ptr.generation != unpacked.generation) return LinkPoolError.WrongGeneration;
249
+
250
+ return header_ptr.refcount;
251
+ }
252
+
253
+ pub fn getTotalSlots(self: *const LinkPool) u64 {
254
+ return self.num_slots;
255
+ }
256
+
257
+ pub fn getFreeSlotCount(self: *const LinkPool) u64 {
258
+ return self.free_list.items.len;
259
+ }
260
+
261
+ pub fn getLiveSlotCount(self: *const LinkPool) u64 {
262
+ return self.num_slots - @as(u32, @intCast(self.free_list.items.len)) - self.retired_slot_count;
263
+ }
264
+ };
265
+
266
+ /// Track link usage per buffer with per-cell refcounting
267
+ pub const LinkTracker = struct {
268
+ pool: *LinkPool,
269
+ used_ids: std.AutoHashMap(u32, u32), // id -> cell_count
270
+
271
+ pub fn init(allocator: std.mem.Allocator, pool: *LinkPool) LinkTracker {
272
+ return .{
273
+ .pool = pool,
274
+ .used_ids = std.AutoHashMap(u32, u32).init(allocator),
275
+ };
276
+ }
277
+
278
+ fn decRefAll(self: *LinkTracker) void {
279
+ var it = self.used_ids.iterator();
280
+ while (it.next()) |entry| {
281
+ const id = entry.key_ptr.*;
282
+ self.pool.decref(id) catch {};
283
+ }
284
+ }
285
+
286
+ pub fn deinit(self: *LinkTracker) void {
287
+ self.decRefAll();
288
+ self.used_ids.deinit();
289
+ self.* = undefined;
290
+ }
291
+
292
+ pub fn clear(self: *LinkTracker) void {
293
+ self.decRefAll();
294
+ self.used_ids.clearRetainingCapacity();
295
+ }
296
+
297
+ pub fn addCellRef(self: *LinkTracker, id: u32) void {
298
+ const res = self.used_ids.getOrPut(id) catch |err| {
299
+ std.debug.panic("LinkTracker.addCellRef getOrPut failed: {}\n", .{err});
300
+ };
301
+ if (!res.found_existing) {
302
+ // First time seeing this ID - try to incref in pool
303
+ self.pool.incref(id) catch {
304
+ // Invalid ID (not allocated in pool) - silently ignore
305
+ // This can happen with garbage in attribute bits
306
+ return;
307
+ };
308
+ res.value_ptr.* = 1;
309
+ } else {
310
+ res.value_ptr.* += 1;
311
+ }
312
+ }
313
+
314
+ pub fn removeCellRef(self: *LinkTracker, id: u32) void {
315
+ if (self.used_ids.getPtr(id)) |count_ptr| {
316
+ if (count_ptr.* > 0) {
317
+ count_ptr.* -= 1;
318
+ if (count_ptr.* == 0) {
319
+ _ = self.used_ids.remove(id);
320
+ self.pool.decref(id) catch {};
321
+ }
322
+ }
323
+ }
324
+ }
325
+
326
+ pub fn hasAny(self: *const LinkTracker) bool {
327
+ return self.used_ids.count() > 0;
328
+ }
329
+
330
+ pub fn getLinkCount(self: *const LinkTracker) u32 {
331
+ return @intCast(self.used_ids.count());
332
+ }
333
+ };
334
+
335
+ var GLOBAL_LINK_POOL: ?LinkPool = null;
336
+
337
+ pub fn initGlobalLinkPool(allocator: std.mem.Allocator) *LinkPool {
338
+ if (GLOBAL_LINK_POOL == null) {
339
+ GLOBAL_LINK_POOL = LinkPool.init(allocator);
340
+ }
341
+ return &GLOBAL_LINK_POOL.?;
342
+ }
343
+
344
+ pub fn deinitGlobalLinkPool() void {
345
+ if (GLOBAL_LINK_POOL) |*p| {
346
+ p.deinit();
347
+ GLOBAL_LINK_POOL = null;
348
+ }
349
+ }
@@ -0,0 +1,43 @@
1
+ const std = @import("std");
2
+
3
+ pub const LogLevel = enum(u8) {
4
+ err = 0,
5
+ warn = 1,
6
+ info = 2,
7
+ debug = 3,
8
+ };
9
+
10
+ var global_log_callback: ?*const fn (level: u8, msgPtr: [*]const u8, msgLen: u32) callconv(.c) void = null;
11
+
12
+ pub fn setLogCallback(callback: ?*const fn (level: u8, msgPtr: [*]const u8, msgLen: u32) callconv(.c) void) void {
13
+ global_log_callback = callback;
14
+ }
15
+
16
+ // Helper function to log messages - can be used directly throughout the codebase
17
+ pub fn logMessage(level: LogLevel, comptime format: []const u8, args: anytype) void {
18
+ if (global_log_callback) |callback| {
19
+ var buf: [4096]u8 = undefined;
20
+ const msg = std.fmt.bufPrint(&buf, format, args) catch {
21
+ const fallback = "Log formatting failed";
22
+ callback(@intFromEnum(LogLevel.err), fallback.ptr, std.math.cast(u32, fallback.len) orelse return);
23
+ return;
24
+ };
25
+ callback(@intFromEnum(level), msg.ptr, std.math.cast(u32, msg.len) orelse return);
26
+ }
27
+ }
28
+
29
+ pub fn err(comptime format: []const u8, args: anytype) void {
30
+ logMessage(.err, format, args);
31
+ }
32
+
33
+ pub fn warn(comptime format: []const u8, args: anytype) void {
34
+ logMessage(.warn, format, args);
35
+ }
36
+
37
+ pub fn info(comptime format: []const u8, args: anytype) void {
38
+ logMessage(.info, format, args);
39
+ }
40
+
41
+ pub fn debug(comptime format: []const u8, args: anytype) void {
42
+ logMessage(.debug, format, args);
43
+ }
@@ -0,0 +1,126 @@
1
+ const std = @import("std");
2
+ const Allocator = std.mem.Allocator;
3
+
4
+ pub const MemRegistryError = error{
5
+ OutOfMemory,
6
+ InvalidMemId,
7
+ };
8
+
9
+ /// Memory buffer reference in the registry
10
+ pub const MemBuffer = struct {
11
+ data: []const u8,
12
+ owned: bool,
13
+ active: bool, // Track if slot is in use
14
+ };
15
+
16
+ /// Registry for multiple memory buffers
17
+ pub const MemRegistry = struct {
18
+ buffers: std.ArrayListUnmanaged(MemBuffer),
19
+ free_slots: std.ArrayListUnmanaged(u8), // Track free slot indices
20
+ allocator: Allocator,
21
+
22
+ pub fn init(allocator: Allocator) MemRegistry {
23
+ return .{
24
+ .buffers = .{},
25
+ .free_slots = .{},
26
+ .allocator = allocator,
27
+ };
28
+ }
29
+
30
+ pub fn deinit(self: *MemRegistry) void {
31
+ for (self.buffers.items) |mem_buf| {
32
+ if (mem_buf.active and mem_buf.owned) {
33
+ self.allocator.free(mem_buf.data);
34
+ }
35
+ }
36
+ self.buffers.deinit(self.allocator);
37
+ self.free_slots.deinit(self.allocator);
38
+ self.* = undefined;
39
+ }
40
+
41
+ pub fn register(self: *MemRegistry, data: []const u8, owned: bool) MemRegistryError!u8 {
42
+ // Try to reuse a free slot first
43
+ if (self.free_slots.items.len > 0) {
44
+ const id = self.free_slots.items[self.free_slots.items.len - 1];
45
+ _ = self.free_slots.pop();
46
+ self.buffers.items[id] = MemBuffer{
47
+ .data = data,
48
+ .owned = owned,
49
+ .active = true,
50
+ };
51
+ return id;
52
+ }
53
+
54
+ // No free slots, allocate a new one
55
+ if (self.buffers.items.len >= 255) {
56
+ return MemRegistryError.OutOfMemory;
57
+ }
58
+ const id: u8 = @intCast(self.buffers.items.len);
59
+ try self.buffers.append(self.allocator, .{
60
+ .data = data,
61
+ .owned = owned,
62
+ .active = true,
63
+ });
64
+ return id;
65
+ }
66
+
67
+ pub fn get(self: *const MemRegistry, id: u8) ?[]const u8 {
68
+ if (id >= self.buffers.items.len) return null;
69
+ const buf = self.buffers.items[id];
70
+ if (!buf.active) return null;
71
+ return buf.data;
72
+ }
73
+
74
+ pub fn replace(self: *MemRegistry, id: u8, data: []const u8, owned: bool) MemRegistryError!void {
75
+ if (id >= self.buffers.items.len) return MemRegistryError.InvalidMemId;
76
+ const prev = self.buffers.items[id];
77
+ if (!prev.active) return MemRegistryError.InvalidMemId;
78
+ if (prev.owned) {
79
+ self.allocator.free(prev.data);
80
+ }
81
+ self.buffers.items[id] = .{ .data = data, .owned = owned, .active = true };
82
+ }
83
+
84
+ pub fn unregister(self: *MemRegistry, id: u8) MemRegistryError!void {
85
+ if (id >= self.buffers.items.len) return MemRegistryError.InvalidMemId;
86
+ var buf = &self.buffers.items[id];
87
+ if (!buf.active) return MemRegistryError.InvalidMemId;
88
+
89
+ // Free owned memory
90
+ if (buf.owned) {
91
+ self.allocator.free(buf.data);
92
+ }
93
+
94
+ // Mark slot as inactive
95
+ buf.active = false;
96
+ buf.data = &[_]u8{};
97
+ buf.owned = false;
98
+
99
+ // Add to free slots list
100
+ try self.free_slots.append(self.allocator, id);
101
+ }
102
+
103
+ pub fn clear(self: *MemRegistry) void {
104
+ for (self.buffers.items) |mem_buf| {
105
+ if (mem_buf.active and mem_buf.owned) {
106
+ self.allocator.free(mem_buf.data);
107
+ }
108
+ }
109
+ self.buffers.clearRetainingCapacity();
110
+ self.free_slots.clearRetainingCapacity();
111
+ }
112
+
113
+ pub fn getUsedSlots(self: *const MemRegistry) usize {
114
+ // Count only active slots
115
+ var count: usize = 0;
116
+ for (self.buffers.items) |buf| {
117
+ if (buf.active) count += 1;
118
+ }
119
+ return count;
120
+ }
121
+
122
+ pub fn getFreeSlots(self: *const MemRegistry) usize {
123
+ // Total capacity (255) minus buffers allocated plus explicitly freed slots
124
+ return 255 - self.buffers.items.len + self.free_slots.items.len;
125
+ }
126
+ };
@@ -0,0 +1,21 @@
1
+ #define MINIAUDIO_IMPLEMENTATION
2
+
3
+ #if defined(__linux__)
4
+ #define MA_ENABLE_ONLY_SPECIFIC_BACKENDS
5
+ #define MA_ENABLE_ALSA
6
+ #define MA_ENABLE_PULSEAUDIO
7
+ #endif
8
+
9
+ #if defined(__APPLE__)
10
+ #define MA_ENABLE_ONLY_SPECIFIC_BACKENDS
11
+ #define MA_ENABLE_COREAUDIO
12
+ #endif
13
+
14
+ #if defined(_WIN32)
15
+ #define MA_ENABLE_ONLY_SPECIFIC_BACKENDS
16
+ #define MA_ENABLE_WASAPI
17
+ #define MA_ENABLE_DSOUND
18
+ #define MA_ENABLE_WINMM
19
+ #endif
20
+
21
+ #include "vendor/miniaudio/miniaudio.h"
@@ -0,0 +1,112 @@
1
+ const std = @import("std");
2
+
3
+ const editor_view = @import("editor-view.zig");
4
+ const native_yoga = @import("yoga.zig");
5
+ const text_buffer_view = @import("text-buffer-view.zig");
6
+
7
+ pub const MeasureTargetKind = enum(u32) {
8
+ none = 0,
9
+ text_buffer_view = 1,
10
+ editor_view = 2,
11
+ };
12
+
13
+ // Generic measure targets keep Yoga independent of concrete renderable types.
14
+ // Add target kinds here instead of adding type-specific Yoga APIs.
15
+ pub const MeasureTarget = union(MeasureTargetKind) {
16
+ none,
17
+ text_buffer_view: *text_buffer_view.UnifiedTextBufferView,
18
+ editor_view: *editor_view.EditorView,
19
+ };
20
+
21
+ pub const NativeRenderable = struct {
22
+ // Borrowed during the migration to native-backed renderables. Today JS owns
23
+ // the Renderable tree and Yoga nodes; this native object only routes hot
24
+ // measurement without crossing back into JS. Long term, NativeRenderable
25
+ // should back every Renderable and own the Yoga node directly.
26
+ yoga_node: native_yoga.YGNodeRef = null,
27
+ measure_target: MeasureTarget = .none,
28
+
29
+ pub fn deinit(self: *NativeRenderable) void {
30
+ self.clearMeasureTarget();
31
+ self.yoga_node = null;
32
+ self.* = undefined;
33
+ }
34
+
35
+ pub fn attachYogaNode(self: *NativeRenderable, node: native_yoga.YGNodeRef) void {
36
+ if (self.yoga_node != null and self.yoga_node != node) {
37
+ native_yoga.yogaNodeSetNativeMeasureFunc(self.yoga_node, null, null);
38
+ }
39
+ self.yoga_node = node;
40
+ self.applyMeasureTarget();
41
+ }
42
+
43
+ pub fn setMeasureTarget(self: *NativeRenderable, target: MeasureTarget) void {
44
+ self.measure_target = target;
45
+ self.applyMeasureTarget();
46
+ }
47
+
48
+ pub fn clearMeasureTarget(self: *NativeRenderable) void {
49
+ if (self.yoga_node != null) {
50
+ native_yoga.yogaNodeSetNativeMeasureFunc(self.yoga_node, null, null);
51
+ }
52
+ self.measure_target = .none;
53
+ }
54
+
55
+ fn applyMeasureTarget(self: *NativeRenderable) void {
56
+ if (self.yoga_node == null) return;
57
+ switch (self.measure_target) {
58
+ .none => native_yoga.yogaNodeSetNativeMeasureFunc(self.yoga_node, null, null),
59
+ else => native_yoga.yogaNodeSetNativeMeasureFunc(self.yoga_node, self, &NativeRenderable.measure),
60
+ }
61
+ }
62
+
63
+ fn measure(target: ?*anyopaque, width: f32, width_mode: u32, height: f32, height_mode: u32) callconv(.c) native_yoga.ExternalYogaSize {
64
+ _ = height_mode;
65
+ const self: *NativeRenderable = @ptrCast(@alignCast(target orelse return .{ .width = std.math.nan(f32), .height = std.math.nan(f32) }));
66
+ const effective_width = normalizeYogaMeasureWidthInput(width, width_mode);
67
+ const effective_height = normalizeYogaMeasureHeightInput(height);
68
+ const measure_width = floorToU32(effective_width);
69
+ const measure_height = floorToU32(effective_height);
70
+ const result = self.measureTarget(measure_width, measure_height) orelse return .{ .width = 1, .height = 1 };
71
+
72
+ var measured_width: f32 = @floatFromInt(@max(@as(u32, 1), result.width_cols_max));
73
+ var measured_height: f32 = @floatFromInt(@max(@as(u32, 1), result.line_count));
74
+
75
+ if (width_mode == @intFromEnum(native_yoga.YogaMeasureMode.at_most) and self.yoga_node != null and !isYogaNodeAbsolute(self.yoga_node)) {
76
+ measured_width = @min(effective_width, measured_width);
77
+ measured_height = @min(effective_height, measured_height);
78
+ }
79
+
80
+ return .{ .width = measured_width, .height = measured_height };
81
+ }
82
+
83
+ fn measureTarget(self: *NativeRenderable, width: u32, height: u32) ?text_buffer_view.MeasureResult {
84
+ return switch (self.measure_target) {
85
+ .none => null,
86
+ .text_buffer_view => |view| view.measureForDimensions(width, height) catch null,
87
+ .editor_view => |view| view.getTextBufferView().measureForDimensions(width, height) catch null,
88
+ };
89
+ }
90
+ };
91
+
92
+ pub fn normalizeYogaMeasureWidthInput(value: f32, width_mode: u32) f32 {
93
+ if (width_mode == @intFromEnum(native_yoga.YogaMeasureMode.undefined) or std.math.isNan(value)) return 0;
94
+ return value;
95
+ }
96
+
97
+ pub fn normalizeYogaMeasureHeightInput(value: f32) f32 {
98
+ if (std.math.isNan(value)) return 1;
99
+ return value;
100
+ }
101
+
102
+ fn floorToU32(value: f32) u32 {
103
+ if (!std.math.isFinite(value) or value <= 0) return 0;
104
+ const floored = @floor(value);
105
+ if (floored >= @as(f32, @floatFromInt(std.math.maxInt(u32)))) return std.math.maxInt(u32);
106
+ return @intFromFloat(floored);
107
+ }
108
+
109
+ fn isYogaNodeAbsolute(node: native_yoga.YGNodeRef) bool {
110
+ return native_yoga.yogaNodeStyleGetEnum(node, @intFromEnum(native_yoga.YogaEnumKind.position_type)) ==
111
+ @intFromEnum(native_yoga.YogaPositionType.absolute);
112
+ }
@@ -0,0 +1,7 @@
1
+ const lib = @import("lib.zig");
2
+ const bench = @import("bench/native-span-feed_bench.zig");
3
+
4
+ comptime {
5
+ _ = lib;
6
+ _ = bench;
7
+ }