Skip to content

Keeping Luau current

This page is for people who maintain LuneBlox. Its whole purpose is to run the Luau that Roblox runs, so when Roblox moves to a new Luau release, LuneBlox follows.

Luau reaches the binary through three things in the repository. All three move together.

LuneBlox uses mlua for its Luau bindings. mlua-sys is the crate that pins which Luau is built: mlua 0.12.2 asks for mlua-sys 0.13, which asks for luau0-src 0.22 and so Luau 0.740. Every crate in the workspace names the same mlua version.

When Roblox is ahead of the newest mlua release, Cargo.toml patches mlua-sys to the commit on mlua’s main branch that carries the new Luau, until a release does:

[patch.crates-io]
mlua-sys = { git = "https://github.com/mlua-rs/mlua", rev = "<commit>" }

Such a patch also needs the repository in allow-git of deny.toml.

luau0-src is the crate that carries Luau’s C++ sources. LuneBlox keeps a copy in vendor/luau0-src and patches the dependency to it:

[patch.crates-io]
luau0-src = { path = "vendor/luau0-src" }

The copy is luau0-src 0.22.0+luau740 as published, plus fixes to Luau’s own C++. Each fix is marked with a comment that starts with LuneBlox:. The directory is excluded from the workspace, so it is not linted or formatted.

List the fixes with:

Terminal window
grep -rn "LuneBlox:" vendor/luau0-src

Today there is one, in luau/CodeGen/src/IrRegAllocA64.cpp: the ARM64 register allocator no longer plans to reload a spilled value from a constant past K255.

crates/lune/src/rt/roblox_fflags.rs is generated against one Luau version and one Roblox client version. See Fast flags.

  1. Move mlua to the new Luau. If an mlua release carries it, bump mlua in every crate’s Cargo.toml and run cargo update -p mlua -p mlua-sys. If none does yet, patch mlua-sys in Cargo.toml to an mlua commit that pins the new Luau, and drop the patch once a release has it.

  2. Re-copy vendor/luau0-src. Replace the directory with the luau0-src crate version the new mlua-sys asks for.

  3. Re-apply the marked fixes. Before replacing the directory, collect every LuneBlox: fix. For each one, check whether the new Luau has taken it. Re-apply those it has not, keeping the LuneBlox: comment. If none remain, drop the luau0-src patch and the vendored directory.

  4. Build.

    Terminal window
    cargo build
  5. Regenerate the fast flags. The generator reads the flags the new Luau declares, so it has to run after the sources have moved.

    Terminal window
    luneblox run scripts/generate_roblox_fflags.luau
  6. Run the test suite. Rust tests and every Luau test:

    Terminal window
    cargo nextest run --workspace --all-features
  7. Run the gates. The tree is kept at zero warnings.

    Terminal window
    lefthook run pre-commit --all-files
  8. Update the words. The Luau version appears in README.md, in the comments of Cargo.toml and in a new CHANGELOG.md entry.

_VERSION needs no change. The part after the + is read from Luau itself at run time.

Terminal window
cargo run -- run - <<'EOF'
print(_VERSION)
EOF

It should print the new Luau number after the +, such as LuneBlox 0.11.3+740.

The regression test for each carried fix must still pass. For the ARM64 fix it is tests/luau/codegen_far_constant.luau, registered in crates/lune/src/tests.rs. A Luau test that is not registered there never runs.

Roblox changes flag values between Luau releases. To pick those up without moving Luau, do steps 5 to 7 alone and release.

  • Read mlua’s changelog before bumping it. A release can change what a conversion accepts, as 0.12.2 did for integers, and such a change shows up only when a script runs.
  • The release profile builds mlua-sys at opt-level = 3 while the rest of the workspace uses "z". If the crate that compiles Luau’s C++ changes, the override in Cargo.toml has to follow it, or the VM silently goes back to -Os.
  • Test on ARM64 and x64. The native code generators are separate, and the one carried fix so far was ARM64 only.
  • Releases go to GitHub only. luneblox build --target downloads base executables from the release of the same version, so a release needs all six target archives. See Standalone executables.