Skip to content

Commit a7d8a17

Browse files
API.read_only: prevent changes to subtables and support the # operator
1 parent 3a2d67d commit a7d8a17

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

file-browser.lua

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ local state = {
195195
directory_label = nil,
196196
prev_directory = "",
197197
co = nil,
198+
empty_text = 'empty directory',
198199

199200
--lvl 2 values
200201
selected = 1,
@@ -257,7 +258,7 @@ local NIL_STATE = {}
257258

258259
local function get_state(level)
259260
--bypasses the readonly reference and grabs the original table and metatable
260-
local s = getmetatable(state).__index
261+
local s = getmetatable(state).mutable
261262
local mt = getmetatable(s)
262263

263264
--travels up the state chain until it finds a mt of the same level as `level`
@@ -290,17 +291,20 @@ end
290291

291292
--the values table will be made readonly and set as part of the state - do not use values after passing to this function!
292293
local function set_state(level, values)
293-
local new_mt = { level = level }
294-
setmetatable(values, new_mt)
295294

296295
if level == 0 then
296+
setmetatable(values, { level = 0 })
297297
state = API.read_only(values)
298298
return state
299299
end
300300

301301
local s, mt = get_state(level)
302302
if not mt then error('failed to get state of level '..level) end
303-
new_mt.__index = mt.level == level and mt.__index or s
303+
if mt.level == level then
304+
setmetatable(values, mt)
305+
else
306+
setmetatable(values, { level = level, __index = s })
307+
end
304308

305309
state = API.read_only(values)
306310
return state
@@ -712,10 +716,20 @@ do
712716
local references = setmetatable({}, { __mode = 'k' })
713717

714718
--returns a read-only reference to the table t
719+
--based on https://stackoverflow.com/a/28315547
715720
function API.read_only(t)
721+
if type(t) ~= 'table' then return t end
716722
if references[t] then return references[t] end
717723

718-
local ro = setmetatable({}, { __index = t, __newindex = newindex })
724+
local ro = setmetatable({}, {
725+
__newindex = newindex,
726+
mutable = t,
727+
__index = function(_, k)
728+
return API.read_only( t[k] )
729+
end,
730+
__len = function () return #t end
731+
})
732+
719733
references[t] = ro
720734
return ro
721735
end

0 commit comments

Comments
 (0)