Skip to content

Not written yet

codingncaffeine edited this page Nov 6, 2026 · 100 revisions

Not written yet

The bar for every feature is what the shipping browsers offer, at the least (The Pledge). This page is where Sashfold is still short of it: work that is owed, none of it decided against. Nothing stands in for a missing feature except where this page says so; the dashboard's census on The Sashfold 100 counts how often the live web asks for each.

Scripting

Pages run their scripts (Scripting): the DOM, events, timers, promises and the event loop are written. What a page cannot do is what its bundle needs from the newer half of the language, below: a script that uses one of those features fails at parse time with a syntax error that names it, and the page stands as its markup alone. A growing share of sites answer a browser without their script with a bot challenge instead of the page.

A site that puts every visitor through an invisible reCAPTCHA now gets as far as a browser nobody has heard of gets anywhere: the check runs — its worker, its ports, its frames measuring themselves — and the picture challenge is shown, drawn as it should be, for the reader to answer. Getting there takes about twenty seconds of the engine's time, most of it spent collecting garbage and looking variables up by name, which is the next work on the engine's speed (Measurements).

Of workers: module workers (type: "module"), shared and service workers, a worker started by a worker, and a blob: URL the page made read from inside its worker (importScripts or fetch; the worker's own are read). Of Web Crypto: everything but digest — keys, signing, encryption — is a refused promise. Of errors: a stack line names where its function begins, not where the call was made. Of flexbox: a picture's automatic minimum height through its ratio, when the other axis is what is constrained.

The engine itself exists and runs scripts: a JavaScript engine of our own in src/js (Architecture), scored on test262 (Measurements). What it does not have yet, each of which is a syntax error that names itself rather than a silent misparse: the v regular-expression flag, lookbehind and property escapes. Modules are written — records, their linking and their evaluation, live bindings, the namespace object, dynamic import(), import.meta and top-level await (a module's body runs as an async function, and its importers wait for it) — and module scripts on the page run: fetched in CORS mode with the credentials the element asks for, held to a JavaScript type, deferred in document order with the classic defer scripts, an inline module keyed by its element with the document's URL as its base. JSON and CSS modules are refused by type. Not written on the page side either: WebSocket, streams (fetch and XMLHttpRequest read a body whole), tree walkers, document.write after the parse, MutationObserver records. A value a script sets on a style (element.style.x = …, setProperty) is kept whatever it is: the CSSOM does not yet check it against the property's grammar, nor give it back in the canonical order.

Styling

  • Pseudo-elements other than ::before, ::after and ::first-letter — ::first-line, ::marker, ::selection, ::placeholder — are parsed, and match nothing. A background, border or padding on a ::first-letter waits on inline box painting, below.
  • Of shadow trees (Styling): a <link rel="stylesheet"> inside one, exportparts, delegatesFocus and focus moving through a tree, elementFromPoint into a tree, and ElementInternals (form-associated custom elements, custom states).
  • Of animations (Styling): transitions of discrete properties (transition-behavior: allow-discrete); scroll and view timelines and animation-range; getKeyframes() on a CSS animation gives its values as the sheet wrote them, not as they compute; getComputedStyle(element, '::before') answers for the element.
  • font-synthesis — a weight or a slant the face does not have is always synthesized, so font-synthesis-weight: none and font-synthesis-style: none change nothing.

Layout

  • margin-trim — the property is not read, so a container cannot drop the margins of the children that touch its own content edge. Now that the flow-relative properties are read, this is the one thing between the engine and the twenty-eight tests in css-box/margin-trim, which until then were matching a reference that had no margins either.

  • Tables — empty-cells: hide; visibility: collapse on rows and columns; percentage heights of rows and cells. In the collapsing border model a line whose winner changes along a spanning box's edge is drawn at the widest of them rather than segment by segment.

  • Grid — subgrid and grid-lanes (masonry) are passed over (a subgrid track list is none); items share a baseline down a row but not across a column, so justify-self: baseline is start. The content keywords are read as a width, a min-width, a max-width and a flex-basis, but not as a height — a block's min-content and max-content heights are its content height, which is what auto already gives it — and fit-content(<length>) as a size property is not read (the grid track function of that name is).

  • Multi-column layout, text-overflow; hyphenation by dictionary — hyphens: auto hyphenates only at the soft hyphens the text holds — and hyphenate-limit-chars; tab-size, and the tab stops a preserved tab should reach — each is 8 spaces wide wherever it stands; the words of Thai, Lao, Khmer and Myanmar, which a dictionary finds — a line ends between their clusters instead, and word-break: auto-phrase breaks as normal does; the part of line-break: loose and normal that depends on the language (the CJK hyphens, centred punctuation, prefixes and suffixes); justify stretches the spaces a line was broken at, so text kept whole by white-space: pre-wrap — which holds its spaces inside a word — does not stretch, and the only word separator it stretches is the ordinary space, not the no-break space or the Ethiopic, Aegean, Ugaritic and Phoenician ones; text-justify is read but the only method written is the one between words, so inter-character behaves as inter-word; and text-indent reads no each-line or hanging. text-transform uses the SIMPLE case mappings, so sharp s stays sharp s rather than becoming SS, the Turkish dotted i and the Greek final sigma are not decided by language or neighbour, and full-width and full-size-kana are not written; capitalize finds word starts within one text node, so a word split across an inline box is capitalized twice.

  • Writing modes and bidi — writing-mode is read, and a page or a box that asks for vertical-rl, vertical-lr, sideways-rl or sideways-lr is laid out sideways: its lines stack across the page, its text runs down it, and every glyph of a horizontal script turns a quarter circle. A box whose mode is not the one around it starts an orthogonal flow, laid out in a frame of its own and turned back into the page when it is done; the room its lines have is its own extent along the outer block axis, or where that is not settled, the initial containing block's. direction and the dir attribute settle which end of the line a block's content starts at and what start and end mean, and dir="auto" and unicode-bidi: plaintext find that direction in the text itself — and the bidirectional algorithm reorders the text: a line's entries are drawn in the order rules L1 and L2 give them, a run that reads right to left has its characters reversed and its brackets mirrored (L4), and unicode-bidi opens the levels its values name, on inline boxes and, for the overrides, on blocks, as the formatting characters written in the text do. A flex container's two axes, a grid's columns and a table's columns all read the way their direction says, and so does the overflow edge, the indent, the room a width leaves over, and where a box out of the flow stands when it writes no offsets of its own.

    What is left: an inline box whose content changes direction inside it is drawn as one box around all of it rather than in the several pieces the specification asks for; there is no shaping, so Arabic letters do not join and a combining mark inside a reversed run lands on the wrong side of its base; text-orientation is read but does nothing, and text-combine-upright is not written. An orthogonal flow's baseline is dropped rather than synthesized.

  • Flexbox — baseline alignment is flex-start.

  • Positioning — an inline box that the flow broke around a block child fades that block with it, but each such block is its own group rather than all of them and the box's lines being one, which shows only where two of them overlap.

  • Inline boxes — an empty one contributes no height of its own to the line box, and box-decoration-break: clone draws as slice.

  • List markers — list-style-image; and an inside marker leads the item’s own first line only, so a list item whose content is blocks keeps its marker outside.

  • Percentage heights of a box whose containing block has no definite height stay auto, as the specification says.

Painting

  • Filters, clip paths, masks; border-image in all its parts.
  • Of shadows (Painting and text): a table row's or row group's box shadow (the row reaches the painter as a background color only), and a shadow over a box broken across lines or pages drawn per fragment as box-decoration-break says.
  • Paint order inside a line: a block's words are painted after all of its inline boxes, so an inline box's background or shadow that reaches back over earlier words of the same block lies under them rather than over them.
  • Where two translucent layers meet exactly halfway between two 8-bit values, the blend rounds up where the shipping engines round down: one unit in one channel.
  • Of rounded corners: a positioned descendant of a box that rounds its corners is held to that box's rectangle rather than its curve, and a table row's or column's background under its cells is square.
  • Of backgrounds: background-attachment (every layer scrolls with the page), background-clip: text and border-area, three- and four-value and negative-percentage positions, and a row's or column's background in the collapsing border model.
  • Rotations, scales and skews (translations are drawn).
  • Border styles other than solid draw solid.
  • Font hinting. Of colour emoji, the sequences: a family, a flag or a profession written as several code points joined by U+200D or paired as regional indicators, a skin tone, and the text and emoji presentation selectors need GSUB's ligatures to become one glyph, and are drawn one code point at a time until then; COLR version 1 (gradients, transforms), SVG glyphs, and sbix graphics that are not PNG (JPEG, TIFF, a dupe of another glyph's) are not read; a page's own @font-face emoji font yields to a colour face the machine has.

Media

  • CFF2, the variable-font form, is not read (TrueType and CFF @font-face sources load, plain or wrapped as WOFF or WOFF2).
  • AVIF.
  • Of SVG (Painting and text has what is drawn): markers, patterns, masks, filters, foreignObject, text on a path, textLength, the switch conditions (every child is drawn), animation and scripting inside a picture, a <image> fetched from the network (a data: URL draws), an href to another document; a group's opacity fades each shape on its own rather than the group as one, which shows only where two of its shapes overlap; text and pictures are drawn level whatever the transform turns; the CSS transform and clip-path properties on SVG elements (the attributes are read); vector-effect, paint-order, shape-rendering.
  • Of audio and video: MP4 with H.264 and AAC, which is what most of the web serves (WebM with VP9 and Opus plays, as YouTube serves it, and WAVE); a way to decode pictures on a machine whose graphics card decodes none; Windows and macOS.

Frames

An <iframe> shows its document — its srcdoc, a data: URL, or what its src fetches — drawn into the frame at the frame's size (Layout) and held to the framing rules Security defaults lists; its document runs its own scripts in a realm of its own (Scripting), is drawn live as they change it, follows its iframe when a script inserts, removes or repoints it, navigates itself by its Location and runs javascript: URLs, keeps its sandbox, and is reached from the page and back through a WindowProxy — contentWindow, parent, top and postMessage across origins, contentDocument and frameElement within one. A <frame> has its window and its documents as an iframe does. What a frame does not have yet: an error page drawn for a document it cannot show (it keeps its window, over an empty document of an opaque origin); find in page inside a frame; a frame document that is not markup (a picture or plain text sent to a frame shows nothing); of <object> and <embed>, deciding again when a later style change hides or shows one, a size of its own for an SVG document one shows, an object telling a document the framing rules refuse from one that failed to load (both show its fallback), and document.elementFromPoint for their image maps; a blob: URL in an iframe's src, fetch() or XMLHttpRequest; loading="lazy" (every frame is fetched when its page is laid out, one after another); BroadcastChannel; marginwidth and marginheight. Setting an iframe's src or srcdoc to the value it already has does not reload it, as it would in a browser; it only brings back what the attribute names when the frame's Location took it elsewhere.

Networking and the shell

  • The macOS window and TLS, so the window and https pages are Windows and Linux today. On Linux the TLS client checks only the leaf's revocation list and no OCSP, and sends no early data on a resumed connection; the frame the shell draws on a compositor without server-side decorations (GNOME) has no shadow and no title text of its own; a touchscreen taps and scrolls but does not pinch or select, and an input method composes at the caret but is given no surrounding text to edit.
  • Of aspect-ratio: a flex or grid item's automatic minimum size through its ratio, and a grid container whose content outgrows the ratio's height (it aligns within the ratio's); object-fit on a video, a canvas and an <svg> picture in vertical text.
  • Of forms that post: one inside a frame (it says so), files in a multipart/form-data body, and asking before a reload sends the data again (a reload is a GET); file inputs are drawn only; required/pattern validation; a select's dropdown (keyboard only). Of a field's text: a selection smaller than the whole value (Ctrl+A selects all of it, and what is typed or pasted takes its place), Shift with the arrows, a drag or a double click to select, and a click that puts the caret where it landed (it goes to the end).
  • Socket timeouts (a hung server hangs a load), of loading off the window's thread, all but the first step: a page's stylesheets, scripts, fonts and pictures are fetched together ahead of its asking (Networking), and the document comes on another thread with the window live meanwhile, but an @import, a frame's document and a script's own fetch() are still waited for where they are asked — by the page's own thread, which is no longer the window's (The shell): a heavy page holds its own tab for as long as those take, and its scrolling with it, while the window, the tabs and the address bar stay the reader's; of the cache, stale-while-revalidate and stale-if-error, range requests, a Vary beyond Accept, Accept-Encoding and User-Agent (such a response is not stored), and a cache partitioned per container.
  • Of the menus (The shell): a field's Cut and Copy, which wait on a field having a selection of its own (it has a caret); saving a link's target, and searching for the selected words (there is no search engine to send them to until the reader has chosen one); a menu is drawn inside the window, so it cannot reach past the window's edge the way the system's own can.
  • Of bookmarks: a popup at the star to name and file a new one (it goes onto the bar, and is edited on about:bookmarks), dragging to reorder or onto the bar — on the bar and in the manager, where Up and Down stand in for it — several chosen at once, tags and keywords, Safari's bookmarks (a binary property list) and Firefox's live places.sqlite (its own dated copies are read instead), and a store of page icons shared with history (a bookmark keeps its own). A history page, suggestions in the address bar, a downloads list, zoom, a settings page; of session restore, the pages a session's tabs were on are fetched again rather than kept, so a form's typed values and a page's script state do not come back, and a session is one file per profile, never several windows; of the profile, the cache lives in memory and is shared between containers (a container's requests can tell whether another container fetched a resource, by timing — Firefox partitions it), sessionStorage is the document's rather than the tab's, and a container has no menu of its own yet (the chord, the tab's colour and --script until the command palette).
  • Of Content Security Policy: securitypolicyviolation events and the reports report-uri and report-to name (the directives are read; a violation is a console line and nothing leaves the machine); base-uri (no <base> resolution); media-src, worker-src and manifest-src are matched but nothing of theirs is fetched yet; a framed document's own policy is enforced but its violations are not reported, a frame having no console of its own; a sandbox directive's flags beyond allow-scripts and allow-forms (the origin stays the page's); upgrade-insecure-requests for navigations (subresources are upgraded); a hash source matching an external script by its integrity; the nonce attribute's value stays readable from the tree.
  • Of content blocking: regular-expression rules and the csp, redirect, removeparam options; the procedural (#?#, :has-text() and kin), style-injecting (#$#), snippet and scriptlet cosmetic forms; an element-hiding rule for an id or class a script adds after the page loaded (the sheet is composed from what the page has when its styles are gathered). Lists are read at start, not refreshed.
  • The tab strip's open, close and hover transitions: the theme's timings are parsed, not yet consumed.
  • Of what Security defaults says is not written: going on past a certificate error behind a warning, for a host that has not asked for HTTPS only; choosing a search engine for the address bar; opening a download from the browser.
  • Of notifications (Security defaults): macOS (no window there yet; pages are answered "denied"), a service worker's notifications and so actions, badges, large images and vibration.
  • Of the sandbox: each site in a process of its own with no rights beyond what it needs. On Linux the one process has given up starting programs and writing outside its own folders; it can still read what you can and reach the network. On Windows and macOS nothing is given up yet.
  • Of updates (Security defaults): macOS (no window there yet).

Clone this wiki locally