Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Benchmarks: frame times in a browser. `apps/playground/bench.html` (built with the playground) pans, zooms and scrolls made-up trees of 125 to 10,000 tips as SVG and on the canvas and times every frame; open it in any browser, press Run and save the numbers. `node scripts/bench-browser.mjs` runs it in the Chrome already installed, headless, at pixel density 1 and 2 and with the main thread slowed 4 times, and writes `docs/benchmarks-browser.md`; `--from <file>` adds a section from numbers saved in another browser. It uses a throwaway profile that it deletes, listens on this machine only and sends nothing anywhere. First numbers (headless Chrome 157, M2 Max, other work running): the canvas held 60 frames a second at every size up to 19,999 nodes, slowed thread included; SVG held it through 1,999 nodes, and through 499 on the slowed thread. The 1,000-node switch is unchanged. Not measured: WebKit, Firefox, a window on a real screen, a real slow device, radial layouts. The benchmark page and script have no tests of their own.
- Payload plugin docs: moving a departed person's proposals to another account. The README's "When someone leaves" now says that `author` and `decidedBy` can't be changed through Payload, that the lock is a hook and so doesn't cover a host's own database code, and that a host making that move there must change only those two fields and leave `proposal`, `checksum` and the snapshot alone. A new test makes the move on MongoDB and checks that the proposal still matches its checksum, the version made from it still verifies, and the proposal stays locked. No code changed; an option to allow the move through Payload was considered and not built (ADR 0012).
- Payload plugin: people are recorded by id, never by name (changes the unreleased proposals, before anyone used them). `proposals.nameOf` is gone. `proposals.personId({ req })` gives an opaque id for the signed-in person (default: their user document's id), and that id is all a proposal stores about its author and all an accepted proposal seals into the new snapshot for the author and the manager. An id is 1 to 64 letters, digits, `.`, `_`, `:` and `-`, starting with a letter or digit, so an email address or a name with a space in it is refused: the action stops, nothing is saved, and the refused value isn't written to the log. A one-word handle would pass; the plugin can't tell it from an id. `proposals.displayName({ req, personId })` is optional and gives the name to show: it is looked up each time a proposal is read (once per person per request), returned as `authorName` on the proposal and in the preview, and never stored or sealed, so a name changed or removed at the site changes what is shown at once and leaves every snapshot's checksum alone. Why: a name inside a sealed snapshot can't be taken out when a person leaves. Core is unchanged apart from its comments and one error text: `acceptIntoSnapshot` still seals the `author` and `acceptedBy` strings it is given. Still sealed as written, and not screened: a proposal's title, each move's note and the manager's note. No endpoint turns an id from a snapshot's record back into a name. Tested on Payload 3.93 with an in-memory MongoDB (142 plugin tests, 526 in all) and through the example site (47 checks); eight deliberate breaks of the new code each failed a test. Not tested: Postgres or SQLite, and a host with more than one auth collection.
- React: names in the drawing are no longer struck through or covered. In rectangular layouts an inner node's name was drawn 6 units above the node, so when its children's rows were one row apart, a child's branch ran straight through it ("Reptilia" in the amniotes classes view). The name now goes in the first of three places the branches to its children leave clear: on the node's own row, just above it, or just below it; when rows are closer than a name is tall, it takes the place with the most room. A folded branch's name started 8 units out, on top of its 12-unit triangle; it now starts 16 units out, past it. The SVG and the canvas use the same rule (`innerLabelAt`, `leafLabelX`), so a name is in the same place in both. A leaf's name hasn't moved. Limits: a long name can still cross a branch further down the tree, since only the node's own children are looked at, and in a radial drawing a folded branch's triangle still points right whatever the branch's angle.
- Example site: `apps/payload-example`, a small Payload 3.93 and Next.js 16 site that uses the Payload plugin (private, never published). It runs on this machine only, on a throwaway in-memory MongoDB that `pnpm dev` starts and seeds: two made-up accounts with a password made up per run, one published snapshot with two views, and one staged snapshot, all from the repository's illustrative fixtures. Accounts have two roles: a curator manages and decides, a member reads and proposes, only a curator hands out roles, and a member sees no account but their own. Proposals record people by account id, and `proposals.displayName` looks up a public `handle`, not the email address, when one is shown. The public pages are Server Components that read as an anonymous visitor and draw each published view with `TreeView` and `TreeOutline`, with what the view leaves out and its sources; a source's address is a link only when it is http or https. `pnpm smoke` builds the site, starts it on a free port and runs 47 checks over HTTP with sign-in cookies: what a visitor reads and can't do through the pages, REST and GraphQL; cookies that count only from the site's own pages; roles; a proposal made, shared, accepted into a staged, sealed version that records both people by id and holds no handle and no email address. CI runs it, and the CI workflow now cancels a run when a newer push arrives and stops a job after 20 minutes. Passed on `next dev` and on the built site on a Mac; the pages were looked at in headless Chrome in light and dark. Not tested: a person clicking through the admin, a screen reader, Postgres or SQLite, a deployed site. The site has no pages for proposals or imports.
Expand Down
32 changes: 32 additions & 0 deletions apps/playground/bench.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>OneTaxonomy renderer benchmark</title>
<link rel="stylesheet" href="styles.css" />
<style>
body { margin: 0; padding: 0; font-family: system-ui, sans-serif; }
@media (prefers-color-scheme: dark) { body { background: #0f1218; color: #eef1f6; } }
/* The drawing sits at the top left, 1000 CSS pixels square, so it is on screen in a 1100 by 1100 window. */
#stage { width: 1000px; height: 1000px; overflow: hidden; }
#stage svg { display: block; width: 1000px; height: 1000px; }
main { padding: 1rem 1.5rem 2rem; max-width: 70rem; }
h1 { font-size: 1.3rem; margin: 0 0 0.5rem; }
button { font: inherit; padding: 0.4rem 0.9rem; }
table { border-collapse: collapse; margin-top: 0.75rem; }
th, td { border: 1px solid color-mix(in srgb, currentColor 30%, transparent); padding: 0.3rem 0.6rem; text-align: right; }
th:first-child, td:first-child, th:nth-child(4), td:nth-child(4) { text-align: left; }
</style>
</head>
<body>
<div id="stage" aria-hidden="true"></div>
<main>
<h1>OneTaxonomy renderer benchmark</h1>
<p>Pans, zooms and scrolls made-up trees, drawn as SVG and on the canvas, and times each frame. It takes about four minutes. Keep this window in front and leave the mouse alone while it runs.</p>
<p><button id="run" type="button">Run</button> <span id="status" role="status"></span></p>
<div id="results"></div>
</main>
<script src="bench.js"></script>
</body>
</html>
Loading
Loading