Channel stable
-
changed:
stable head
2.0.3→2.1.0
stable: Artifacts
-
changed:
Artifact crate size
2395447 bytes→2416845 bytes
Releases
- added: Release 2.1.0stable, available, dated 2026-10-15 by its publisher
Publisher's notes for 2.1.0 stable
the publisher lists breaking changes
Limits that hold: an uncatchable watchdog on every host call, a memory cap the allocator enforces, protected host-level pushes, deeply frozen sandboxes, and process capabilities that mean what they say; plus process.sleep, @dream/fs path functions and atomic writes, the rest of a regex API, trimming, shortest float digits, and Runtime::shutdown for hosts that exit without dropping the runtime.
Breaking changes
StackandFramepushes,open_standard_libraries,sandbox_globalsandsandbox_luaureturnResult: a push checks the stack has room, and host-level pushes and setup that allocate run under protection, so a stack overflow or an out of memory at host level isErrinstead of an abort.process.writeneeds theprocess.stdiocapability.process.runstarts a child with only the variablesenvnames unlessprocess.environmentis granted, and kills a child still running when the execution time limit runs out.data.countisdata.countWhereanddata.compareisdata.select, so neither shares a name withbytes.countorbytes.compare.bytes.translate(text, rules)takes the rules tableintern.newtakes (nocase,replace,collapse,trimStart,trimEnd), or abytes.rulescompiled from one, in place of its ownfrom,toand options.- The TLS stream's
shutdownWrite()isshutdown('write'), as a TCP stream half-closes. raster's modulergba8andrgb8clamp and round as the receiver's always did, instead of raising on a channel out of range.
Added
process.sleep(seconds), never past the runtime's execution time limit.@dream/fsjoin,parent,fileName,extensionandisFileName, which touch no disk and need no capability;isFileandisDir;writeFile'sexclusive,atomicandcreateParents.bytes.regexmatch,captures, amatchesiterator,replaceandreplaceAllby template or function,split,tostring, andbytes.regexEscape.bytes.trim,trimStartandtrimEnd: Unicode whitespace on UTF-8, ASCII otherwise, or a given byte set.bytes.shortest(value, width?), the fewest decimal digits that read back as a value atf64orf32width, andbytes.toF32.Runtime::shutdown(), which flushes and closes every live@dream/fswriter without freeing the heap, for a host that leaves the heap to the process's exit.runtime::watchdog_remaining(scope)andruntime::expire_if_due(scope), so a host's own blocking native clamps its wait to the watchdog.Error::ExecutionTimeLimitandError::MemoryLimit(Error::is_limit()),CallContext::HOST,Scope::is_host_level,flags::luau_assertions().- One capability denial,
Error::deniedandModuleInstaller::gated, and onestack::push_list, for extensions. raster's module gains the channel getters its receiver has; everymath()receiver method and its module function are expanded from one list, and a test holds them to each other.
Changed
- Every host call into Luau runs under the runtime's limits: an implicit host-interface scope arms the watchdog and the memory cap unless the host opens an
Initializationscope itself. - Release builds define
NDEBUG, so they no longer carry Luau's assertions and traps. udp's capability denials read like every other module's.
Fixed
- A timeout is sticky: once a call's execution time limit runs out, every safepoint raises until the scope that armed it ends, so
pcall,xpcalland coroutines can't catch it and carry on. - The memory limit is the allocator's: a growth past it fails at the allocation, so one
buffer.createcan't take a gigabyte between watchdog polls. Thread::resetrefuses a thread that is running or resuming another, instead of tripping Luau's assertion and freeing the stack it runs on.readFile,readFileStringandopenrefuse a FIFO, a socket or a device instead of blocking on it or reading without end.- Every table and metatable a sandbox's library views and common packages reach is frozen, so one instance can't write through a nested table or a shared metatable to another.
Migration
Handle the Result every push and setup call now returns (? in a function returning l3i::Result). Grant process.stdio to a runtime whose scripts write to the terminal through process.write, and process.environment to one whose children need the parent's environment, or pass env. Rename data.count and data.compare calls, rewrite bytes.translate(text, from, to, options) as bytes.translate(text, bytes.rules { replace = { ... }, collapse = ..., ... }) (compile the rules once outside a loop), and shutdownWrite() as shutdown('write'). A script that caught a timeout with pcall to carry on now stops; that was the bug.
bytes.shortest gives Rust's digits, which can differ from Ryū's (serde_json's) in the last digit where two shortest spellings both read back as the value.
Written by the publisher and shown verbatim, rendered through a sanitizer.