Context
Bytecode and %DebugPrint dumps are the point of jslab, and they are unreadable
to the people most likely to be learning from them. The built-in opcode
reference explains what LdaSmi does in general; it cannot say why this line
matters in this snippet — that an elements kind just went from packed to
holey, or that the second Star is where a closure captures its variable.
Today that explanation has nowhere to live. It ends up in ordinary //
comments next to the code, where the reader has to map it onto the right line
of the dump themselves, or outside the tool entirely — in the article, the
lesson, or the chat message the link was pasted into. None of it survives the
link being shared onward, which is exactly when the explanation is needed most.
Proposal
An @annotation comment in the snippet attaches an explanation to matching text
in the engine output. The matched fragment gets a highlight; clicking it opens
the explanation.
/* @annotation
match: elements kind: HOLEY_SMI_ELEMENTS
highlight: HOLEY_SMI_ELEMENTS
title: PACKED_SMI_ELEMENTS → HOLEY_SMI_ELEMENTS
text: |
Growing length creates the missing indexes 3–9.
V8 therefore switches the array representation from packed to holey.
*/
arr.length = 10;
%DebugPrint(arr);
Why in the source rather than in the UI. The snippet is already the unit
that gets shared, saved and embedded. Keeping the explanations in a comment
means they travel with the code through share links, /embed/bytecode and the
sample catalog with no extra plumbing, and they can be reviewed in a diff like
any other code. It also means the author of an example — not the site — decides
what is worth explaining.
Directive format, one block per rule:
| Field |
Meaning |
match |
Required. Exact text to look for; case, whitespace and punctuation count. |
text |
Required. The explanation, as plain text. |
highlight |
Optional substring of match to underline. Must occur inside match exactly once. |
title |
Optional heading; defaults to the highlighted text. |
occurrence |
all (default) or a match number starting at 1, per output channel. |
text: | keeps line breaks and strips the common indent. Values are literal
text — Markdown and HTML are not interpreted.
Design constraints worth stating, because they rule out simpler designs:
- The raw output is never modified. Copy still yields exactly what the
engine printed; annotations are a rendering layer over unchanged text.
- Matching is literal, not regex. An annotation cannot quietly start
matching something else after an engine upgrade.
- A rule that matches nothing is normal, not an error. One snippet runs on
four engines that print different text, and stdout/stderr are matched
separately.
- Mistakes in the directives are reported. An unknown field, an empty
match, a highlight that is not inside match — each surfaces as a warning
next to the output, so a typo does not fail silently as "no highlight".
Acceptance criteria
- An
@annotation block in a snippet highlights the matching output fragment on
every engine that prints it, and the explanation opens on click and on Enter.
- Directive errors are shown next to the output with the source line number.
- The raw output and the Copy button are byte-identical to the un-annotated run.
- Annotations survive a share link and a
/embed/bytecode snapshot.
- In diff mode, rules apply to the current run's rows only.
Related
Gives #35 (Learn section) its mechanism: an explainer can embed a live run whose
output explains itself, instead of pairing a screenshot with prose that drifts
out of sync with the engine.
Context
Bytecode and
%DebugPrintdumps are the point of jslab, and they are unreadableto the people most likely to be learning from them. The built-in opcode
reference explains what
LdaSmidoes in general; it cannot say why this linematters in this snippet — that an elements kind just went from packed to
holey, or that the second
Staris where a closure captures its variable.Today that explanation has nowhere to live. It ends up in ordinary
//comments next to the code, where the reader has to map it onto the right line
of the dump themselves, or outside the tool entirely — in the article, the
lesson, or the chat message the link was pasted into. None of it survives the
link being shared onward, which is exactly when the explanation is needed most.
Proposal
An
@annotationcomment in the snippet attaches an explanation to matching textin the engine output. The matched fragment gets a highlight; clicking it opens
the explanation.
Why in the source rather than in the UI. The snippet is already the unit
that gets shared, saved and embedded. Keeping the explanations in a comment
means they travel with the code through share links,
/embed/bytecodeand thesample catalog with no extra plumbing, and they can be reviewed in a diff like
any other code. It also means the author of an example — not the site — decides
what is worth explaining.
Directive format, one block per rule:
matchtexthighlightmatchto underline. Must occur insidematchexactly once.titleoccurrenceall(default) or a match number starting at1, per output channel.text: |keeps line breaks and strips the common indent. Values are literaltext — Markdown and HTML are not interpreted.
Design constraints worth stating, because they rule out simpler designs:
engine printed; annotations are a rendering layer over unchanged text.
matching something else after an engine upgrade.
four engines that print different text, and stdout/stderr are matched
separately.
match, ahighlightthat is not insidematch— each surfaces as a warningnext to the output, so a typo does not fail silently as "no highlight".
Acceptance criteria
@annotationblock in a snippet highlights the matching output fragment onevery engine that prints it, and the explanation opens on click and on Enter.
/embed/bytecodesnapshot.Related
Gives #35 (Learn section) its mechanism: an explainer can embed a live run whose
output explains itself, instead of pairing a screenshot with prose that drifts
out of sync with the engine.