You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Segmentation fault when re-evaluating an ES module involved in a circular dependency #1320
Segmentation fault in js_create_module_function with circular ES module dependencies
Description
These notes are generated by claude. Maybe it's my problem? Please tell me how to?
Summary
QuickJS-ng crashes with a segmentation fault when calling eval() on ES modules with circular dependencies. The crash occurs because js_create_module_function receives a NULL pointer when recursively processing circular module dependencies.
Environment
QuickJS-ng version: git master
Platform: Linux
Project: circu.js(txiki.js fork)
Steps to Reproduce
Create two modules with circular dependency:
a.ts:
import'./b';exportconsta='module a';
b.ts:
import'./a';exportconstb='module b';
Load and evaluate module 'a' - works fine
Load and evaluate module 'b' - crashes with SEGV
Expected Behavior
Circular module dependencies should be handled gracefully without crashing, similar to how Node.js and other JS engines handle circular imports.
Actual Behavior
Program crashes with segmentation fault:
Program received signal SIGSEGV, Segmentation fault.
0x000055555563bbca in js_create_module_function (ctx=0x555555763fd0, m=0x0)
at /root/txiki.ts/deps/quickjs/quickjs.c:28852
28852 if (m->func_created)
Stack Trace
#0 0x000055555563bbca in js_create_module_function (ctx=0x555555763fd0, m=0x0)
at /root/txiki.ts/deps/quickjs/quickjs.c:28852
#1 0x000055555563bcc9 in js_create_module_function (ctx=0x555555763fd0, m=0x55555580c840)
at /root/txiki.ts/deps/quickjs/quickjs.c:28878
#2 0x000055555563bcc9 in js_create_module_function (ctx=0x555555763fd0, m=0x5555559f1960)
at /root/txiki.ts/deps/quickjs/quickjs.c:28878
#3 0x000055555565100b in JS_EvalFunctionInternal (ctx=0x555555763fd0, fun_obj=...,
this_obj=..., var_refs=0x0, sf=0x0) at /root/txiki.ts/deps/quickjs/quickjs.c:35376
#4 0x0000555555651125 in JS_EvalFunction (ctx=0x555555763fd0, fun_obj=...)
at /root/txiki.ts/deps/quickjs/quickjs.c:35394
Root Cause
the function js_create_module_function attempts to access m->func_created without checking if m is NULL:
if (m->func_created) // CRASH: m is NULL herereturnm->func_obj;
When processing circular dependencies, the recursive call chain eventually passes a NULL module pointer, causing the segfault.
Additional Notes
Evaluating module 'a' works fine
Evaluating module 'b' (which depends on 'a', which depends on 'b') crashes
The issue occurs specifically when using module.eval() on modules with circular dependencies
Without calling eval(), the circular dependency itself doesn't cause issues
Workaround
Currently avoiding the use of eval() on modules with potential circular dependencies.
➜ quickjs git:(master) ✗ git pull
Already up to date.
➜ quickjs git:(master) ✗ cmake --build .
[ 27%] Built target qjs
[ 40%] Built target qjsc
[ 63%] Built target qjs_exe
[ 77%] Built target run-test262
[ 86%] Built target api-test
[100%] Built target function_source
➜ quickjs git:(master) ✗ gcc eg.c libqjs.a -lm -O0 -o eg
➜ quickjs git:(master) ✗ gdb eg
GNU gdb (Debian 17.1-1) 17.1
Copyright (C) 2025 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from eg...
(gdb) r
Starting program: /root/quickjs/eg
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
bt0x00005555555b5e1f in js_create_module_function (ctx=0x555555662bc0, m=0x0) at /root/quickjs/quickjs.c:28873
28873 if (m->func_created)
(gdb) bt
#0 0x00005555555b5e1f in js_create_module_function (ctx=0x555555662bc0, m=0x0) at /root/quickjs/quickjs.c:28873
#1 0x00005555555b5f1e in js_create_module_function (ctx=0x555555662bc0, m=0x5555556782a0)
at /root/quickjs/quickjs.c:28899
#2 0x00005555555b5f1e in js_create_module_function (ctx=0x555555662bc0, m=0x555555678cb0)
at /root/quickjs/quickjs.c:28899
#3 0x00005555555cb512 in JS_EvalFunctionInternal (ctx=0x555555662bc0, fun_obj=..., this_obj=..., var_refs=0x0, sf=0x0)
at /root/quickjs/quickjs.c:35396
#4 0x00005555555cb62c in JS_EvalFunction (ctx=0x555555662bc0, fun_obj=...) at /root/quickjs/quickjs.c:35414
#5 0x0000555555561782 in module_loader ()
#6 0x00005555555b4954 in js_host_resolve_imported_module (ctx=0x555555662bc0, base_cname=0x555555678238 "a",
cname1=0x555555678438 "b", attributes=...) at /root/quickjs/quickjs.c:28307
#7 0x00005555555b4a17 in js_host_resolve_imported_module_atom (ctx=0x555555662bc0, base_module_name=555,
module_name1=557, attributes=...) at /root/quickjs/quickjs.c:28329
#8 0x00005555555b5aed in js_resolve_module (ctx=0x555555662bc0, m=0x5555556782a0) at /root/quickjs/quickjs.c:28783
#9 0x00005555555cbbe5 in __JS_EvalInternal (ctx=0x555555662bc0, this_obj=...,
input=0x55555562d008 "import { vt } from 'b';export function test(a){ return a.toString(); } export function test2(){ return vt; }", input_len=108, filename=0x555555678250 "a", line=1, flags=33, scope_idx=-1)
at /root/quickjs/quickjs.c:35518
#10 0x00005555555cbde1 in JS_EvalInternal (ctx=0x555555662bc0, this_obj=...,
input=0x55555562d008 "import { vt } from 'b';export function test(a){ return a.toString(); } export function test2(){ return vt; }", input_len=108, filename=0x555555678250 "a", line=1, flags=33, scope_idx=-1)
at /root/quickjs/quickjs.c:35551
#11 0x00005555555cc09f in JS_EvalThis2 (ctx=0x555555662bc0, this_obj=...,
input=0x55555562d008 "import { vt } from 'b';export function test(a){ return a.toString(); } export function test2(){ return vt; }", input_len=108, options=0x7fffffffdac0) at /root/quickjs/quickjs.c:35606
#12 0x00005555555cc11d in JS_Eval (ctx=0x555555662bc0,
input=0x55555562d008 "import { vt } from 'b';export function test(a){ return a.toString(); } export function test2(){ return vt; }", input_len=108, filename=0x555555678250 "a", eval_flags=33) at /root/quickjs/quickjs.c:35620
#13 0x0000555555561763 in module_loader ()
--Type <RET> for more, q to quit, c to continue without paging--
#14 0x00005555555b4954 in js_host_resolve_imported_module (ctx=0x555555662bc0, base_cname=0x555555677ed8 "main",
cname1=0x555555678238 "a", attributes=...) at /root/quickjs/quickjs.c:28307
#15 0x00005555555b4a17 in js_host_resolve_imported_module_atom (ctx=0x555555662bc0, base_module_name=554,
module_name1=555, attributes=...) at /root/quickjs/quickjs.c:28329
#16 0x00005555555b5aed in js_resolve_module (ctx=0x555555662bc0, m=0x555555677ef0) at /root/quickjs/quickjs.c:28783
#17 0x00005555555cbbe5 in __JS_EvalInternal (ctx=0x555555662bc0, this_obj=..., input=0x55555562d0ee "import 'a';",
input_len=11, filename=0x55555562d0fa "main", line=1, flags=1, scope_idx=-1) at /root/quickjs/quickjs.c:35518
#18 0x00005555555cbde1 in JS_EvalInternal (ctx=0x555555662bc0, this_obj=..., input=0x55555562d0ee "import 'a';",
input_len=11, filename=0x55555562d0fa "main", line=1, flags=1, scope_idx=-1) at /root/quickjs/quickjs.c:35551
#19 0x00005555555cc09f in JS_EvalThis2 (ctx=0x555555662bc0, this_obj=..., input=0x55555562d0ee "import 'a';",
input_len=11, options=0x7fffffffdef0) at /root/quickjs/quickjs.c:35606
#20 0x00005555555cc11d in JS_Eval (ctx=0x555555662bc0, input=0x55555562d0ee "import 'a';", input_len=11,
filename=0x55555562d0fa "main", eval_flags=1) at /root/quickjs/quickjs.c:35620
#21 0x0000555555561904 in main ()
Yes, you are right. If I remove the JS_EvalFunction call, everything works perfectly. However, I need to inject some custom environments into the module before QuickJS takes ownership of it, which requires me to execute/evaluate the module manually via JS_EvalFunction first.
If this issue is caused by my incorrect usage, please let me know.
Activity
bnoordhuis commentedon Jan 24, 2026
Can't reproduce with qjs, it's probably something on your end. Can you post a test case that works (that is, crashes) with qjs, the quickjs shell?
Note that bare imports don't work in qjs, you have to write them as
import './b.js'.imzlh commentedon Jan 24, 2026
then,
saghul commentedon Jan 25, 2026
Don't test with txikijs, it's not up to date with quickjs master. Test with this repo. Also, you should check for errors in JS eval
imzlh commentedon Jan 27, 2026
imzlh commentedon Jan 27, 2026
And that's not txikijs! It's my fork version and I also add
import...withsupport. I updated quickjs dependency half a month ago.saghul commentedon Jan 27, 2026
Well the backtrace showed that, so I needed to be sure!
I'll take a look.
imzlh commentedon Feb 12, 2026
Any progress? I need the feature to wrap and process CJS modules.
saghul commentedon Feb 12, 2026
I cannot reproduce this.
Here is what I have:
a.js
b.js
c.js
Then when I run c.js:
That is with latest master.
imzlh commentedon Feb 13, 2026
Yes, you are right. If I remove the JS_EvalFunction call, everything works perfectly. However, I need to inject some custom environments into the module before QuickJS takes ownership of it, which requires me to execute/evaluate the module manually via JS_EvalFunction first.
If this issue is caused by my incorrect usage, please let me know.
saghul commentedon Feb 13, 2026
Show a reduced but complete example of what you're doing.
You can also check how we evaluate some things at the start in qjs.c.
imzlh commentedon Feb 20, 2026
Isn't it complete?