slate 0.0.28 — the client-side gap
The client-side gap. slate could build a page and could not read one; it can now, which is what
makes hydration possible — and a link behave like a link.
Behaviour changes
A call the program wrote is strict on both back ends. The JavaScript back end checked no arity at
all: f(1, 2) to a one-parameter f dropped the 2 and ran. It is a fault now, as it always was
under the interpreter. A function with no parameters carried no signature at all, which is why a
component given props was the silent case.
A native calls your function with as many arguments as it declares. on(node, "click", () -> …)
is what a person writes and now what runs; declaring more than the native has is a fault naming the
native. The checker follows the machine through a seam, fits_callback, so a program-declared
(integer, integer) -> integer still refuses n -> n.
A browser's print is the print dialog, and slate was reaching for it. A page's every
print("hi") opened a printer chooser and wrote nothing. It writes to the console now. A document is
what tells a browser from quickjs, whose print is a writer.
Connecting to a literal address no longer touches the resolver. connect("127.0.0.1", p) asked
getaddrinfo what 127.0.0.1 means — a call of unbounded latency in front of a connection whose
destination was never in doubt. Anything inet_pton refuses still goes the long way, so 127.1 and
2130706433 are unchanged.
slate:dom can read a page
children(node), tagName(node), nodeText(node) and attribute(node, name). Every one of the
module's thirteen document names either made a node or changed one, so a framework adopting markup a
server rendered had nothing to walk it with.
A handle for an element the program never created is not a new kind of value — byId and query
have minted one since the module shipped — so this is the read side of an arrangement that already
existed. children answers every child node and not only the elements, because a text node between
two elements is a position; tagName answers null for one, which is how the two are told apart;
attribute answers true for a bare attribute, which is the reading setAttribute writes.
parent, the siblings and an innerHTML reader are deliberately absent: a page is walked downwards
from something the program already holds.
lath 0.3.0 is what this is for: hydrate(el, host)
adopts a server's markup instead of rebuilding it, and makes no DOM mutations at all — measured
with a MutationObserver rather than asserted.
A click says which button and which modifiers
mods — { meta, ctrl, shift, alt } — and button join type, value, checked, key, stop
and prevent on the record a handler is given.
A link cannot be written without them. A framework intercepting a click has to let a cmd-click, a
ctrl-click, a shift-click and a middle click through to the browser, and until now it could not tell
any of them from a plain click — so a router would have swallowed the most ordinary thing anybody
does to a link.
slate:url
percentDecode, encodeComponent, parseQuery and parsePairs, in a module of their own.
They were slate:http's, exported from it with a comment saying a framework over that module needs
the same decoder its router uses. That was true and it was not enough: the JavaScript back end
emits the whole of an imported module, so a browser page importing slate:http to reach two of
them went from 340,761 bytes to 579,710 — a file server and an HTTP/2 speaker downloaded to read a
query string.
slate:http imports them back and exports all four under their old names, so nothing written against
it changed. Import them from slate:url in anything that is not a server.
Also in this release
The OWED list is checked as three sets, which found five natives that were in neither the runtime
nor the list. A diagnostic about a function names it. slate:gzip, fetch, the ws client and the
calendar are all whole under slate js — see the parity
page.