Skip to content

Send the first program once the block's editor has its text - #32

Merged
cedricvogel-leo merged 1 commit into
mainfrom
fix/wait-for-editor-text
Nov 6, 2026
Merged

cedricvogel-leo merged 1 commit into
mainfrom
fix/wait-for-editor-text

Conversation

@cedricvogel-leo

Copy link
Copy Markdown
Collaborator

A visualization in a LiaScript fragment sometimes started empty: «Keine Schritte aufgezeichnet», with no step buttons. It happened in presentation mode, once the embed was in the browser cache.

Cause. A race in the macro, not in the embed:

  • When a fragment appears, LiaScript creates the block's editor and the embed's iframe together. The iframe is loading="lazy", so nothing runs while the fragment is hidden.
  • LiaScript fills the editor 10–100 ms later. Its lia-editor waits for its Ace editor before it takes the text.
  • A cached embed says ready within 1–20 ms of being created. The macro then read the editor at once and sent an empty program.

One failing visit (ms, course page clock):

ms
fragment shown, iframe and editor created 30740
ready, program read: 0 characters 30741
editor gets its 124 characters 30758

Fix. On ready, while all of the block's editors are still empty, the first program waits for their text, then goes out at once. It's the same path for load and visualize.

  • Signal: Ace's change event, via element.env.editor. LiaScript blocks its own editorUpdate while it sets the text itself. For an editor that isn't connected yet, attach() checks again on each DOM change.
  • Fallback: after 2 s the program goes out anyway, since a block may be empty on purpose.
  • Nothing else waits: ▶, «Tests» and the REPL work right after ready. A program sent meanwhile carries the block as it is then, and the first one is dropped.
  • Several files: it only waits while every file is empty. One empty file among others doesn't wait.

Checks.

  • npm run check:ready (new, in CI): runs the macro's @onload code on a test page, with a stand-in lia-editor that gets its text only after ready and a stub embed. Everything is served through Playwright routes, with no external sites. Cases:

    • text 300 ms after ready: sent when it arrives;
    • text already there: sent right away;
    • a block that stays empty: sent after 2 s;
    • several files, one empty: no wait;
    • ▶ and «Tests» during the wait: sent at once, and the first program is dropped.

    On main's macro, 4 of the 6 cases fail.

  • npm run check:player [visits] (new, not in CI): the real LiaScript player and the live embed, with scripts/player/course.md (a visualization inside {{1}}), visited several times. Run it before macro releases.

    • On main's macro: 2 of 4 visits empty.
    • With the fix: 13 of 13 visits filled over two runs. Separately, your course's slides 6 and 4, with this macro served in place of the import, were filled on every visit (4 of 4 and 3 of 3). Without the fix, every visit after the first was empty.
    • In one earlier run, the visualizer didn't appear within 60 s on one visit, although the full program had arrived. It didn't happen again in the 13 visits. The script may be flaky on slow loads, which is another reason to keep it out of CI.
  • check-macro passes.

The repo gets a package.json with playwright-core (devDependency) for both scripts, and CI runs npm ci.

Going live. Merging reaches courses at once; then a patch version bump per course. Public behaviour:

  • Unchanged: buttons, messages, protocol, options.
  • Timing: a block whose code is still empty sends its first program once the text arrives. A block that stays empty sends it after 2 s instead of at once.
  • Order: if the learner clicks ▶ or «Tests» before the text arrives, the embed gets only that program, not the earlier load as well. The result is the same.

Manual test. In presentation mode, open slide 5 of a course with a visualization in a fragment on slide 6. Go to 6, show the fragment, go back to 5 and repeat. The program shows every time, also in a warm tab.

🤖 Generated with Claude Code

In a fragment, LiaScript creates the editor and the iframe together and
fills the editor a few milliseconds later; a cached embed's "ready" came
first, so a visualization started empty. While all of the block's editors
are empty, the first program now waits for Ace's change event (at most
2 s); anything sent meanwhile replaces it. check:ready (CI) covers it on a
test page with a stand-in editor; check:player (not in CI) with the real
LiaScript player.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cedricvogel-leo
cedricvogel-leo merged commit c9c2c12 into main Nov 6, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant