Skip to content

Sashfold 0.1.5

Choose a tag to compare

@codingncaffeine codingncaffeine released this 02 Oct 03:06
· 269 commits to main since this release

Sashfold 0.1.5 is the release where pages move: 172 commits since 0.1.0 on 2026-09-16. Video and sound play, and a video site's watch page plays through with its player's controls answering. Every tab's page runs on a thread of its own, so the window never waits on a page; the network speaks HTTP/2; and the DOM and Web API surface is much larger and much closer to the standard, with pointer events, WebIDL receiver checks, Trusted Types and many interfaces a page expects to find. Speed work runs through all of it. Still every byte is written in this repository, and still it does not pretend to do what it cannot.

What's New

  • Video plays on Linux — a WebM parser and Media Source Extensions feed a VP9 decoder on the machine's video hardware, through Vulkan Video and then VA-API, with pictures decoded off the page's thread, scaled smoothly and shown at their time.
  • Sound on Linux — an Opus decoder and a WAVE reader written here, played straight to the desktop's PulseAudio or PipeWire server; a video's sound plays, and a page's volume and mute reach the mixer.
  • A player's own controls — play and pause, volume, seek, settings, theater mode and full screen answer on a video site's watch page. The Fullscreen API gives an element the whole window, and Esc gives it back.
  • A page on a thread of its own — each tab's scripts, styles, layout and paint run in an engine on a thread of their own, so a busy page no longer holds the strip, the address bar or the window; dedicated workers get threads too.
  • Pages arrive sooner — stylesheets, scripts, fonts and pictures are fetched together and ahead of the page's asking, the document comes while the window stays live, and a page shows with the pictures that have come and swaps in its fonts as they land.
  • HTTP/2 — a page's requests to one host share one connection, with HPACK and the framing written from the RFCs; a request that cannot safely be repeated is never sent twice.
  • Components and observers — custom elements, a MutationObserver that delivers real records, an IntersectionObserver that measures, and load and error events on pictures and stylesheet links.
  • Canvas, IndexedDB and Intl — a canvas draws through a full 2D context, databases are kept per origin in the profile, and Intl formats numbers, dates, lists, units and relative times in English.
  • Pointer events — a page hears the pointer as the standards have it: over, enter, move, down, up, out and leave with their mouse counterparts, a click at the common ancestor, double and auxiliary clicks, and real movement.
  • A far larger Web API surface — WebIDL receiver checks, event handlers on the interfaces that own them, window and navigator objects as real interfaces, Trusted Types, TreeWalker and NodeIterator, resource-management stacks, and regular-expression lookbehind and \p{} escapes.
  • More CSS, and forms that post — @supports, display: contents, aspect-ratio, object-fit and pointer-events; a form whose method is post sends URL-encoded, multipart or plain-text bodies.
  • Menus and tabs — a right click opens a menu of what it landed on, the toolbar has a main menu, Ctrl+Shift+T brings a closed tab back, and a tab can be duplicated or pinned.
  • Bookmarks — a star and Ctrl+D, a bar under the toolbar, folders, a manager at about:bookmarks with search and undo, import from other browsers, export and dated backups.
  • Themes from other browsers — a Firefox .xpi or a Chrome .crx is converted into a theme, from the profile's folder or at one click on about:themes, with pictures behind the tabs, moving ones included.

What's Fixed

  • Pages that would not scroll or click — a page whose html and body are 100% tall now scrolls to what reaches out of them, and what is under the pointer is found in painting order, so a link laid over a whole card answers and z-index counts.
  • Dialogs nobody could see — a fixed box inside a fixed backdrop was never laid out, so a page held still under a dialog showed none.
  • Relative links and the address field — <base href> was read by nothing, and pushState left the address field behind so that Back left the site; both follow the page now.
  • A window that stopped answering — loading a page held the window until it drew, and dragging a window's edge queued half a minute of layout; the document comes on another thread, and the drag settles half a second after it ends.
  • Pictures stretched out of shape — height: auto over a picture's height attribute came out as tall as the attribute; pictures keep their shape now, and complete says whether the picture is in.
  • Buttons drawn empty — an icon button showed an empty face, and a field's placeholder, a control's padding and its baseline were missing or wrong.
  • A video that stopped partway — a video site's watch page gave up about 44 seconds in; Web API methods now refuse to run on the wrong kind of object, as every browser's do, and the video plays through.
  • Players that stalled — a stylesheet link never said its sheet had come, so a player stayed in its loading skeleton and theater mode and full screen did nothing; a click on pause was read as a click on the picture and played again; play() before the source was chosen was refused; and video stuttered while its page was busy.
  • Pages that use :has() — one :has() in a page's styles made every style change recompute the whole document; now only what the change can reach is recomputed, and entering full screen on a video player went from about three seconds to half a second.
  • Scripts that threw where other browsers do not — recursion stopped at a thousand calls where a browser reaches twelve and a half thousand, and JSON.parse and syntax errors now carry V8's wording.
  • A runaway page took the machine — a script that allocated without end now stops at a heap ceiling of its own, and the other tabs go on.
  • The web driving the browser's own pages — a link or a script could name about:bookmarks?remove= and have it done; only the page itself can ask now.

What's Not Written Yet

  • Hover and focus styling — :hover, :focus, :active and :focus-visible never match yet and there is no outline, so hover and focus styles do not show and a clicked button shows the engine's own focus ring.
  • Painting gaps — a transform can translate but not scale, rotate or skew, so a video player's progress bar draws its fill at full width; CSS shadows, filters, clip paths and masks are not painted.
  • Slow reactions — layout after a script reads it is recomputed for the whole page, which makes some page reactions slow.
  • The newer edge of scripting — WebAssembly, WebGL, Web Audio, streams, service workers, import maps, WebSocket, shadow trees and the regular-expression v flag are not written.
  • Media gaps — video is VP9 in WebM and sound is Opus and WAVE; Opus frames of the SILK and hybrid kinds play as silence, and any other codec or container, WebP and AVIF are not read. Windows has no sound and shows no video pictures yet, and on Linux video needs a graphics driver that decodes VP9 through Vulkan Video or VA-API — there is no software path for playback yet.
  • Layout and text gaps — subgrid, masonry, multi-column layout and several table behaviors; Arabic letters do not join, and Thai, Lao, Khmer and Myanmar words break between clusters.
  • macOS — the engine and its command line build and test on macOS in CI, but there is no window there yet, and no TLS client of its own either.

Measured

  • CSS reference tests — 9,877 of 15,186, up from 9,427 of 14,616. The table is at sashfold.com/wpt.html.
  • WPT scripted tests — 145,667 of 174,114 subtests over 5,555 files, against 65,822 of 74,294 in 0.1.0; the suite grew with many more directories. The table is at sashfold.com/wpt-harness.html.
  • test262 — the ECMAScript conformance suite: 41,845 of 45,367, up from 40,358 of 41,791. The table is at sashfold.com/test262.html.
  • At 100% — both html5lib suites, WPT URL parsing, and the Unicode bidirectional and line-breaking conformance suites.
  • The Sashfold 100 — 80 of a hundred pages of the live web render on the Windows build and 82 on the Linux build, against 83 and 81 in 0.1.0, with the five deliberately bad certificates refused on both. What each page asks for that is not written yet is listed at sashfold.com/sashfold100.
  • Every score is held by CI: a test that stops passing fails the build.

Running It

  • The downloads — sashfold-0.1.5-windows-x64.zip, unzipped with themes kept beside sashfold.exe, and sashfold-0.1.5-linux-x64.tar.gz, unpacked with themes kept beside sashfold. sashfold https://en.wikipedia.org opens the window on a page; with no address it opens its own new-tab page. Downloads go to your Downloads folder.
  • A Debian package and an AUR package — sashfold_0.1.5_amd64.deb installs on Debian 13, Ubuntu 24.04 and their derivatives with sudo apt install ./sashfold_0.1.5_amd64.deb, which puts sashfold on PATH and in the applications menu with its icon; on Arch, sashfold-bin on the AUR installs the same build the same way.
  • Requirements — Windows 10 or 11, 64-bit; the binary is statically linked and imports only the operating system's own libraries, which is checked in CI. Linux needs a 64-bit machine with glibc 2.39 or newer (Ubuntu 24.04, Debian 13, Fedora 40 and their successors, Arch) and a Wayland compositor; video needs a graphics driver that decodes VP9 through Vulkan Video or VA-API, and sound a PulseAudio or PipeWire server, which the Debian package recommends; the binary carries its own C++ runtime and imports only libc and libm, checked the same way, and the window is a Wayland client of its own with no toolkit underneath it. bash tools/install-desktop-linux.sh ./sashfold --desktop puts it in the applications menu and on the desktop with its icon; that script needs ImageMagick for the icon sizes.
  • Profiles and headless rendering — --profile <dir> keeps a browser's cookies, storage and session in that folder between runs. sashfold --render page.html -o out.png draws a page to a picture with no window at all.
  • Source — macOS builds from source with CMake and Ninja; the window itself is Windows and Linux for now.