Repository navigation
Description
Symptom
A course opened directly on a slide that has long block-macro expansions followed by a single- or multiple-choice quiz never leaves the loading screen in Chrome. Since LiaScript keeps the slide in the URL, reloading on that slide hangs too. Opened on an earlier slide, the course loads, but navigating to that slide shows it empty (no macro content, no quiz). The console shows:
Invalid regular expression: /^ …60856 spaces… /g: Regular expression too large
In our original course Safari loads the same slide (JavaScriptCore accepts the pattern); I haven't checked this reduced example in Safari.
Reproduction (no imports)
- Hangs: https://liascript.github.io/course/?https://raw.githubusercontent.com/glpython-edu/funktionen/debug/chrome-regex/materials/01-von-snap-reportern-zu-python-funktionen/debug/liascript-repro.md#2
- Loads (opened on slide 1, then → shows slide 2 empty): https://liascript.github.io/course/?https://raw.githubusercontent.com/glpython-edu/funktionen/debug/chrome-regex/materials/01-von-snap-reportern-zu-python-funktionen/debug/liascript-repro.md#1
- Loads (same course without the quiz): https://liascript.github.io/course/?https://raw.githubusercontent.com/glpython-edu/funktionen/debug/chrome-regex/materials/01-von-snap-reportern-zu-python-funktionen/debug/liascript-repro-no-quiz.md#2
Source: liascript-repro.md. A block macro @long (about 20,000 characters of HTML) is used three times on slide 2, followed by [( )] wrong / [(X)] right. The same happens with list-item options (- [(X)] …). With the macro used once, the slide loads.
Tested with Chrome 156 (macOS, and headless) on https://liascript.github.io/course/, 2026-11-01.
Cause
inject(Macro/Parser.elm L224–268) puts the expansion in front of the remaining input withmodifyInput(L264). In parser-combinators 7.1.0,modifyInput(Combine.elm L603–607) only replacesstream.input.stream.data, the original text, stays as it was, whilestream.positionkeeps counting through the expanded text.currentLocation(Combine.elm L531–547) measures line and column againststream.data. Onceposition > String.length data(the expansions are longer than the rest of the original text), it returns the overshoot as the column (L540–541). Here that's about 60,000. Before that point the column is measured against the wrong text too, just less visibly.- The choice-quiz
item(Quiz/Vector/Parser.elm L120–145) reads that column withwithColumn(L127) and pushes it as indentation:Indent.push (String.repeat (after - active) " ")(L137). - Every following line checks the indentation stack as a regex: Parser/Indentation.elm
indentationL52–65 →strictL69–71. V8 rejects regexes of 32,768 characters or more. It throws at the regex's first use, not when the regex is created, soRegex.fromStringreturnsJustand the exception escapes the parser. With one use of the macro (about 20,000 spaces) the slide still loads, with a wrong indentation; from about 32,768 it hangs.
Suggested fix
- The root is in parser-combinators: after
modifyInput(andputInput), the location functions measure against text the parser never saw. Keepingdataequal to the consumed text plus the new input would fix lines and columns after macro expansion, e.g.data = String.left position data ++ f inputinmodifyInput. I'll report that there too. - In LiaScript, independently:
itemcould take the indentation from what it just matched (the leading whitespace plus the marker) instead of the absolute column. Then it doesn't depend on the stream's location bookkeeping.
Catching the regex exception alone would only hide the wrong indentation.
Workaround
We keep macro expansions short: glpython-liascript moved its shared code from every block into @onload (glpython-edu/glpython-liascript#23), so each expansion went from about 37,000 to about 3,000 characters.
Activity
andre-dietrich commentedon Nov 1, 2026
Thank you for the detailed bug report ... and it has been fixed as a hotfix on liascript.github.io, but not on the editor plugins ... I will update this during the week with a couple of other improvements ... So it works online but not yet offline ;-)
a4b1c4b