Files
benilla-octo/third_party/lua-src/BENILLA.md
T
SamandClaude Fable 5 2c1ffca2ca 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

80 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# benilla's `lua-src` fork — what differs from upstream, and how to check
Upstream: [`mlua-rs/lua-src-rs`](https://github.com/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:
```lua
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:
```sh
# 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.