Tables assigned to wezterm.GLOBAL become "userdata"
What Operating System(s) are you seeing this problem on?
macOS
Which Wayland compositor or X11 Window manager(s) are you using?
No response
WezTerm version
20231228-084719-ff274374
Did you try the latest nightly build to see if the issue is better (or worse!) than your current version?
Yes, and I updated the version box above to show the version of the nightly that I tried
Describe the bug
The documentation for wezterm.GLOBAL says that we can use it as a persistent in-memory cache for use across threads in WezTerm including tables (table type).
However, it looks like that wezterm.GLOBAL converts the assigned tables to type userdata that doesn't allow any normal table operations on it (next(), pairs() etc.). Any of these operations will throw:
runtime error: <location> bad argument #1 to 'next' (table expected, got Value)
For my specific use-case, I can probably implement a work-around by serializing/de-serializing the table to string but would be nice if we could make use of normal table operations in wezterm.GLOBAL (or we should update the documentation to notify other users)
To Reproduce
- Create a simple table (can be empty):
local myTable = { ["foo"] = "bar"} -- type(myTable): "table" - Assign it to
wezterm.GLOBAL:wezterm.GLOBAL.myTable = myTable - Try a
next()operation onwezterm.GLOBAL.myTable(e.g.: to check if it's empty):next(wezterm.GLOBAL.myTable) - See the error in the debug overlay
- Inspect the type of
wezterm.GLOBAL:type(wezterm.GLOBAL.myTable) -- "userdata"
Configuration
no config
Expected Behavior
I expected to be able to use next() and pairs() operations on table values assigned to wezterm.GLOBAL
Logs
No response
Anything else?
No response
The values need to be userdata in order to allow reference updates to work. I think it is reasonable to want pairs/ipairs to function.
In the meantime, as a workaround, try adding in an extra layer to your table. So:
local myTable = {
data = {
["foo"] = "bar"
}
}
wezterm.GLOBAL.myTable = myTable
then when you access it:
next(wezterm.GLOBAL.myTable.data)
I can't remember if I was "smart" and make every access work as a reference or not; if I wasn't too smart for my own good, that second level access will read as a normal lua table value.
I am new to Lua but is the following difference in behaviors of plain table list and wezterm.GLOBAL.list comes from this issue?
wezterm version: 20240121-180215-76028ca1 aarch64-apple-darwin
Window Environment: macOS 14.2.1 (23C71)
WebGPU: name=Apple M1 Pro, device_type=IntegratedGpu, backend=Metal, vendor=0, device=0
Enter lua statements or expressions and hit Enter.
Press ESC or CTRL-D to exit
> list = {}
> for a,b in pairs(list) do print(a,b) end -- prints nothing, OK
> for a,b in ipairs(list) do print(a,b) end -- prints nothing, OK
> wezterm.GLOBAL.list = {}
> for a,b in pairs(wezterm.GLOBAL.list) do print(a,b) end -- prints nothing, OK
> for a,b in ipairs(wezterm.GLOBAL.list) do print(a,b) end -- ERROR!
can only index objects using string values
stack traceback:
[C]: in ?
[C]: in for iterator 'for iterator'
[string "repl"]:1: in main chunk
(In my actual use in my config, I wrapped the loop with size check to avoid errors.)
next(wezterm.GLOBAL.myTable.data)I can't remember if I was "smart" and make every access work as a reference or not; if I wasn't too smart for my own good, that second level access will read as a normal lua table value.
Unfortunately…you were too smart for your own good in this case. In theory, one could make a __pairs and/or __ipairs iterator for the userdata, but as of right now the values in wezterm.GLOBAL cannot be iterated over, even with the indirection layer suggested.