Crash when accessing the field 'data' of a whatsit(write) node

I’m the maintainer of the nodetree package. I got a bug report: https://github.com/Josef-Friedrich/nodetree/issues/46 I was able to narrow down the problem: debug.tex: \documentclass{article} \begin{document} \directlua{ luatexbase.add_to_callback('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then local tmp = head.data end return true end, 'debug' ) } \begin{figure} \caption{test} \end{figure} \end{document} lualatex debug.tex: ! Incomplete \iffalse; all text was ignored after line 19. <inserted text> \fi l.19 \end{figure} The line 'local tmp = head.data' causes the error. I tried also 'print(head.data)' or 'local tmp = head['data']'. These access types also caused a crash. Access to fields other than data works without any problems. print(head.stream) print(head.id) print(head.xxx) Is this a bug in LuaTeX? Or how can I access the field 'data' of a whatsit(write) node for debugging purposes?

On Sat, 17 May 2025 at 13:02, Josef Friedrich
I’m the maintainer of the nodetree package. I got a bug report: https://github.com/Josef-Friedrich/nodetree/issues/46 I was able to narrow down the problem:
debug.tex:
\documentclass{article} \begin{document} \directlua{ luatexbase.add_to_callback('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then local tmp = head.data end return true end, 'debug' ) } \begin{figure} \caption{test} \end{figure} \end{document}
lualatex debug.tex:
! Incomplete \iffalse; all text was ignored after line 19. <inserted text> \fi l.19 \end{figure}
The line 'local tmp = head.data' causes the error. I tried also 'print(head.data)' or 'local tmp = head['data']'. These access types also caused a crash.
Access to fields other than data works without any problems.
print(head.stream) print(head.id) print(head.xxx)
Is this a bug in LuaTeX? Or how can I access the field 'data' of a whatsit(write) node for debugging purposes?
hm I see the ! Incomplete \iffalse; line, but no crash LuaTeX, Version 1.23.1 (TeX Live 2026/dev) Development id: 7679 -- luigi

I think it is a bug. Luatex tries to expand data field content like with \edef thats why you get \iffalse. With older texlive (v0.76) the same example prints: table: 03420800 table: 034212F0 table: 03421318 \documentclass{article} \begin{document} \directlua{ callback.register('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then print (head.data) end return true end, 'debug' ) } \begin{figure} \caption{test} \end{figure} \end{document} On 5/17/2025 1:54 PM, Josef Friedrich wrote:
I’m the maintainer of the nodetree package. I got a bug report: https://github.com/Josef-Friedrich/nodetree/issues/46 I was able to narrow down the problem:
debug.tex:
\documentclass{article} \begin{document} \directlua{ luatexbase.add_to_callback('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then local tmp = head.data end return true end, 'debug' ) } \begin{figure} \caption{test} \end{figure} \end{document}
lualatex debug.tex:
! Incomplete \iffalse; all text was ignored after line 19. <inserted text> \fi l.19 \end{figure}
The line 'local tmp = head.data' causes the error. I tried also 'print(head.data)' or 'local tmp = head['data']'. These access types also caused a crash.
Access to fields other than data works without any problems.
print(head.stream) print(head.id) print(head.xxx)
Is this a bug in LuaTeX? Or how can I access the field 'data' of a whatsit(write) node for debugging purposes?
_______________________________________________ dev-luatex mailing list -- dev-luatex@ntg.nl To unsubscribe send an email to dev-luatex-leave@ntg.nl

On 5/27/2025 7:23 AM, Linas Stonys wrote:
I think it is a bug. Luatex tries to expand data field content like with \edef thats why you get \iffalse. With older texlive (v0.76) the same example prints:
we now have luatex 1.12 so that is indeed old ... way too old to bother about here
table: 03420800 table: 034212F0 table: 03421318
\documentclass{article} \begin{document} \directlua{ callback.register('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then print (head.data) end return true end, 'debug' ) } \begin{figure} \caption{test} \end{figure} \end{document}
On 5/17/2025 1:54 PM, Josef Friedrich wrote:
I’m the maintainer of the nodetree package. I got a bug report: https://github.com/Josef-Friedrich/nodetree/issues/46 I was able to narrow down the problem:
debug.tex:
\documentclass{article} \begin{document} \directlua{ luatexbase.add_to_callback('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then local tmp = head.data end return true end, 'debug' ) } \begin{figure} \caption{test} \end{figure} \end{document}
lualatex debug.tex:
! Incomplete \iffalse; all text was ignored after line 19. <inserted text> \fi l.19 \end{figure} The line 'local tmp = head.data' causes the error. I tried also 'print(head.data)' or 'local tmp = head['data']'. These access types also caused a crash.
Access to fields other than data works without any problems.
print(head.stream) print(head.id) print(head.xxx)
Is this a bug in LuaTeX? Or how can I access the field 'data' of a whatsit(write) node for debugging purposes?
A tex error is not a crash and normally not a bug either. I suggest you look into what the "data" field gets set to which is unclear from your example. \directlua{ callback.register('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then print(head.data) end return true end) } \def\hello{\iftrue true\else false\fi} \def\world{\iftrue true\else false\fi} \protected\def\HELLO{\iftrue TRUE\else FALSE\fi} \protected\def\WORLD{\iftrue TRUE\else FALSE\fi} \noindent \directlua{ local n = node.new("whatsit",1) n.data = [[(\hello\world)(\HELLO\WORLD)]] print(n.data) tex.print(n) } test test test \bye So maybe use \tracingall in your latex example code to get an idea what is going on? Hans ----------------------------------------------------------------- Hans Hagen | PRAGMA ADE Ridderstraat 27 | 8061 GH Hasselt | The Netherlands tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl -----------------------------------------------------------------

Dear Hans, Luigi, Linays! First of all, thank you very much for your help! I have looked into the problem again more intensively and was able to find out a little more. I have encountered the error with LuaTeX Version 1.18.0 (7611) and Version 1.22.0 (7673) When I try to access the data field of this node, the described error occurs: │ ├─WHATSIT (write) stream 1, data '\@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5em\relax \rightskip 2.55em\parfillskip -\rightskip \parindent 1.5em\relax \let \interlinepenalty \@M \unhbox \voidb@x \@tempdima 2.3em\relax \advance \leftskip \@tempdima \hbox {}\protect \penalty \@M \hskip -\leftskip {\protect \hbox to\@tempdima {1\hfil }{\ignorespaces test}}\protect \penalty \@M \leaders \hbox {$\mathsurround \z@ \mkern 4.5mu\hbox {.}\mkern 4.5mu$}\hfill \protect \penalty \@M \hbox to1.55em{\hfil \protect \protect \edef TU{TU}\let \enc@update \relax \edef lmr{lmr}\edef m{m}\edef n{n}\let \protect \let }}}' Please note that this is purely read-only access. I have the impression that the data field can only be accessed once? That the node can no longer be used by internal algorithms after accessing the data field? I modified my debug document slightly. Now it uses my nodetree package \documentclass{article} \begin{document} \directlua{ local nodetree = require('nodetree') luatexbase.add_to_callback('vpack_filter', function(head) nodetree.print(head) end, 'debug' ) } \begin{figure} \caption{test} \end{figure} test \end{document} The compilation stops and when I press ENTER a few times, nodetree can finally render the debug node tree view. lualatex debug.tex: This is LuaHBTeX, Version 1.22.0 (TeX Live 2025) restricted system commands enabled. (./debug.tex LaTeX2e <2024-11-01> patch level 2 L3 programming layer <2025-04-29> (/usr/local/texlive/texmf-dist/tex/latex/base/article.cls Document Class: article 2024/06/29 v1.4n Standard LaTeX document class (/usr/local/texlive/texmf-dist/tex/latex/base/size10.clo)) (/usr/local/texlive/texmf-dist/tex/latex/l3backend/l3backend-luatex.def) (./debug.aux) ! Incomplete \iffalse; all text was ignored after line 14. <inserted text> \fi l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? ! Incomplete \iffalse; all text was ignored after line 14. <inserted text> \fi l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? ! Incomplete \iffalse; all text was ignored after line 14. <inserted text> \fi l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? ! Incomplete \iffalse; all text was ignored after line 14. <inserted text> \fi l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? ! Incomplete \iffalse; all text was ignored after line 14. <inserted text> \fi l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? Runaway text? \@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5\ETC. ! Forbidden control sequence found while scanning text of \write. <inserted text> } l.14 \end{figure} ? ├─WHATSIT (write) stream 1, data '\@writefile{lof}{\protect \gdef {}\vskip \z@ plus.2\p@ {\leftskip 1.5em\relax \rightskip 2.55em\parfillskip -\rightskip \parindent 1.5em\relax \let \interlinepenalty \@M \unhbox \voidb@x \@tempdima 2.3em\relax \advance \leftskip \@tempdima \hbox {}\protect \penalty \@M \hskip -\leftskip {\protect \hbox to\@tempdima {1\hfil }{\ignorespaces test}}\protect \penalty \@M \leaders \hbox {$\mathsurround \z@ \mkern 4.5mu\hbox {.}\mkern 4.5mu$}\hfill \protect \penalty \@M \hbox to1.55em{\hfil \protect \protect \edef TU{TU}\let \enc@update \relax \edef lmr{lmr}\edef m{m}\edef n{n}\let \protect \let }}}' ├─GLUE (userskip) wd 10pt ├─HLIST (box) wd 345pt, dp 2.06pt, ht 6.8pt │ ╚═head │ ├─GLUE (userskip) plus +1fil │ ├─HLIST (box) wd 59.94pt, dp 2.06pt, ht 6.8pt │ │ ╚═head │ │ ├─GLYPH (glyph) 'F', font 15, wd 6.53pt, ht 6.8pt │ │ ├─GLYPH (glyph) 'i', font 15, wd 2.78pt, ht 6.57pt │ │ ├─GLYPH (glyph) 'g', font 15, wd 5pt, ht 4.53pt, dp 2.06pt │ │ ├─DISC (regular) penalty 50 │ │ │ ╚═pre │ │ │ └─GLYPH (glyph) '-', font 15, wd 3.33pt, ht 2.45pt │ │ ├─GLYPH (glyph) 'u', font 15, wd 5.56pt, ht 4.42pt, dp 0.11pt │ │ ├─GLYPH (glyph) 'r', font 15, wd 3.92pt, ht 4.42pt │ │ ├─GLYPH (glyph) 'e', font 15, wd 4.44pt, ht 4.48pt, dp 0.11pt │ │ ├─PENALTY (userpenalty) 10000 │ │ ├─GLUE (spaceskip) wd 3.33pt, plus 1.66pt, minus 1.11pt │ │ ├─GLYPH (glyph) '1', font 15, wd 5pt, ht 6.66pt │ │ ├─GLYPH (glyph) ':', font 15, wd 2.78pt, ht 4.31pt │ │ ├─GLUE (spaceskip) wd 4.44pt, plus 3.33pt, minus 0.55pt │ │ ├─GLYPH (glyph) 't', font 15, wd 3.89pt, ht 6.15pt, dp 0.11pt │ │ ├─GLYPH (glyph) 'e', font 15, wd 4.44pt, ht 4.48pt, dp 0.11pt │ │ ├─GLYPH (glyph) 's', font 15, wd 3.94pt, ht 4.48pt, dp 0.11pt │ │ └─GLYPH (glyph) 't', font 15, wd 3.89pt, ht 6.15pt, dp 0.11pt │ └─GLUE (userskip) plus +1fil ├─GLUE (userskip) └─GLUE (userskip) └─VLIST (unknown) └─WHATSIT (write) stream 129, data '' ├─VLIST (unknown) └─GLUE (userskip) wd 12pt, plus 2pt, minus 2pt ├─GLUE (userskip) wd -12pt, plus -2pt, minus -2pt ├─GLUE (userskip) wd 20pt, plus 2pt, minus 4pt ├─GLUE (topskip) wd 3.85pt ├─HLIST (line) wd 345pt, dp 0.11pt, ht 6.15pt │ ╚═head │ ├─LOCAL_PAR │ ├─HLIST (indent) wd 15pt │ ├─GLYPH (glyph) 't', font 15, wd 3.89pt, ht 6.15pt, dp 0.11pt │ ├─GLYPH (glyph) 'e', font 15, wd 4.44pt, ht 4.48pt, dp 0.11pt │ ├─GLYPH (glyph) 's', font 15, wd 3.94pt, ht 4.48pt, dp 0.11pt │ ├─GLYPH (glyph) 't', font 15, wd 3.89pt, ht 6.15pt, dp 0.11pt │ ├─PENALTY (linepenalty) 10000 │ ├─GLUE (parfillskip) plus +1fil │ └─GLUE (rightskip) ├─GLUE (userskip) wd -0.11pt └─GLUE (userskip) plus +1fil ├─GLUE (userskip) └─GLUE (userskip) plus +0.000106812fil ├─GLUE (userskip) plus +1fil └─HLIST (box) wd 345pt ╚═head └─HLIST (box) wd 345pt ├─VLIST (unknown) ht 12pt ├─GLUE (userskip) wd 25pt ├─GLUE (lineskip) ├─VLIST (unknown) ht 550pt ├─GLUE (baselineskip) wd 23.34pt └─HLIST (box) wd 345pt, ht 6.66pt ╚═head └─HLIST (box) wd 345pt, ht 6.66pt ╚═head ├─GLUE (userskip) plus +1fil ├─GLYPH (glyph) '1', font 15, wd 5pt, ht 6.66pt └─GLUE (userskip) plus +1fil ├─GLUE (userskip) wd 16pt └─VLIST (unknown) shift 62pt [1] ├─GLUE (splittopskip) wd 10pt └─VLIST (unknown) └─WHATSIT (write) stream 129, data '' (./debug.aux)) (\end occurred when \iftrue on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) (\end occurred when \if on line 14 was incomplete) 898 words of node memory still in use: 10 hlist, 6 vlist, 1 rule, 1 disc, 1 local_par, 25 glue, 3 kern, 2 penalty, 19 glyph, 21 attribute, 48 glue_spec, 21 attribute_list, 3 write nodes avail lists: 2:21,3:1,4:1,5:31,7:1,9:2 Output written on debug.pdf (1 page, 888 bytes). Transcript written on debug.log. On 27.05.25 12:02, Hans Hagen wrote:
On 5/27/2025 7:23 AM, Linas Stonys wrote:
I think it is a bug. Luatex tries to expand data field content like with \edef thats why you get \iffalse. With older texlive (v0.76) the same example prints:
we now have luatex 1.12 so that is indeed old ... way too old to bother about here
table: 03420800 table: 034212F0 table: 03421318
\documentclass{article} \begin{document} \directlua{ callback.register('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then print (head.data) end return true end, 'debug' ) } \begin{figure} \caption{test} \end{figure} \end{document}
On 5/17/2025 1:54 PM, Josef Friedrich wrote:
I’m the maintainer of the nodetree package. I got a bug report: https://github.com/Josef-Friedrich/nodetree/issues/46 I was able to narrow down the problem:
debug.tex:
\documentclass{article} \begin{document} \directlua{ luatexbase.add_to_callback('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then local tmp = head.data end return true end, 'debug' ) } \begin{figure} \caption{test} \end{figure} \end{document}
lualatex debug.tex:
! Incomplete \iffalse; all text was ignored after line 19. <inserted text> \fi l.19 \end{figure} The line 'local tmp = head.data' causes the error. I tried also 'print(head.data)' or 'local tmp = head['data']'. These access types also caused a crash.
Access to fields other than data works without any problems.
print(head.stream) print(head.id) print(head.xxx)
Is this a bug in LuaTeX? Or how can I access the field 'data' of a whatsit(write) node for debugging purposes?
A tex error is not a crash and normally not a bug either. I suggest you look into what the "data" field gets set to which is unclear from your example.
Unfortunately I don't know how the data field of this particular node was set by LaTeX. I only know that this is related to the \caption macro. I have tried to reproduce the error artificially without LaTeX, but without success.
\directlua{ callback.register('vpack_filter', function(head) if node.type(head.id) == 'whatsit' and head.subtype == 1 then print(head.data) end return true end) }
\def\hello{\iftrue true\else false\fi} \def\world{\iftrue true\else false\fi} \protected\def\HELLO{\iftrue TRUE\else FALSE\fi} \protected\def\WORLD{\iftrue TRUE\else FALSE\fi}
\noindent \directlua{ local n = node.new("whatsit",1) n.data = [[(\hello\world)(\HELLO\WORLD)]] print(n.data) tex.print(n) } test test test
\bye
Thanks for the example. I can confirm that it compiles without errors.
So maybe use \tracingall in your latex example code to get an idea what is going on?
I have tried \tracingall, but I am overwhelmed by its verbosity. Here are a few lines before the error occurs ~........\selectfont ->\protect \selectfont ~........\selectfont ->\ifx \f@linespread \baselinestretch \else \set@fontsize \baselinestretch \f@size \f@baselineskip \fi \ifx \delayed@f@adjustment \@empt y \else \let \f@shape@saved \f@shape \let \f@series@saved \f@series \delayed@f@ adjustment \maybe@load@fontshape \ifcsname \f@encoding /\f@family /\f@series /\ f@shape \endcsname \else \let \f@shape \f@shape@saved \let \f@series \f@series@ saved \let \delayed@merge@font@shape \merge@font@shape \let \delayed@merge@font @series \merge@font@series \delayed@f@adjustment \let \delayed@merge@font@shape \merge@font@shape@without@substitution \let \delayed@merge@font@series \merge@ font@series@without@substitution \fi \let \delayed@f@adjustment \@empty \fi \@f orced@seriesfalse \xdef \font@name {\csname \curr@fontshape /\f@size \endcsname }\pickup@font \font@name \UseHook {selectfont}\size@update \enc@update {\ifx: (level 4) entered on line 17} {true} {\else: \ifx (level 4) entered on line 17} {\fi: \ifx (level 4) entered on line 17} {\ifx: (level 4) entered on line 17} {true} {\else: \ifx (level 4) entered on line 17} {\fi: \ifx (level 4) entered on line 17} ~........\@forced@seriesfalse ->\let \if@forced@series \iffalse {\iffalse: (level 4) entered on line 17} {false} ! Incomplete \iffalse; all text was ignored after line 17. <inserted text> \fi <to be read again> \endwrite <inserted text> }\endwrite \@endfloatbox ...pagefalse \outer@nobreak \egroup \color@endbox \end@float ->\@endfloatbox \ifnum \@floatpenalty <\z@ \@largefloatcheck \@co... \end ...ook {env/#1/end}}\csname end#1\endcsname \@checkend {#1}\endgroup \... l.17 \end{figure} ? ! Emergency stop. <inserted text> \fi <to be read again> \endwrite <inserted text> }\endwrite \@endfloatbox ...pagefalse \outer@nobreak \egroup \color@endbox \end@float ->\@endfloatbox \ifnum \@floatpenalty <\z@ \@largefloatcheck \@co... \end ...ook {env/#1/end}}\csname end#1\endcsname \@checkend {#1}\endgroup \... l.17 \end{figure} Thanks Josef
Hans
----------------------------------------------------------------- Hans Hagen | PRAGMA ADE Ridderstraat 27 | 8061 GH Hasselt | The Netherlands tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl ----------------------------------------------------------------- _______________________________________________ dev-luatex mailing list -- dev-luatex@ntg.nl To unsubscribe send an email to dev-luatex-leave@ntg.nl

If I understood correct this was changed in 1.09.2 version -const char *luatex_version_string = “1.09.2”; +const char *luatex_version_string = “1.09.0"; In file lnodelib.c function get_write_direct_value started to expand tokens: -#define get_write_direct_value(L,n) do { \ +#define xget_write_direct_value(L,n) do { \ tokenlist_to_lua(L, write_tokens(n)); \ } while (0) +#define get_write_direct_value(L,n) do { \ + int l; \ + char *s; \ + expand_macros_in_tokenlist(n); \ + s = tokenlist_to_cstring(def_ref, 1, &l); \ + lua_pushlstring(L, s, (size_t) l); \ + free(s); \ + flush_list(def_ref); \ +} while (0) + Sourcehttps://github.com/TeX-Live/texlive-source.git https://github.com/TeX-Live/texlive-source.git What was the reason for this change I have no idea. We have reverted back this change in our compiled luatex because constantly playing with nodes reading we get issues with the "write" node. On 5/27/2025 1:02 PM, Hans Hagen wrote:
On 5/27/2025 7:23 AM, Linas Stonys wrote:
I think it is a bug. Luatex tries to expand data field content like with \edef thats why you get \iffalse. With older texlive (v0.76) the same example prints:
we now have luatex 1.12 so that is indeed old ... way too old to bother about here

On 5/30/2025 7:30 AM, Linas Stonys wrote:
If I understood correct this was changed in 1.09.2 version -const char *luatex_version_string = “1.09.2”; +const char *luatex_version_string = “1.09.0";
In file lnodelib.c function get_write_direct_value started to expand tokens:
-#define get_write_direct_value(L,n) do { \ +#define xget_write_direct_value(L,n) do { \ tokenlist_to_lua(L, write_tokens(n)); \ } while (0)
+#define get_write_direct_value(L,n) do { \ + int l; \ + char *s; \ + expand_macros_in_tokenlist(n); \ + s = tokenlist_to_cstring(def_ref, 1, &l); \ + lua_pushlstring(L, s, (size_t) l); \ + free(s); \ + flush_list(def_ref); \ +} while (0) +
Sourcehttps://github.com/TeX-Live/texlive-source.git
What was the reason for this change I have no idea. We have reverted back this change in our compiled luatex because constantly playing with nodes reading we get issues with the "write" node.
consistency with what write does when it writes data (also, returning a token list as lua table and then expecting that to get expanded explicitly otherwise is not that efficient) we can consider adding getfield(w,"rawdata") for write and special whatsits (maybe tl 2026); the current "data" access with expansion is not a bug and it won't change
On 5/27/2025 1:02 PM, Hans Hagen wrote:
On 5/27/2025 7:23 AM, Linas Stonys wrote:
I think it is a bug. Luatex tries to expand data field content like with \edef thats why you get \iffalse. With older texlive (v0.76) the same example prints:
we now have luatex 1.12 so that is indeed old ... way too old to bother about here
_______________________________________________ dev-luatex mailing list -- dev-luatex@ntg.nl To unsubscribe send an email to dev-luatex-leave@ntg.nl
-- ----------------------------------------------------------------- Hans Hagen | PRAGMA ADE Ridderstraat 27 | 8061 GH Hasselt | The Netherlands tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl -----------------------------------------------------------------

On 5/30/2025 10:24 AM, Linas Stonys wrote:
we can consider adding getfield(w,"rawdata") for write and special whatsits (maybe tl 2026); the current "data" access with expansion is not a bug and it won't change
Sounds very well! So write node will have fields: attr, stream, data, *rawdata. * thanks a lot!
actually "value" as we already have that as keyword elsewhere .. btw, we're talking tl 2026 here because we don't update such things between releases but it might end up in intermediate versions Hans ----------------------------------------------------------------- Hans Hagen | PRAGMA ADE Ridderstraat 27 | 8061 GH Hasselt | The Netherlands tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl -----------------------------------------------------------------

life is running so fast that change in TL2026 sounds legit. On 5/30/2025 11:38 AM, Hans Hagen wrote:
On 5/30/2025 10:24 AM, Linas Stonys wrote:
we can consider adding getfield(w,"rawdata") for write and special whatsits (maybe tl 2026); the current "data" access with expansion is not a bug and it won't change
Sounds very well! So write node will have fields: attr, stream, data, *rawdata. * thanks a lot!
actually "value" as we already have that as keyword elsewhere .. btw, we're talking tl 2026 here because we don't update such things between releases but it might end up in intermediate versions
Hans
----------------------------------------------------------------- Hans Hagen | PRAGMA ADE Ridderstraat 27 | 8061 GH Hasselt | The Netherlands tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl ----------------------------------------------------------------- _______________________________________________ dev-luatex mailing list -- dev-luatex@ntg.nl To unsubscribe send an email to dev-luatex-leave@ntg.nl

On Fri, 30 May 2025 at 10:45, Linas Stonys
life is running so fast that change in TL2026 sounds legit.
Just pushed in https://gitlab.lisn.upsaclay.fr/texlive/luatex.git
commit ea28673465c4d9445bbb582ccdb5dbea75cafc19 (HEAD -> master,
origin/master, origin/HEAD)
Author: Luigi Scarso

First of all, thank you for the new `value` field for `write` whatsit nodes! So that I have understood it correctly: A debugging package such as nodetree must not access the `data` field, as access to the `data` field expands the token list, which may cause in some circumstances the document to stop compiling? Access to the new value field is safe as it does not expand? I have compiled the latest LuaTeX with the lastet commit from Luigi and tried to test the new `value` field. \def\hello{\iftrue true\else false\fi} \def\world{\iftrue true\else false\fi} \protected\def\HELLO{\iftrue TRUE\else FALSE\fi} \protected\def\WORLD{\iftrue TRUE\else FALSE\fi} \noindent \directlua{ local n = node.new("whatsit",1) n.data = [[(\hello\world)(\HELLO\WORLD)]] local output = '' for index, token in pairs(n.value) do output = output .. string.char(token[2]) end print(output) } test This is LuaTeX, Version 1.23.2 (TeX Live 2026/dev) restricted system commands enabled. (./hans.tex(truetrue)(\HELLO \WORLD ) [1{/usr/local/texlive/2025/texmf-var/fonts/map/pdftex/updmap/pdftex .map}]) Instead of the output ‘(truetrue)(\HELLO \WORLD )’ I would have expected ‘(\hello\world)(\HELLO\WORLD)’? I also noticed the following: I think the field `value` would still have to be entered in the file `texnodes.c` so that the `node.fields()` function can output it. ```tex \directlua{ for index, field in pairs(node.fields(node.id('whatsit'), 1)) do print(field) end } `` diff --git a/source/texk/web2c/luatexdir/tex/texnodes.c b/source/texk/web2c/luatexdir/tex/texnodes.c index 47eda07cb..0c8275d10 100644 --- a/source/texk/web2c/luatexdir/tex/texnodes.c +++ b/source/texk/web2c/luatexdir/tex/texnodes.c @@ -1049,7 +1049,8 @@ void l_set_whatsit_data(void) { init_field_key(node_fields_whatsit_write, 0, attr); init_field_key(node_fields_whatsit_write, 1, stream); init_field_key(node_fields_whatsit_write, 2, data); - init_field_nop(node_fields_whatsit_write, 3); + init_field_key(node_fields_whatsit_write, 3, value); + init_field_nop(node_fields_whatsit_write, 4); init_node_key(whatsit_node_data, pdf_literal_node, pdf_literal) init_node_key(whatsit_node_data, pdf_late_literal_node,pdf_late_literal) Josef On 30.05.25 16:17, luigi scarso wrote:
On Fri, 30 May 2025 at 10:45, Linas Stonys
mailto:lstonys@vtex.lt> wrote: life is running so fast that change in TL2026 sounds legit.
Just pushed in https://gitlab.lisn.upsaclay.fr/texlive/luatex.git https://gitlab.lisn.upsaclay.fr/texlive/luatex.git
commit ea28673465c4d9445bbb582ccdb5dbea75cafc19 (HEAD -> master, origin/master, origin/HEAD) Author: Luigi Scarso
mailto:luigi.scarso@gmail.com> Date: Fri May 30 16:07:24 2025 +0200 Additional 'value' field for write nodes (getfield) for unexpanded token tables (H.Hagen). LaTeX 1.23.2
-- luigi
_______________________________________________ dev-luatex mailing list -- dev-luatex@ntg.nl To unsubscribe send an email to dev-luatex-leave@ntg.nl
participants (4)
-
Hans Hagen
-
Josef Friedrich
-
Linas Stonys
-
luigi scarso