set_sys_inputs (lib.rs:218) and compile_internal (lib.rs:380) both take &mut *compiler, with no lock on either side of the boundary. Concurrent use aliases a &mut, and the mutations are real:
compile_inner calls world.reset_time() (world.rs:176), an OnceLock::take, while another compile may be in get_or_init on the same cell.
set_inputs (world.rs:165) replaces self.library. typst::compile borrows world.library() for the whole evaluation, so this frees a Library another thread is still reading.
TypstCompiler carries no lock and no thread-safety remark, while TypstDocument documents its own rules. README.md:196 recommends caching one instance in ASP.NET, and the mail-merge example sets inputs and compiles in a loop, so a singleton is the shape users will build. Two overlapping requests then either corrupt the process or render one request's document with another request's sys.inputs.
What I would like:
- A class-level
<summary> and a README note stating that an instance is not thread-safe, and to use one per worker or an ObjectPool<TypstCompiler>.
- A lock inside
TypstCompiler around CompileToDocument, SetSysInputs and Dispose, plus an overload taking the inputs so set-then-compile is atomic. A per-call lock alone is not enough, since those are two calls.
Happy to send a PR.
set_sys_inputs(lib.rs:218) andcompile_internal(lib.rs:380) both take&mut *compiler, with no lock on either side of the boundary. Concurrent use aliases a&mut, and the mutations are real:compile_innercallsworld.reset_time()(world.rs:176), anOnceLock::take, while another compile may be inget_or_initon the same cell.set_inputs(world.rs:165) replacesself.library.typst::compileborrowsworld.library()for the whole evaluation, so this frees aLibraryanother thread is still reading.TypstCompilercarries no lock and no thread-safety remark, whileTypstDocumentdocuments its own rules.README.md:196recommends caching one instance in ASP.NET, and the mail-merge example sets inputs and compiles in a loop, so a singleton is the shape users will build. Two overlapping requests then either corrupt the process or render one request's document with another request'ssys.inputs.What I would like:
<summary>and a README note stating that an instance is not thread-safe, and to use one per worker or anObjectPool<TypstCompiler>.TypstCompileraroundCompileToDocument,SetSysInputsandDispose, plus an overload taking the inputs so set-then-compile is atomic. A per-call lock alone is not enough, since those are two calls.Happy to send a PR.