Files
benilla-octo/third_party/lua-src/BENILLA.md
T
SamandClaude Fable 5 b427860b35 dialogs come to the front, and the red line names what it needs
- dialogs carry the reference's toplevel bit, so the stack-split window opens above Bagnon instead of behind it
- the failure line fills its blank — "Requires Blacksmith Hammer", not "Requires" — and Opening casts stop printing a label the spell itself marks "no text"
- the pet bar's Attack/Follow/Stay tooltips name their keybinding, and typed text reaches the focused frame through the client's own delivery walk
- AtlasLoot parses again: our Lua keeps 5.0's compatibility semicolon

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 19:38:18 +07:00

4.9 KiB
Raw Blame History

benilla's lua-src fork — what differs from upstream, and how to check

Upstream: mlua-rs/lua-src-rs, MIT, version 550.0.0 — the version mlua 0.11 resolves to. Wired in through [patch.crates-io] in the workspace root.

Why a fork exists at all

The 1.12 addon corpus is Lua 5.0 code. It uses the iterator-less generic-for:

for k, v in someTable do ... end        -- no pairs(), no iterator function

183 of 218 corpus addons are reached by it (118 carry it, 65 inherit it through a declared dependency), across 1,163 sites. On stock Lua 5.1 it raises attempt to call a table value, and it is the first session-start error for 60 of 218 addons — three quarters of everything that breaks once the client is actually running, eleven times the next cause.

Lua 5.1 removed it at the opcode level, which is why no layer above the VM can reach it. Every other dialect gap this project has closed was reachable from inside Lua — table.setn is a library function, bit is a library, print is a global (decisions 1194, 1196). This one is not:

  • a __call metamethod would work, but the tables are the addon's own and Lua 5.1 has no per-type default metatable for tables;
  • rewriting the chunk source means parsing Lua with a regex to tell in t do from in pairs(t) do, and getting that wrong changes behaviour silently;
  • there is no lua50 backend — lua-src ships 5.1 through 5.5 and every one of them removed it.

What is NOT being done

benilla is not adopting Lua 5.0. We stay on 5.1.5 and restore the behaviour of a single opcode that Lua itself shipped and labelled /* for compatibility only */. Every other 5.1 fix, and the whole of mlua's surface, stay exactly as upstream. That is a far smaller commitment than a version downgrade, and it is the entire reason this is a one-hunk fork rather than a vendored 5.0.

The delta, and the command that proves it

Current state: three hunks, in three files. src/lib.rs additionally differs by having Lua 5.2/5.3/5.4/5.5 stripped from the Version enum (with their source trees deleted) — benilla builds 5.1 and only 5.1, and a fork that still offered the other four would answer a request for one with a missing directory at build time instead of a compile error.

file hunk why record
lvm.c 5.0's OP_TFORPREP table→next substitution, folded into the top of OP_TFORLOOP for k, v in someTable do raised "attempt to call a table value"; it was the first session-start error for 60 corpus addons 1215
luaconf.h LUA_COMPAT_LSTR 1 → 2 5.1 kept 5.0's nesting machinery and put an advisory error in front of it; two corpus addons died on "nesting of [[...]] is deprecated" —
lparser.c 5.0's compat-semicolon skip restored at the top of constructor()'s field loop — 5.0's own line, verbatim, comment included one extra ; after a field separator inside a table constructor (Back_Title = AL["Factions"];;, ×20 in AtlasLoot's ButtonRegistry.lua) parses on the client and died here with "unexpected symbol near ;"; statement-level ;; stays rejected by both dialects 1315

The ordering was deliberate and it held: the fork landed inert, byte-identical to upstream, so the build pipeline was proven transparent before any behavioural payload went into it — and when the suite then moved, the patch was the only thing that could have moved it. Both hunks are measured against the 218-addon corpus rather than argued: the long-string one alone took loaded 134 → 139 and survivors 99 → 104.

To verify the Lua sources against upstream at any time:

# 550.0.0 is the pinned version; adjust the path if cargo's registry hash differs.
diff -r third_party/lua-src/lua-5.1.5 \
  ~/.cargo/registry/src/*/lua-src-550.0.0/lua-5.1.5

That must print exactly the three hunks in the table above and nothing else. If it ever prints more, something crept in.

Status of the payload

Landed. The reverse-engineering answer this was deliberately blocked on came back from wow-5875-re (system/ui/scratch/lua-generic-for.md) and is what the lvm.c comment cites, detail by detail: a bare type-tag test that never consults a metatable (so a table carrying __call still gets next), the global next read raw and fetched fresh at every loop entry (so an addon assigning next = myfn changes every later generic-for in the session), and userdata not substituted.

Waiting was the right call twice over. Checking stock 5.0 first corrected two assumptions the project had already written down — the substitution happens in OP_TFORPREP, an opcode 5.1 deleted, not in OP_TFORLOOP; and the test is a bare ttistable with no __call check. Stock 5.0 was corroboration, never the authority: the client links 5.0 but may be modified, and only the byte-read of the client settles what it actually does.