I’m using swipl compiled as a WASM package, that I include in a js project. I was getting this error:
01f4a08e:0xe351e [FATAL ERROR: at Fri Aug 8 08:57:17 2025
01f4a08e:0xe351e Too many stacked strings]
and I narrowed it down to a memory leak in the prolog.query
function. Here is some reproduction and some thoughts.
Minimal reproduction:
say(Thing) :-
format(string(Command), `console.log("~w")`, [Thing]),
js_run_script(Command).
adhoc(Result) :-
findall(_{id: X, label:'some_long_label'}, between(1, 100000, X), Result),
say(Result),
say('adhoc').
On the javascript side, this is called as:
<button
class=“button”
onclick={() => {
let r = prolog.query(‘adhoc(Rs)’).once();
console.log(r);
}}>ad hoc</button>
The code I just posted doesn’t work, and it results in the Too many stacked strings
error after 4 times you press the adhoc button. Or, if you increase the number to 400000
, in just 1 press.
Now, I understand there could be an overall limit in the strings you transfer, but I doubt this should be cumulative. If the number is 100000
, once the first invocation is completed, memory should be released.
A version that works
If we don’t want communication via prolog.query
, the code works (adhoc
has arity 0 now):
say(Thing) :-
format(string(Command), `console.log("~w")`, [Thing]),
js_run_script(Command).
adhoc :-
findall(_{id: X, label:'some_long_label'}, between(1, 100000, X), Result),
say(Result),
say('adhoc').
<button
class=“button”
onclick={() => {
prolog.query(‘adhoc()’).once();
}}>ad hoc</button>
The thing I find interesting is that the logging I do from the prolog side (say(Result)
) contains the same information as the communication through prolog.query
, and yet the first always works while the second doesn’t.
@jan, @jeswr any thoughts about this? Who should I tag here that’s familiar with the WASM port?