@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.
- package/README.md +63 -0
- package/dev/keypress-debug-renderer.ts +148 -0
- package/dev/keypress-debug.ts +43 -0
- package/dev/print-env-vars.ts +32 -0
- package/dev/test-tmux-graphics-334.sh +68 -0
- package/dev/test-tmux-theme-queries.sh +151 -0
- package/dev/thai-debug-test.ts +68 -0
- package/dev/theme-mode.ts +290 -0
- package/docs/development.md +144 -0
- package/package.json +102 -0
- package/prebuilt/aarch64-android/libopentui.so +0 -0
- package/scripts/build-android.ts +226 -0
- package/scripts/build-native-termux.sh +525 -0
- package/scripts/build.ts +530 -0
- package/scripts/dist-test.ts +312 -0
- package/scripts/package-prebuilt.ts +110 -0
- package/scripts/publish.ts +60 -0
- package/scripts/test-node-hook.mjs +16 -0
- package/scripts/test-node.ts +241 -0
- package/scripts/vendor-deps.sh +73 -0
- package/src/NativeSpanFeed.ts +375 -0
- package/src/Renderable.ts +1878 -0
- package/src/__snapshots__/buffer.test.ts.snap +28 -0
- package/src/animation/Timeline.test.ts +2709 -0
- package/src/animation/Timeline.ts +598 -0
- package/src/ansi.ts +22 -0
- package/src/audio.ts +479 -0
- package/src/benchmark/attenuation-benchmark.ts +81 -0
- package/src/benchmark/audio-playback-benchmark.ts +344 -0
- package/src/benchmark/box-draw-benchmark.ts +1042 -0
- package/src/benchmark/colormatrix-benchmark.ts +123 -0
- package/src/benchmark/gain-benchmark.ts +80 -0
- package/src/benchmark/latest-all-bench-run.json +707 -0
- package/src/benchmark/latest-async-bench-run.json +336 -0
- package/src/benchmark/latest-default-bench-run.json +657 -0
- package/src/benchmark/latest-large-bench-run.json +707 -0
- package/src/benchmark/latest-quick-bench-run.json +207 -0
- package/src/benchmark/layout-benchmark.ts +2547 -0
- package/src/benchmark/markdown-benchmark.ts +1796 -0
- package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
- package/src/benchmark/native-span-feed-benchmark.md +56 -0
- package/src/benchmark/native-span-feed-benchmark.ts +596 -0
- package/src/benchmark/native-span-feed-compare.ts +280 -0
- package/src/benchmark/render-traversal-benchmark.ts +928 -0
- package/src/benchmark/text-buffer-render-benchmark.ts +874 -0
- package/src/benchmark/text-table-benchmark.ts +948 -0
- package/src/buffer.test.ts +292 -0
- package/src/buffer.ts +564 -0
- package/src/console.test.ts +629 -0
- package/src/console.ts +1253 -0
- package/src/edit-buffer.test.ts +1852 -0
- package/src/edit-buffer.ts +417 -0
- package/src/editor-view.test.ts +1056 -0
- package/src/editor-view.ts +290 -0
- package/src/index.ts +25 -0
- package/src/lib/KeyHandler.integration.test.ts +292 -0
- package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
- package/src/lib/KeyHandler.test.ts +662 -0
- package/src/lib/KeyHandler.ts +222 -0
- package/src/lib/RGBA.test.ts +60 -0
- package/src/lib/RGBA.ts +343 -0
- package/src/lib/ascii.font.ts +330 -0
- package/src/lib/border.test.ts +83 -0
- package/src/lib/border.ts +170 -0
- package/src/lib/bunfs.test.ts +27 -0
- package/src/lib/bunfs.ts +18 -0
- package/src/lib/clipboard.test.ts +63 -0
- package/src/lib/clipboard.ts +41 -0
- package/src/lib/clock.ts +35 -0
- package/src/lib/data-paths.test.ts +133 -0
- package/src/lib/data-paths.ts +109 -0
- package/src/lib/debounce.ts +106 -0
- package/src/lib/detect-links.test.ts +98 -0
- package/src/lib/detect-links.ts +56 -0
- package/src/lib/env.test.ts +228 -0
- package/src/lib/env.ts +209 -0
- package/src/lib/extmarks-history.ts +51 -0
- package/src/lib/extmarks-multiwidth.test.ts +324 -0
- package/src/lib/extmarks.test.ts +3547 -0
- package/src/lib/extmarks.ts +861 -0
- package/src/lib/fonts/block.json +405 -0
- package/src/lib/fonts/grid.json +265 -0
- package/src/lib/fonts/huge.json +741 -0
- package/src/lib/fonts/pallet.json +314 -0
- package/src/lib/fonts/shade.json +591 -0
- package/src/lib/fonts/slick.json +321 -0
- package/src/lib/fonts/tiny.json +69 -0
- package/src/lib/hast-styled-text.ts +59 -0
- package/src/lib/index.ts +22 -0
- package/src/lib/keybinding.internal.test.ts +342 -0
- package/src/lib/keybinding.internal.ts +182 -0
- package/src/lib/objects-in-viewport.test.ts +789 -0
- package/src/lib/objects-in-viewport.ts +153 -0
- package/src/lib/output.capture.ts +58 -0
- package/src/lib/parse.keypress-kitty.protocol.test.ts +347 -0
- package/src/lib/parse.keypress-kitty.test.ts +712 -0
- package/src/lib/parse.keypress-kitty.ts +470 -0
- package/src/lib/parse.keypress.test.ts +2020 -0
- package/src/lib/parse.keypress.ts +480 -0
- package/src/lib/parse.mouse.test.ts +552 -0
- package/src/lib/parse.mouse.ts +232 -0
- package/src/lib/paste.ts +18 -0
- package/src/lib/queue.ts +65 -0
- package/src/lib/render-geometry.ts +36 -0
- package/src/lib/renderable.validations.test.ts +87 -0
- package/src/lib/renderable.validations.ts +83 -0
- package/src/lib/scroll-acceleration.ts +98 -0
- package/src/lib/selection.ts +261 -0
- package/src/lib/singleton.ts +34 -0
- package/src/lib/stdin-parser.test.ts +2439 -0
- package/src/lib/stdin-parser.ts +2007 -0
- package/src/lib/styled-text.ts +178 -0
- package/src/lib/terminal-capability-detection.test.ts +226 -0
- package/src/lib/terminal-capability-detection.ts +98 -0
- package/src/lib/terminal-palette.test.ts +954 -0
- package/src/lib/terminal-palette.ts +441 -0
- package/src/lib/tree-sitter/assets/README.md +119 -0
- package/src/lib/tree-sitter/assets/javascript/highlights.scm +205 -0
- package/src/lib/tree-sitter/assets/javascript/tree-sitter-javascript.wasm +0 -0
- package/src/lib/tree-sitter/assets/markdown/highlights.scm +150 -0
- package/src/lib/tree-sitter/assets/markdown/injections.scm +27 -0
- package/src/lib/tree-sitter/assets/markdown/tree-sitter-markdown.wasm +0 -0
- package/src/lib/tree-sitter/assets/markdown_inline/highlights.scm +115 -0
- package/src/lib/tree-sitter/assets/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
- package/src/lib/tree-sitter/assets/typescript/highlights.scm +604 -0
- package/src/lib/tree-sitter/assets/typescript/tree-sitter-typescript.wasm +0 -0
- package/src/lib/tree-sitter/assets/update.ts +360 -0
- package/src/lib/tree-sitter/assets/zig/highlights.scm +284 -0
- package/src/lib/tree-sitter/assets/zig/tree-sitter-zig.wasm +0 -0
- package/src/lib/tree-sitter/assets.d.ts +9 -0
- package/src/lib/tree-sitter/cache.test.ts +291 -0
- package/src/lib/tree-sitter/client.test.ts +1434 -0
- package/src/lib/tree-sitter/client.ts +847 -0
- package/src/lib/tree-sitter/default-parsers.ts +133 -0
- package/src/lib/tree-sitter/download-utils.ts +148 -0
- package/src/lib/tree-sitter/index.ts +75 -0
- package/src/lib/tree-sitter/parser.worker.ts +1098 -0
- package/src/lib/tree-sitter/parsers-config.ts +81 -0
- package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
- package/src/lib/tree-sitter/resolve-ft.ts +189 -0
- package/src/lib/tree-sitter/types.ts +132 -0
- package/src/lib/tree-sitter/update-assets.ts +10 -0
- package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
- package/src/lib/tree-sitter-styled-text.ts +314 -0
- package/src/lib/validate-dir-name.ts +55 -0
- package/src/lib/yoga.options.test.ts +628 -0
- package/src/lib/yoga.options.ts +346 -0
- package/src/native-event-worker-repro.test.ts +48 -0
- package/src/native-event-worker-repro.worker.ts +9 -0
- package/src/native-handle.test.ts +221 -0
- package/src/platform/ffi.test.ts +516 -0
- package/src/platform/ffi.ts +653 -0
- package/src/platform/runtime.test.ts +52 -0
- package/src/platform/runtime.ts +121 -0
- package/src/platform/test.ts +45 -0
- package/src/platform/worker-handler-cleanup.fixture.ts +12 -0
- package/src/platform/worker-onmessage-startup.fixture.ts +10 -0
- package/src/platform/worker-startup.fixture.ts +9 -0
- package/src/platform/worker.node-test.ts +153 -0
- package/src/platform/worker.ts +425 -0
- package/src/plugins/core-slot.ts +579 -0
- package/src/plugins/registry.ts +402 -0
- package/src/plugins/types.ts +46 -0
- package/src/post/effects.ts +948 -0
- package/src/post/filters.ts +512 -0
- package/src/post/matrices.ts +288 -0
- package/src/renderables/ASCIIFont.ts +219 -0
- package/src/renderables/Box.test.ts +474 -0
- package/src/renderables/Box.ts +353 -0
- package/src/renderables/Code.test.ts +2388 -0
- package/src/renderables/Code.ts +555 -0
- package/src/renderables/Diff.regression.test.ts +381 -0
- package/src/renderables/Diff.test.ts +3212 -0
- package/src/renderables/Diff.ts +1278 -0
- package/src/renderables/EditBufferRenderable.test.ts +288 -0
- package/src/renderables/EditBufferRenderable.ts +1152 -0
- package/src/renderables/FrameBuffer.ts +47 -0
- package/src/renderables/Input.test.ts +1310 -0
- package/src/renderables/Input.ts +273 -0
- package/src/renderables/LineNumberRenderable.ts +725 -0
- package/src/renderables/Markdown.ts +2144 -0
- package/src/renderables/ScrollBar.ts +423 -0
- package/src/renderables/ScrollBox.ts +903 -0
- package/src/renderables/Select.test.ts +1134 -0
- package/src/renderables/Select.ts +535 -0
- package/src/renderables/Slider.test.ts +456 -0
- package/src/renderables/Slider.ts +342 -0
- package/src/renderables/TabSelect.test.ts +238 -0
- package/src/renderables/TabSelect.ts +447 -0
- package/src/renderables/Text.selection-buffer.test.ts +118 -0
- package/src/renderables/Text.test.ts +2662 -0
- package/src/renderables/Text.ts +147 -0
- package/src/renderables/TextBufferRenderable.ts +504 -0
- package/src/renderables/TextNode.test.ts +1137 -0
- package/src/renderables/TextNode.ts +379 -0
- package/src/renderables/TextTable.test.ts +1411 -0
- package/src/renderables/TextTable.ts +1434 -0
- package/src/renderables/Textarea.ts +425 -0
- package/src/renderables/TimeToFirstDraw.ts +89 -0
- package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
- package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
- package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
- package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
- package/src/renderables/__tests__/Code.test.ts +55 -0
- package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
- package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +827 -0
- package/src/renderables/__tests__/LineNumberRenderable.test.ts +1906 -0
- package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
- package/src/renderables/__tests__/Markdown.code-colors.test.ts +288 -0
- package/src/renderables/__tests__/Markdown.test.ts +4175 -0
- package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
- package/src/renderables/__tests__/Textarea.buffer.test.ts +683 -0
- package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
- package/src/renderables/__tests__/Textarea.editing.test.ts +2120 -0
- package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
- package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
- package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
- package/src/renderables/__tests__/Textarea.keybinding.test.ts +3275 -0
- package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
- package/src/renderables/__tests__/Textarea.rendering.test.ts +1927 -0
- package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
- package/src/renderables/__tests__/Textarea.selection.test.ts +1589 -0
- package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
- package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
- package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
- package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
- package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
- package/src/renderables/__tests__/markdown-parser.test.ts +241 -0
- package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
- package/src/renderables/composition/README.md +8 -0
- package/src/renderables/composition/VRenderable.ts +32 -0
- package/src/renderables/composition/constructs.ts +127 -0
- package/src/renderables/composition/vnode.ts +277 -0
- package/src/renderables/index.ts +23 -0
- package/src/renderables/markdown-parser.ts +79 -0
- package/src/renderer-theme-mode.ts +199 -0
- package/src/renderer.ts +4975 -0
- package/src/runtime-plugin-support-configure.ts +63 -0
- package/src/runtime-plugin-support.ts +13 -0
- package/src/runtime-plugin.ts +626 -0
- package/src/specs/terminal-startup.md +64 -0
- package/src/syntax-style.test.ts +841 -0
- package/src/syntax-style.ts +274 -0
- package/src/testing/README.md +219 -0
- package/src/testing/bun-test-node.ts +880 -0
- package/src/testing/capture-spans.test.ts +216 -0
- package/src/testing/integration.test.ts +276 -0
- package/src/testing/manual-clock.ts +117 -0
- package/src/testing/mock-keys.test.ts +1378 -0
- package/src/testing/mock-keys.ts +457 -0
- package/src/testing/mock-mouse.test.ts +218 -0
- package/src/testing/mock-mouse.ts +247 -0
- package/src/testing/mock-tree-sitter-client.ts +81 -0
- package/src/testing/spy.ts +13 -0
- package/src/testing/terminal-capabilities.ts +47 -0
- package/src/testing/test-recorder.test.ts +410 -0
- package/src/testing/test-recorder.ts +133 -0
- package/src/testing/test-renderer.ts +375 -0
- package/src/testing/test-renderer.wait.test.ts +278 -0
- package/src/testing/test-streams.ts +31 -0
- package/src/testing.ts +9 -0
- package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
- package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
- package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
- package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
- package/src/tests/allocator-stats.test.ts +53 -0
- package/src/tests/audio.test.ts +303 -0
- package/src/tests/destroy-during-render.test.ts +200 -0
- package/src/tests/destroy-on-exit.fixture.ts +36 -0
- package/src/tests/destroy-on-exit.test.ts +62 -0
- package/src/tests/ffi-borrowed-pointer-callsites.test.ts +153 -0
- package/src/tests/hover-cursor.test.ts +98 -0
- package/src/tests/native-backed-measurement-lifecycle.test.ts +133 -0
- package/src/tests/native-backed-measurement-parity.test.ts +322 -0
- package/src/tests/native-span-feed-async.test.ts +173 -0
- package/src/tests/native-span-feed-close.test.ts +120 -0
- package/src/tests/native-span-feed-coverage.test.ts +227 -0
- package/src/tests/native-span-feed-edge-cases.test.ts +384 -0
- package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
- package/src/tests/opacity.test.ts +123 -0
- package/src/tests/renderable.snapshot.test.ts +524 -0
- package/src/tests/renderable.test.ts +1851 -0
- package/src/tests/renderer.clock.test.ts +270 -0
- package/src/tests/renderer.console-startup.test.ts +2151 -0
- package/src/tests/renderer.control.test.ts +458 -0
- package/src/tests/renderer.core-slot-binding.test.ts +962 -0
- package/src/tests/renderer.cursor.test.ts +26 -0
- package/src/tests/renderer.custom-stdout.test.ts +1112 -0
- package/src/tests/renderer.destroy-during-render.test.ts +147 -0
- package/src/tests/renderer.focus-restore.test.ts +257 -0
- package/src/tests/renderer.focus.test.ts +329 -0
- package/src/tests/renderer.idle.test.ts +219 -0
- package/src/tests/renderer.input.test.ts +2615 -0
- package/src/tests/renderer.kitty-flags.test.ts +195 -0
- package/src/tests/renderer.lifecycle.test.ts +34 -0
- package/src/tests/renderer.mouse.test.ts +1315 -0
- package/src/tests/renderer.notifications.test.ts +27 -0
- package/src/tests/renderer.palette.test.ts +1199 -0
- package/src/tests/renderer.remote.test.ts +247 -0
- package/src/tests/renderer.render-stats.test.ts +146 -0
- package/src/tests/renderer.scrollback-surface.test.ts +474 -0
- package/src/tests/renderer.selection.test.ts +138 -0
- package/src/tests/renderer.slot-registry.test.ts +684 -0
- package/src/tests/renderer.tracker.test.ts +202 -0
- package/src/tests/renderer.useMouse.test.ts +83 -0
- package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
- package/src/tests/runtime-plugin-node-modules-import-like-string.fixture.ts +48 -0
- package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
- package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
- package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
- package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
- package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
- package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
- package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
- package/src/tests/runtime-plugin-support-configure.fixture.ts +31 -0
- package/src/tests/runtime-plugin-support-late-addition.fixture.ts +17 -0
- package/src/tests/runtime-plugin-support.fixture.ts +11 -0
- package/src/tests/runtime-plugin-support.test.ts +54 -0
- package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
- package/src/tests/runtime-plugin.fixture.ts +40 -0
- package/src/tests/runtime-plugin.test.ts +369 -0
- package/src/tests/scrollbox-culling-bug.test.ts +114 -0
- package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
- package/src/tests/scrollbox-hitgrid.test.ts +909 -0
- package/src/tests/scrollbox.test.ts +1895 -0
- package/src/tests/wrap-resize-perf.test.ts +276 -0
- package/src/tests/yoga-api-coverage.test.ts +409 -0
- package/src/tests/yoga-callback-stress.test.ts +122 -0
- package/src/tests/yoga-ffi.test.ts +117 -0
- package/src/tests/yoga-setters.test.ts +921 -0
- package/src/tests/yoga-upstream/YGAlignBaselineTest.test.ts +124 -0
- package/src/tests/yoga-upstream/YGComputedBorderTest.test.ts +27 -0
- package/src/tests/yoga-upstream/YGComputedMarginTest.test.ts +27 -0
- package/src/tests/yoga-upstream/YGComputedPaddingTest.test.ts +27 -0
- package/src/tests/yoga-upstream/YGDirtiedTest.test.ts +157 -0
- package/src/tests/yoga-upstream/YGErrataTest.test.ts +40 -0
- package/src/tests/yoga-upstream/YGFlexBasisAuto.test.ts +23 -0
- package/src/tests/yoga-upstream/YGHasNewLayout.test.ts +81 -0
- package/src/tests/yoga-upstream/YGMeasureCacheTest.test.ts +31 -0
- package/src/tests/yoga-upstream/YGMeasureTest.test.ts +70 -0
- package/src/tests/yoga-upstream/generated/YGAbsolutePositionTest.test.ts +1864 -0
- package/src/tests/yoga-upstream/generated/YGAlignContentTest.test.ts +5829 -0
- package/src/tests/yoga-upstream/generated/YGAlignItemsTest.test.ts +2444 -0
- package/src/tests/yoga-upstream/generated/YGAlignSelfTest.test.ts +293 -0
- package/src/tests/yoga-upstream/generated/YGAndroidNewsFeed.test.ts +315 -0
- package/src/tests/yoga-upstream/generated/YGAspectRatioTest.test.ts +231 -0
- package/src/tests/yoga-upstream/generated/YGAutoTest.test.ts +347 -0
- package/src/tests/yoga-upstream/generated/YGBorderTest.test.ts +256 -0
- package/src/tests/yoga-upstream/generated/YGBoxSizingTest.test.ts +2747 -0
- package/src/tests/yoga-upstream/generated/YGDimensionTest.test.ts +129 -0
- package/src/tests/yoga-upstream/generated/YGDisplayContentsTest.test.ts +109 -0
- package/src/tests/yoga-upstream/generated/YGDisplayTest.test.ts +1097 -0
- package/src/tests/yoga-upstream/generated/YGFlexDirectionTest.test.ts +4562 -0
- package/src/tests/yoga-upstream/generated/YGFlexTest.test.ts +677 -0
- package/src/tests/yoga-upstream/generated/YGFlexWrapTest.test.ts +2071 -0
- package/src/tests/yoga-upstream/generated/YGGapTest.test.ts +3303 -0
- package/src/tests/yoga-upstream/generated/YGIntrinsicSizeTest.test.ts +582 -0
- package/src/tests/yoga-upstream/generated/YGJustifyContentTest.test.ts +2150 -0
- package/src/tests/yoga-upstream/generated/YGMarginTest.test.ts +1963 -0
- package/src/tests/yoga-upstream/generated/YGMinMaxDimensionTest.test.ts +1446 -0
- package/src/tests/yoga-upstream/generated/YGPaddingTest.test.ts +354 -0
- package/src/tests/yoga-upstream/generated/YGPercentageTest.test.ts +1760 -0
- package/src/tests/yoga-upstream/generated/YGRoundingTest.test.ts +1161 -0
- package/src/tests/yoga-upstream/generated/YGSizeOverflowTest.test.ts +207 -0
- package/src/tests/yoga-upstream/generated/YGStaticPositionTest.test.ts +6338 -0
- package/src/tests/yoga-upstream/tools/MeasureCounter.ts +54 -0
- package/src/tests/yoga-upstream/tools/utils.ts +81 -0
- package/src/text-buffer-view.test.ts +722 -0
- package/src/text-buffer-view.ts +193 -0
- package/src/text-buffer.test.ts +512 -0
- package/src/text-buffer.ts +250 -0
- package/src/types.ts +199 -0
- package/src/utils.ts +88 -0
- package/src/yoga.ts +1146 -0
- package/src/zig/ansi.zig +502 -0
- package/src/zig/audio.zig +1206 -0
- package/src/zig/bench/README.md +50 -0
- package/src/zig/bench/buffer-color-blending_bench.zig +350 -0
- package/src/zig/bench/buffer-draw-box_bench.zig +786 -0
- package/src/zig/bench/buffer-draw-text-buffer_bench.zig +894 -0
- package/src/zig/bench/edit-buffer_bench.zig +476 -0
- package/src/zig/bench/editor-view_bench.zig +169 -0
- package/src/zig/bench/native-span-feed_bench.zig +107 -0
- package/src/zig/bench/rope-markers_bench.zig +713 -0
- package/src/zig/bench/rope_bench.zig +514 -0
- package/src/zig/bench/styled-text_bench.zig +476 -0
- package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
- package/src/zig/bench/text-buffer-view_bench.zig +459 -0
- package/src/zig/bench/text-chunk-graphemes_bench.zig +272 -0
- package/src/zig/bench/utf8_bench.zig +799 -0
- package/src/zig/bench-utils.zig +431 -0
- package/src/zig/bench.zig +223 -0
- package/src/zig/buffer-methods.zig +215 -0
- package/src/zig/buffer.zig +2515 -0
- package/src/zig/build.zig +700 -0
- package/src/zig/build.zig.zon +19 -0
- package/src/zig/edit-buffer.zig +900 -0
- package/src/zig/editor-view.zig +812 -0
- package/src/zig/event-bus.zig +28 -0
- package/src/zig/event-emitter.zig +65 -0
- package/src/zig/file-logger.zig +92 -0
- package/src/zig/grapheme.zig +838 -0
- package/src/zig/handles.zig +267 -0
- package/src/zig/lib.zig +2813 -0
- package/src/zig/link.zig +349 -0
- package/src/zig/logger.zig +43 -0
- package/src/zig/mem-registry.zig +126 -0
- package/src/zig/miniaudio_shim.c +21 -0
- package/src/zig/native-renderable.zig +112 -0
- package/src/zig/native-span-feed-bench-lib.zig +7 -0
- package/src/zig/native-span-feed.zig +747 -0
- package/src/zig/renderer-output.zig +677 -0
- package/src/zig/renderer.zig +2106 -0
- package/src/zig/rope.zig +1220 -0
- package/src/zig/split-scrollback.zig +88 -0
- package/src/zig/syntax-style.zig +174 -0
- package/src/zig/terminal.zig +1652 -0
- package/src/zig/test.zig +82 -0
- package/src/zig/tests/README.md +18 -0
- package/src/zig/tests/ansi_test.zig +18 -0
- package/src/zig/tests/audio_test.zig +439 -0
- package/src/zig/tests/buffer-methods_test.zig +1111 -0
- package/src/zig/tests/buffer_test.zig +2926 -0
- package/src/zig/tests/edit-buffer-history_test.zig +299 -0
- package/src/zig/tests/edit-buffer_test.zig +1688 -0
- package/src/zig/tests/editor-view_test.zig +3454 -0
- package/src/zig/tests/event-emitter_test.zig +249 -0
- package/src/zig/tests/grapheme_test.zig +1329 -0
- package/src/zig/tests/handles_test.zig +123 -0
- package/src/zig/tests/link_test.zig +220 -0
- package/src/zig/tests/mem-registry_test.zig +473 -0
- package/src/zig/tests/memory_leak_regression_test.zig +234 -0
- package/src/zig/tests/native-renderable_test.zig +16 -0
- package/src/zig/tests/native-span-feed_test.zig +1266 -0
- package/src/zig/tests/renderer_test.zig +2604 -0
- package/src/zig/tests/rope-nested_test.zig +712 -0
- package/src/zig/tests/rope_fuzz_test.zig +238 -0
- package/src/zig/tests/rope_test.zig +2362 -0
- package/src/zig/tests/segment-merge.test.zig +148 -0
- package/src/zig/tests/split-scrollback_test.zig +70 -0
- package/src/zig/tests/syntax-style_test.zig +558 -0
- package/src/zig/tests/terminal_test.zig +1489 -0
- package/src/zig/tests/test-renderer.zig +126 -0
- package/src/zig/tests/text-buffer-drawing_test.zig +3291 -0
- package/src/zig/tests/text-buffer-highlights_test.zig +706 -0
- package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
- package/src/zig/tests/text-buffer-segment_test.zig +320 -0
- package/src/zig/tests/text-buffer-selection_test.zig +1056 -0
- package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
- package/src/zig/tests/text-buffer-view_test.zig +3672 -0
- package/src/zig/tests/text-buffer_test.zig +2191 -0
- package/src/zig/tests/unicode-width-map.zon +3909 -0
- package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
- package/src/zig/tests/utf8_test.zig +4060 -0
- package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
- package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
- package/src/zig/tests/word-wrap-editing_test.zig +498 -0
- package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
- package/src/zig/tests/yoga_test.zig +65 -0
- package/src/zig/text-buffer-iterators.zig +496 -0
- package/src/zig/text-buffer-segment.zig +403 -0
- package/src/zig/text-buffer-view.zig +1428 -0
- package/src/zig/text-buffer.zig +1272 -0
- package/src/zig/utf8.zig +1954 -0
- package/src/zig/utils.zig +12 -0
- package/src/zig/uucode-stub.zig +76 -0
- package/src/zig/vendor/miniaudio/miniaudio.h +93468 -0
- package/src/zig/yoga.zig +658 -0
- package/src/zig-structs.ts +381 -0
- package/src/zig.ts +5260 -0
- package/tsconfig.build.json +17 -0
- package/tsconfig.json +27 -0
- package/tsconfig.node-test.json +138 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
const mem_registry = @import("../mem-registry.zig");
|
|
3
|
+
|
|
4
|
+
const MemRegistry = mem_registry.MemRegistry;
|
|
5
|
+
const MemRegistryError = mem_registry.MemRegistryError;
|
|
6
|
+
|
|
7
|
+
test "MemRegistry - init and deinit" {
|
|
8
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
9
|
+
defer registry.deinit();
|
|
10
|
+
|
|
11
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getUsedSlots());
|
|
12
|
+
try std.testing.expectEqual(@as(usize, 255), registry.getFreeSlots());
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
test "MemRegistry - register owned memory" {
|
|
16
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
17
|
+
defer registry.deinit();
|
|
18
|
+
|
|
19
|
+
const text = try std.testing.allocator.dupe(u8, "Hello, World!");
|
|
20
|
+
const id = try registry.register(text, true);
|
|
21
|
+
|
|
22
|
+
try std.testing.expectEqual(@as(u8, 0), id);
|
|
23
|
+
try std.testing.expectEqual(@as(usize, 1), registry.getUsedSlots());
|
|
24
|
+
try std.testing.expectEqual(@as(usize, 254), registry.getFreeSlots());
|
|
25
|
+
|
|
26
|
+
const retrieved = registry.get(id);
|
|
27
|
+
try std.testing.expect(retrieved != null);
|
|
28
|
+
try std.testing.expectEqualStrings("Hello, World!", retrieved.?);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
test "MemRegistry - register non-owned memory" {
|
|
32
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
33
|
+
defer registry.deinit();
|
|
34
|
+
|
|
35
|
+
const text = "Hello, World!";
|
|
36
|
+
const id = try registry.register(text, false);
|
|
37
|
+
|
|
38
|
+
try std.testing.expectEqual(@as(u8, 0), id);
|
|
39
|
+
try std.testing.expectEqual(@as(usize, 1), registry.getUsedSlots());
|
|
40
|
+
|
|
41
|
+
const retrieved = registry.get(id);
|
|
42
|
+
try std.testing.expect(retrieved != null);
|
|
43
|
+
try std.testing.expectEqualStrings("Hello, World!", retrieved.?);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
test "MemRegistry - register multiple buffers" {
|
|
47
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
48
|
+
defer registry.deinit();
|
|
49
|
+
|
|
50
|
+
const text1 = "First";
|
|
51
|
+
const text2 = "Second";
|
|
52
|
+
const text3 = "Third";
|
|
53
|
+
|
|
54
|
+
const id1 = try registry.register(text1, false);
|
|
55
|
+
const id2 = try registry.register(text2, false);
|
|
56
|
+
const id3 = try registry.register(text3, false);
|
|
57
|
+
|
|
58
|
+
try std.testing.expectEqual(@as(u8, 0), id1);
|
|
59
|
+
try std.testing.expectEqual(@as(u8, 1), id2);
|
|
60
|
+
try std.testing.expectEqual(@as(u8, 2), id3);
|
|
61
|
+
try std.testing.expectEqual(@as(usize, 3), registry.getUsedSlots());
|
|
62
|
+
try std.testing.expectEqual(@as(usize, 252), registry.getFreeSlots());
|
|
63
|
+
|
|
64
|
+
try std.testing.expectEqualStrings("First", registry.get(id1).?);
|
|
65
|
+
try std.testing.expectEqualStrings("Second", registry.get(id2).?);
|
|
66
|
+
try std.testing.expectEqualStrings("Third", registry.get(id3).?);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
test "MemRegistry - get invalid ID returns null" {
|
|
70
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
71
|
+
defer registry.deinit();
|
|
72
|
+
|
|
73
|
+
const text = "Test";
|
|
74
|
+
_ = try registry.register(text, false);
|
|
75
|
+
|
|
76
|
+
try std.testing.expect(registry.get(1) == null);
|
|
77
|
+
try std.testing.expect(registry.get(5) == null);
|
|
78
|
+
try std.testing.expect(registry.get(255) == null);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
test "MemRegistry - replace owned buffer" {
|
|
82
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
83
|
+
defer registry.deinit();
|
|
84
|
+
|
|
85
|
+
const text1 = try std.testing.allocator.dupe(u8, "Original");
|
|
86
|
+
const id = try registry.register(text1, true);
|
|
87
|
+
|
|
88
|
+
const text2 = try std.testing.allocator.dupe(u8, "Replaced");
|
|
89
|
+
try registry.replace(id, text2, true);
|
|
90
|
+
|
|
91
|
+
const retrieved = registry.get(id);
|
|
92
|
+
try std.testing.expect(retrieved != null);
|
|
93
|
+
try std.testing.expectEqualStrings("Replaced", retrieved.?);
|
|
94
|
+
try std.testing.expectEqual(@as(usize, 1), registry.getUsedSlots());
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
test "MemRegistry - replace non-owned buffer with owned" {
|
|
98
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
99
|
+
defer registry.deinit();
|
|
100
|
+
|
|
101
|
+
const text1 = "Original";
|
|
102
|
+
const id = try registry.register(text1, false);
|
|
103
|
+
|
|
104
|
+
const text2 = try std.testing.allocator.dupe(u8, "Replaced");
|
|
105
|
+
try registry.replace(id, text2, true);
|
|
106
|
+
|
|
107
|
+
const retrieved = registry.get(id);
|
|
108
|
+
try std.testing.expect(retrieved != null);
|
|
109
|
+
try std.testing.expectEqualStrings("Replaced", retrieved.?);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
test "MemRegistry - replace with invalid ID" {
|
|
113
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
114
|
+
defer registry.deinit();
|
|
115
|
+
|
|
116
|
+
const text = "Test";
|
|
117
|
+
const result = registry.replace(5, text, false);
|
|
118
|
+
try std.testing.expectError(MemRegistryError.InvalidMemId, result);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
test "MemRegistry - clear owned buffers" {
|
|
122
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
123
|
+
defer registry.deinit();
|
|
124
|
+
|
|
125
|
+
const text1 = try std.testing.allocator.dupe(u8, "First");
|
|
126
|
+
const text2 = try std.testing.allocator.dupe(u8, "Second");
|
|
127
|
+
_ = try registry.register(text1, true);
|
|
128
|
+
_ = try registry.register(text2, true);
|
|
129
|
+
|
|
130
|
+
try std.testing.expectEqual(@as(usize, 2), registry.getUsedSlots());
|
|
131
|
+
|
|
132
|
+
registry.clear();
|
|
133
|
+
|
|
134
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getUsedSlots());
|
|
135
|
+
try std.testing.expectEqual(@as(usize, 255), registry.getFreeSlots());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
test "MemRegistry - clear non-owned buffers" {
|
|
139
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
140
|
+
defer registry.deinit();
|
|
141
|
+
|
|
142
|
+
const text1 = "First";
|
|
143
|
+
const text2 = "Second";
|
|
144
|
+
_ = try registry.register(text1, false);
|
|
145
|
+
_ = try registry.register(text2, false);
|
|
146
|
+
|
|
147
|
+
try std.testing.expectEqual(@as(usize, 2), registry.getUsedSlots());
|
|
148
|
+
|
|
149
|
+
registry.clear();
|
|
150
|
+
|
|
151
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getUsedSlots());
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
test "MemRegistry - max capacity" {
|
|
155
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
156
|
+
defer registry.deinit();
|
|
157
|
+
|
|
158
|
+
var i: usize = 0;
|
|
159
|
+
while (i < 255) : (i += 1) {
|
|
160
|
+
const text = "test";
|
|
161
|
+
_ = try registry.register(text, false);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
try std.testing.expectEqual(@as(usize, 255), registry.getUsedSlots());
|
|
165
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getFreeSlots());
|
|
166
|
+
|
|
167
|
+
const text = "overflow";
|
|
168
|
+
const result = registry.register(text, false);
|
|
169
|
+
try std.testing.expectError(MemRegistryError.OutOfMemory, result);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
test "MemRegistry - clear and reuse" {
|
|
173
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
174
|
+
defer registry.deinit();
|
|
175
|
+
|
|
176
|
+
const text1 = "First";
|
|
177
|
+
const id1 = try registry.register(text1, false);
|
|
178
|
+
try std.testing.expectEqual(@as(u8, 0), id1);
|
|
179
|
+
|
|
180
|
+
registry.clear();
|
|
181
|
+
|
|
182
|
+
const text2 = "Second";
|
|
183
|
+
const id2 = try registry.register(text2, false);
|
|
184
|
+
try std.testing.expectEqual(@as(u8, 0), id2);
|
|
185
|
+
try std.testing.expectEqualStrings("Second", registry.get(id2).?);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
test "MemRegistry - mixed owned and non-owned buffers" {
|
|
189
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
190
|
+
defer registry.deinit();
|
|
191
|
+
|
|
192
|
+
const owned = try std.testing.allocator.dupe(u8, "Owned");
|
|
193
|
+
const non_owned = "Not Owned";
|
|
194
|
+
|
|
195
|
+
const id1 = try registry.register(owned, true);
|
|
196
|
+
const id2 = try registry.register(non_owned, false);
|
|
197
|
+
|
|
198
|
+
try std.testing.expectEqual(@as(usize, 2), registry.getUsedSlots());
|
|
199
|
+
|
|
200
|
+
try std.testing.expectEqualStrings("Owned", registry.get(id1).?);
|
|
201
|
+
try std.testing.expectEqualStrings("Not Owned", registry.get(id2).?);
|
|
202
|
+
|
|
203
|
+
registry.clear();
|
|
204
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getUsedSlots());
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
test "MemRegistry - large buffer registration" {
|
|
208
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
209
|
+
defer registry.deinit();
|
|
210
|
+
|
|
211
|
+
const large_text = [_]u8{'A'} ** 10000;
|
|
212
|
+
const id = try registry.register(&large_text, false);
|
|
213
|
+
|
|
214
|
+
const retrieved = registry.get(id);
|
|
215
|
+
try std.testing.expect(retrieved != null);
|
|
216
|
+
try std.testing.expectEqual(@as(usize, 10000), retrieved.?.len);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
test "MemRegistry - empty buffer registration" {
|
|
220
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
221
|
+
defer registry.deinit();
|
|
222
|
+
|
|
223
|
+
const empty = "";
|
|
224
|
+
const id = try registry.register(empty, false);
|
|
225
|
+
|
|
226
|
+
const retrieved = registry.get(id);
|
|
227
|
+
try std.testing.expect(retrieved != null);
|
|
228
|
+
try std.testing.expectEqual(@as(usize, 0), retrieved.?.len);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
test "MemRegistry - sequential replace operations" {
|
|
232
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
233
|
+
defer registry.deinit();
|
|
234
|
+
|
|
235
|
+
const text1 = "First";
|
|
236
|
+
const id = try registry.register(text1, false);
|
|
237
|
+
|
|
238
|
+
const text2 = "Second";
|
|
239
|
+
try registry.replace(id, text2, false);
|
|
240
|
+
try std.testing.expectEqualStrings("Second", registry.get(id).?);
|
|
241
|
+
|
|
242
|
+
const text3 = "Third";
|
|
243
|
+
try registry.replace(id, text3, false);
|
|
244
|
+
try std.testing.expectEqualStrings("Third", registry.get(id).?);
|
|
245
|
+
|
|
246
|
+
try std.testing.expectEqual(@as(usize, 1), registry.getUsedSlots());
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
test "MemRegistry - replace owned with non-owned" {
|
|
250
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
251
|
+
defer registry.deinit();
|
|
252
|
+
|
|
253
|
+
const text1 = try std.testing.allocator.dupe(u8, "Owned");
|
|
254
|
+
const id = try registry.register(text1, true);
|
|
255
|
+
|
|
256
|
+
const text2 = "Not Owned";
|
|
257
|
+
try registry.replace(id, text2, false);
|
|
258
|
+
|
|
259
|
+
const retrieved = registry.get(id);
|
|
260
|
+
try std.testing.expect(retrieved != null);
|
|
261
|
+
try std.testing.expectEqualStrings("Not Owned", retrieved.?);
|
|
262
|
+
try std.testing.expectEqual(@as(usize, 1), registry.getUsedSlots());
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
test "MemRegistry - stress test with many registrations and clears" {
|
|
266
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
267
|
+
defer registry.deinit();
|
|
268
|
+
|
|
269
|
+
var round: usize = 0;
|
|
270
|
+
while (round < 10) : (round += 1) {
|
|
271
|
+
var i: usize = 0;
|
|
272
|
+
while (i < 50) : (i += 1) {
|
|
273
|
+
const text = "test";
|
|
274
|
+
_ = try registry.register(text, false);
|
|
275
|
+
}
|
|
276
|
+
try std.testing.expectEqual(@as(usize, 50), registry.getUsedSlots());
|
|
277
|
+
registry.clear();
|
|
278
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getUsedSlots());
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
test "MemRegistry - unregister basic" {
|
|
283
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
284
|
+
defer registry.deinit();
|
|
285
|
+
|
|
286
|
+
const text = "Hello";
|
|
287
|
+
const id = try registry.register(text, false);
|
|
288
|
+
|
|
289
|
+
try std.testing.expectEqual(@as(usize, 1), registry.getUsedSlots());
|
|
290
|
+
try std.testing.expectEqualStrings("Hello", registry.get(id).?);
|
|
291
|
+
|
|
292
|
+
try registry.unregister(id);
|
|
293
|
+
|
|
294
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getUsedSlots());
|
|
295
|
+
try std.testing.expect(registry.get(id) == null);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
test "MemRegistry - unregister owned buffer frees memory" {
|
|
299
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
300
|
+
defer registry.deinit();
|
|
301
|
+
|
|
302
|
+
const text = try std.testing.allocator.dupe(u8, "Owned Buffer");
|
|
303
|
+
const id = try registry.register(text, true);
|
|
304
|
+
|
|
305
|
+
try std.testing.expectEqual(@as(usize, 1), registry.getUsedSlots());
|
|
306
|
+
|
|
307
|
+
// Should free the memory when unregistered
|
|
308
|
+
try registry.unregister(id);
|
|
309
|
+
|
|
310
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getUsedSlots());
|
|
311
|
+
try std.testing.expect(registry.get(id) == null);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
test "MemRegistry - unregister invalid ID" {
|
|
315
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
316
|
+
defer registry.deinit();
|
|
317
|
+
|
|
318
|
+
const result = registry.unregister(5);
|
|
319
|
+
try std.testing.expectError(MemRegistryError.InvalidMemId, result);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
test "MemRegistry - unregister twice fails" {
|
|
323
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
324
|
+
defer registry.deinit();
|
|
325
|
+
|
|
326
|
+
const text = "Test";
|
|
327
|
+
const id = try registry.register(text, false);
|
|
328
|
+
|
|
329
|
+
try registry.unregister(id);
|
|
330
|
+
|
|
331
|
+
// Second unregister should fail
|
|
332
|
+
const result = registry.unregister(id);
|
|
333
|
+
try std.testing.expectError(MemRegistryError.InvalidMemId, result);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
test "MemRegistry - slot reuse after unregister" {
|
|
337
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
338
|
+
defer registry.deinit();
|
|
339
|
+
|
|
340
|
+
const text1 = "First";
|
|
341
|
+
const text2 = "Second";
|
|
342
|
+
const text3 = "Third";
|
|
343
|
+
|
|
344
|
+
const id1 = try registry.register(text1, false);
|
|
345
|
+
const id2 = try registry.register(text2, false);
|
|
346
|
+
const id3 = try registry.register(text3, false);
|
|
347
|
+
|
|
348
|
+
try std.testing.expectEqual(@as(u8, 0), id1);
|
|
349
|
+
try std.testing.expectEqual(@as(u8, 1), id2);
|
|
350
|
+
try std.testing.expectEqual(@as(u8, 2), id3);
|
|
351
|
+
try std.testing.expectEqual(@as(usize, 3), registry.getUsedSlots());
|
|
352
|
+
|
|
353
|
+
// Unregister middle slot
|
|
354
|
+
try registry.unregister(id2);
|
|
355
|
+
try std.testing.expectEqual(@as(usize, 2), registry.getUsedSlots());
|
|
356
|
+
|
|
357
|
+
// Register new buffer - should reuse slot 1
|
|
358
|
+
const text4 = "Fourth";
|
|
359
|
+
const id4 = try registry.register(text4, false);
|
|
360
|
+
try std.testing.expectEqual(@as(u8, 1), id4);
|
|
361
|
+
try std.testing.expectEqual(@as(usize, 3), registry.getUsedSlots());
|
|
362
|
+
|
|
363
|
+
// Verify contents
|
|
364
|
+
try std.testing.expectEqualStrings("First", registry.get(id1).?);
|
|
365
|
+
try std.testing.expectEqualStrings("Fourth", registry.get(id4).?);
|
|
366
|
+
try std.testing.expectEqualStrings("Third", registry.get(id3).?);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
test "MemRegistry - thousands of register/unregister cycles" {
|
|
370
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
371
|
+
defer registry.deinit();
|
|
372
|
+
|
|
373
|
+
// Simulate thousands of register/unregister operations
|
|
374
|
+
// This ensures slot reuse works over long periods
|
|
375
|
+
var cycle: usize = 0;
|
|
376
|
+
while (cycle < 1000) : (cycle += 1) {
|
|
377
|
+
var ids: [10]u8 = undefined;
|
|
378
|
+
|
|
379
|
+
// Register 10 buffers
|
|
380
|
+
var i: usize = 0;
|
|
381
|
+
while (i < 10) : (i += 1) {
|
|
382
|
+
const text = "test";
|
|
383
|
+
ids[i] = try registry.register(text, false);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
try std.testing.expectEqual(@as(usize, 10), registry.getUsedSlots());
|
|
387
|
+
|
|
388
|
+
// Unregister all
|
|
389
|
+
i = 0;
|
|
390
|
+
while (i < 10) : (i += 1) {
|
|
391
|
+
try registry.unregister(ids[i]);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getUsedSlots());
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Verify we can still register after all those cycles
|
|
398
|
+
const text = "final";
|
|
399
|
+
const id = try registry.register(text, false);
|
|
400
|
+
try std.testing.expectEqualStrings("final", registry.get(id).?);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
test "MemRegistry - max capacity 255 with slot reuse" {
|
|
404
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
405
|
+
defer registry.deinit();
|
|
406
|
+
|
|
407
|
+
// Fill all 255 slots
|
|
408
|
+
// NOTE: This test ensures the registry respects the u8 ID limit (max 255 slots).
|
|
409
|
+
// If the ID type is changed from u8 to u16, this test would fail because:
|
|
410
|
+
// 1. The test fills exactly 255 slots
|
|
411
|
+
// 2. It expects OutOfMemory error on the 256th registration
|
|
412
|
+
// 3. With u16, the limit would be 65535, so no error would occur
|
|
413
|
+
var i: usize = 0;
|
|
414
|
+
var ids: [255]u8 = undefined;
|
|
415
|
+
while (i < 255) : (i += 1) {
|
|
416
|
+
const text = "test";
|
|
417
|
+
ids[i] = try registry.register(text, false);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
try std.testing.expectEqual(@as(usize, 255), registry.getUsedSlots());
|
|
421
|
+
try std.testing.expectEqual(@as(usize, 0), registry.getFreeSlots());
|
|
422
|
+
|
|
423
|
+
// Should fail to register one more
|
|
424
|
+
const text = "overflow";
|
|
425
|
+
const result = registry.register(text, false);
|
|
426
|
+
try std.testing.expectError(MemRegistryError.OutOfMemory, result);
|
|
427
|
+
|
|
428
|
+
// Unregister one slot
|
|
429
|
+
try registry.unregister(ids[100]);
|
|
430
|
+
try std.testing.expectEqual(@as(usize, 254), registry.getUsedSlots());
|
|
431
|
+
try std.testing.expectEqual(@as(usize, 1), registry.getFreeSlots());
|
|
432
|
+
|
|
433
|
+
// Now we should be able to register again
|
|
434
|
+
const new_text = "reused";
|
|
435
|
+
const new_id = try registry.register(new_text, false);
|
|
436
|
+
try std.testing.expectEqual(@as(u8, 100), new_id); // Should reuse slot 100
|
|
437
|
+
try std.testing.expectEqualStrings("reused", registry.get(new_id).?);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
test "MemRegistry - replace inactive slot fails" {
|
|
441
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
442
|
+
defer registry.deinit();
|
|
443
|
+
|
|
444
|
+
const text1 = "Original";
|
|
445
|
+
const id = try registry.register(text1, false);
|
|
446
|
+
|
|
447
|
+
try registry.unregister(id);
|
|
448
|
+
|
|
449
|
+
// Try to replace inactive slot
|
|
450
|
+
const text2 = "Replacement";
|
|
451
|
+
const result = registry.replace(id, text2, false);
|
|
452
|
+
try std.testing.expectError(MemRegistryError.InvalidMemId, result);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
test "MemRegistry - getFreeSlots accounts for unregistered slots" {
|
|
456
|
+
var registry = MemRegistry.init(std.testing.allocator);
|
|
457
|
+
defer registry.deinit();
|
|
458
|
+
|
|
459
|
+
try std.testing.expectEqual(@as(usize, 255), registry.getFreeSlots());
|
|
460
|
+
|
|
461
|
+
const id1 = try registry.register("test1", false);
|
|
462
|
+
const id2 = try registry.register("test2", false);
|
|
463
|
+
const id3 = try registry.register("test3", false);
|
|
464
|
+
|
|
465
|
+
try std.testing.expectEqual(@as(usize, 252), registry.getFreeSlots());
|
|
466
|
+
|
|
467
|
+
try registry.unregister(id2);
|
|
468
|
+
try std.testing.expectEqual(@as(usize, 253), registry.getFreeSlots());
|
|
469
|
+
|
|
470
|
+
try registry.unregister(id1);
|
|
471
|
+
try registry.unregister(id3);
|
|
472
|
+
try std.testing.expectEqual(@as(usize, 255), registry.getFreeSlots());
|
|
473
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
const gp = @import("../grapheme.zig");
|
|
3
|
+
|
|
4
|
+
const GraphemePool = gp.GraphemePool;
|
|
5
|
+
const GraphemePoolError = gp.GraphemePoolError;
|
|
6
|
+
|
|
7
|
+
test "GraphemePool - invalid class_id returns InvalidId" {
|
|
8
|
+
var pool = GraphemePool.init(std.testing.allocator);
|
|
9
|
+
defer pool.deinit();
|
|
10
|
+
|
|
11
|
+
// class_id 5, 6, 7 are invalid (valid are 0-4)
|
|
12
|
+
for ([_]u32{ 5, 6, 7 }) |invalid_class_id| {
|
|
13
|
+
const invalid_id = (invalid_class_id << (gp.GENERATION_BITS + gp.SLOT_BITS));
|
|
14
|
+
|
|
15
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.incref(invalid_id));
|
|
16
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.decref(invalid_id));
|
|
17
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.get(invalid_id));
|
|
18
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.getRefcount(invalid_id));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
test "GraphemePool - out-of-range slot returns InvalidId before dereference" {
|
|
23
|
+
var pool = GraphemePool.init(std.testing.allocator);
|
|
24
|
+
defer pool.deinit();
|
|
25
|
+
|
|
26
|
+
_ = try pool.alloc("allocated");
|
|
27
|
+
|
|
28
|
+
// Class 0 exists after the allocation, but the highest encodable slot has
|
|
29
|
+
// not been allocated. Public operations must reject it before slot access.
|
|
30
|
+
const invalid_id = gp.SLOT_MASK;
|
|
31
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.incref(invalid_id));
|
|
32
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.decref(invalid_id));
|
|
33
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.get(invalid_id));
|
|
34
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.getRefcount(invalid_id));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
test "GraphemePool - unreferenced slot cannot be freed twice" {
|
|
38
|
+
var pool = GraphemePool.init(std.testing.allocator);
|
|
39
|
+
defer pool.deinit();
|
|
40
|
+
|
|
41
|
+
const id = try pool.alloc("pending");
|
|
42
|
+
try pool.freeUnreferenced(id);
|
|
43
|
+
|
|
44
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.freeUnreferenced(id));
|
|
45
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.get(id));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
test "GraphemePool - decref release cannot be freed again as pending" {
|
|
49
|
+
var pool = GraphemePool.init(std.testing.allocator);
|
|
50
|
+
defer pool.deinit();
|
|
51
|
+
|
|
52
|
+
const id = try pool.alloc("live");
|
|
53
|
+
try pool.incref(id);
|
|
54
|
+
try pool.decref(id);
|
|
55
|
+
|
|
56
|
+
try std.testing.expectError(GraphemePoolError.InvalidId, pool.freeUnreferenced(id));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
test "GraphemePool - failed first incref preserves pending ownership" {
|
|
60
|
+
var pool = GraphemePool.init(std.testing.allocator);
|
|
61
|
+
defer pool.deinit();
|
|
62
|
+
|
|
63
|
+
const id = try pool.alloc("owned");
|
|
64
|
+
const allocator = pool.allocator;
|
|
65
|
+
var failing_allocator = std.testing.FailingAllocator.init(
|
|
66
|
+
std.testing.allocator,
|
|
67
|
+
.{ .fail_index = 0 },
|
|
68
|
+
);
|
|
69
|
+
pool.allocator = failing_allocator.allocator();
|
|
70
|
+
defer pool.allocator = allocator;
|
|
71
|
+
|
|
72
|
+
try std.testing.expectError(GraphemePoolError.OutOfMemory, pool.incref(id));
|
|
73
|
+
try std.testing.expectEqual(@as(u32, 0), try pool.getRefcount(id));
|
|
74
|
+
try pool.freeUnreferenced(id);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
test "GraphemePool - growth allocation failure leaves state reusable" {
|
|
78
|
+
var failing_allocator = std.testing.FailingAllocator.init(
|
|
79
|
+
std.testing.allocator,
|
|
80
|
+
.{ .fail_index = 1 },
|
|
81
|
+
);
|
|
82
|
+
var pool = GraphemePool.initWithOptions(failing_allocator.allocator(), .{
|
|
83
|
+
.slots_per_page = [_]u32{ 1, 1, 1, 1, 1 },
|
|
84
|
+
});
|
|
85
|
+
defer pool.deinit();
|
|
86
|
+
|
|
87
|
+
try std.testing.expectError(GraphemePoolError.OutOfMemory, pool.alloc("value"));
|
|
88
|
+
try std.testing.expect(failing_allocator.has_induced_failure);
|
|
89
|
+
|
|
90
|
+
failing_allocator.fail_index = std.math.maxInt(usize);
|
|
91
|
+
const id = try pool.alloc("value");
|
|
92
|
+
try pool.incref(id);
|
|
93
|
+
try std.testing.expectEqualSlices(u8, "value", try pool.get(id));
|
|
94
|
+
try pool.decref(id);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
test "GraphemePool - defer cleanup on failure path" {
|
|
98
|
+
var pool = GraphemePool.init(std.testing.allocator);
|
|
99
|
+
defer pool.deinit();
|
|
100
|
+
|
|
101
|
+
var allocated_ids: std.ArrayListUnmanaged(u32) = .{};
|
|
102
|
+
defer allocated_ids.deinit(std.testing.allocator);
|
|
103
|
+
|
|
104
|
+
for (0..5) |i| {
|
|
105
|
+
var buffer: [8]u8 = undefined;
|
|
106
|
+
const slice = std.fmt.bufPrint(&buffer, "{d}", .{i}) catch unreachable;
|
|
107
|
+
const gid = try pool.alloc(slice);
|
|
108
|
+
try pool.incref(gid);
|
|
109
|
+
try allocated_ids.append(std.testing.allocator, gid);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Simulate failure cleanup
|
|
113
|
+
for (allocated_ids.items) |id| {
|
|
114
|
+
try pool.decref(id);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Force slot reuse
|
|
118
|
+
for (0..5) |_| {
|
|
119
|
+
_ = try pool.alloc("reuse");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
for (allocated_ids.items) |id| {
|
|
123
|
+
try std.testing.expectError(GraphemePoolError.WrongGeneration, pool.get(id));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
test "GraphemePool - pending grapheme cleanup on failure" {
|
|
128
|
+
var pool = GraphemePool.init(std.testing.allocator);
|
|
129
|
+
defer pool.deinit();
|
|
130
|
+
|
|
131
|
+
var result_graphemes: std.ArrayListUnmanaged(u32) = .{};
|
|
132
|
+
defer result_graphemes.deinit(std.testing.allocator);
|
|
133
|
+
|
|
134
|
+
var pending_gid: ?u32 = null;
|
|
135
|
+
const success = false; // intentionally never true to test cleanup path
|
|
136
|
+
|
|
137
|
+
defer {
|
|
138
|
+
if (!success) {
|
|
139
|
+
if (pending_gid) |pgid| {
|
|
140
|
+
pool.decref(pgid) catch {};
|
|
141
|
+
}
|
|
142
|
+
for (result_graphemes.items) |gid| {
|
|
143
|
+
pool.decref(gid) catch {};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const gid1 = try pool.alloc("grapheme1");
|
|
149
|
+
pending_gid = gid1;
|
|
150
|
+
try pool.incref(gid1);
|
|
151
|
+
try result_graphemes.append(std.testing.allocator, gid1);
|
|
152
|
+
pending_gid = null;
|
|
153
|
+
|
|
154
|
+
const gid2 = try pool.alloc("grapheme2");
|
|
155
|
+
pending_gid = gid2;
|
|
156
|
+
try pool.incref(gid2);
|
|
157
|
+
// Simulate failure before storing - pending_gid remains set
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
test "encodeUnicode - cleanup on mid-operation failure" {
|
|
161
|
+
const SimulateResult = struct {
|
|
162
|
+
success: bool,
|
|
163
|
+
captured_ids: [2]u32,
|
|
164
|
+
captured_count: usize,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const simulateEncodeUnicode = struct {
|
|
168
|
+
fn run(pool: *GraphemePool, should_fail: bool) SimulateResult {
|
|
169
|
+
var result: SimulateResult = .{
|
|
170
|
+
.success = false,
|
|
171
|
+
.captured_ids = undefined,
|
|
172
|
+
.captured_count = 0,
|
|
173
|
+
};
|
|
174
|
+
var pending_gid: ?u32 = null;
|
|
175
|
+
var stored_ids: [8]u32 = undefined;
|
|
176
|
+
var stored_count: usize = 0;
|
|
177
|
+
|
|
178
|
+
defer {
|
|
179
|
+
if (!result.success) {
|
|
180
|
+
if (pending_gid) |pgid| {
|
|
181
|
+
pool.decref(pgid) catch {};
|
|
182
|
+
}
|
|
183
|
+
for (stored_ids[0..stored_count]) |gid| {
|
|
184
|
+
pool.decref(gid) catch {};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const gid1 = pool.alloc("emoji1") catch return result;
|
|
190
|
+
result.captured_ids[result.captured_count] = gid1;
|
|
191
|
+
result.captured_count += 1;
|
|
192
|
+
pending_gid = gid1;
|
|
193
|
+
pool.incref(gid1) catch return result;
|
|
194
|
+
stored_ids[stored_count] = gid1;
|
|
195
|
+
stored_count += 1;
|
|
196
|
+
pending_gid = null;
|
|
197
|
+
|
|
198
|
+
const gid2 = pool.alloc("emoji2") catch return result;
|
|
199
|
+
result.captured_ids[result.captured_count] = gid2;
|
|
200
|
+
result.captured_count += 1;
|
|
201
|
+
pending_gid = gid2;
|
|
202
|
+
pool.incref(gid2) catch return result;
|
|
203
|
+
|
|
204
|
+
if (should_fail) {
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
stored_ids[stored_count] = gid2;
|
|
209
|
+
stored_count += 1;
|
|
210
|
+
pending_gid = null;
|
|
211
|
+
|
|
212
|
+
result.success = true;
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
}.run;
|
|
216
|
+
|
|
217
|
+
var pool = GraphemePool.init(std.testing.allocator);
|
|
218
|
+
defer pool.deinit();
|
|
219
|
+
|
|
220
|
+
const sim_result = simulateEncodeUnicode(&pool, true);
|
|
221
|
+
try std.testing.expect(!sim_result.success);
|
|
222
|
+
try std.testing.expectEqual(@as(usize, 2), sim_result.captured_count);
|
|
223
|
+
|
|
224
|
+
// Force slot reuse by allocating enough graphemes to cycle through freed slots
|
|
225
|
+
// Allocate more than captured to ensure freed slots get reused
|
|
226
|
+
for (0..4) |_| {
|
|
227
|
+
_ = try pool.alloc("reuse");
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Verify cleanup: old IDs should now have wrong generation
|
|
231
|
+
for (sim_result.captured_ids[0..sim_result.captured_count]) |old_id| {
|
|
232
|
+
try std.testing.expectError(GraphemePoolError.WrongGeneration, pool.get(old_id));
|
|
233
|
+
}
|
|
234
|
+
}
|