Skip to content

Commit 1ed786d

Browse files
committed
Merge branch 'lua-iteration' into 'master'
Dispatch __pairs without allocating a table for every call See merge request OpenMW/openmw!5510
2 parents 2172154 + 2cc7085 commit 1ed786d

2 files changed

Lines changed: 73 additions & 2 deletions

File tree

apps/components_tests/lua/testlua.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,41 @@ return {
4242
end,
4343
print = print,
4444
45+
iteratePlain = function()
46+
local sum = 0
47+
for k, v in pairs({a = 1, b = 2, c = 3}) do sum = sum + v end
48+
for i, v in ipairs({10, 20, 30}) do sum = sum + v end
49+
return sum
50+
end,
51+
honoursCustomPairs = function()
52+
local t = setmetatable({}, { __pairs = function(v) return next, {z = 9}, nil end })
53+
local sum = 0
54+
for k, v in pairs(t) do sum = sum + v end
55+
return sum
56+
end,
57+
iterateHiddenMetatable = function()
58+
local t = setmetatable({a = 1, b = 2}, { __metatable = false })
59+
local sum = 0
60+
for k, v in pairs(t) do sum = sum + v end
61+
for i, v in ipairs(setmetatable({7, 8}, { __metatable = false })) do sum = sum + v end
62+
return sum
63+
end,
64+
iterateReadOnly = function(t)
65+
local keys, sum = {}, 0
66+
for k, v in pairs(t) do keys[#keys + 1] = k; sum = sum + v end
67+
table.sort(keys)
68+
return table.concat(keys, ','), sum, #t
69+
end,
70+
iterateReadOnlyArray = function(t)
71+
local sum = 0
72+
for i, v in ipairs(t) do sum = sum + v end
73+
return sum, #t
74+
end,
75+
readOnlyIterationStateIsGuarded = function(t)
76+
local _, state = pairs(t)
77+
return rawequal(state, t)
78+
end,
79+
4580
-- should throw an error
4681
incorrectRequire = function() require('counter') end,
4782
modifySystemLib = function() math.sin = 5 end,
@@ -181,6 +216,32 @@ return {
181216
EXPECT_EQ(LuaUtil::getMutableFromReadOnly(LuaUtil::makeReadOnly(script)), script);
182217
}
183218

219+
TEST_F(LuaStateTest, Iteration)
220+
{
221+
const VFS::Path::Normalized path("bbb/tests.lua");
222+
sol::table script = mLua.runInNewSandbox(path);
223+
224+
EXPECT_EQ(LuaUtil::call(script["iteratePlain"]).get<int>(), 66);
225+
EXPECT_EQ(LuaUtil::call(script["honoursCustomPairs"]).get<int>(), 9);
226+
EXPECT_EQ(LuaUtil::call(script["iterateHiddenMetatable"]).get<int>(), 18);
227+
228+
mLua.protectedCall([&](LuaUtil::LuaView& view) {
229+
sol::table hash = LuaUtil::makeReadOnly(view.sol().create_table_with("a", 1, "b", 2, "c", 3));
230+
sol::table array = LuaUtil::makeReadOnly(view.sol().create_table_with(1, 10, 2, 20, 3, 30));
231+
232+
auto readOnly = LuaUtil::call(script["iterateReadOnly"], hash);
233+
EXPECT_EQ(readOnly.get<std::string>(0), "a,b,c");
234+
EXPECT_EQ(readOnly.get<int>(1), 6);
235+
EXPECT_EQ(readOnly.get<int>(2), 0);
236+
237+
auto readOnlyArray = LuaUtil::call(script["iterateReadOnlyArray"], array);
238+
EXPECT_EQ(readOnlyArray.get<int>(0), 60);
239+
EXPECT_EQ(readOnlyArray.get<int>(1), 3);
240+
241+
EXPECT_TRUE(LuaUtil::call(script["readOnlyIterationStateIsGuarded"], hash).get<bool>());
242+
});
243+
}
244+
184245
TEST_F(LuaStateTest, Print)
185246
{
186247
const VFS::Path::Normalized path("bbb/tests.lua");

components/lua/luastate.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,18 @@ namespace LuaUtil
221221
sol.script(R"(
222222
local _pairs = pairs
223223
local _ipairs = ipairs
224-
pairs = function(v) return (rawget(getmetatable(v) or {}, '__pairs') or _pairs)(v) end
225-
ipairs = function(v) return (rawget(getmetatable(v) or {}, '__ipairs') or _ipairs)(v) end
224+
-- script environments, sandboxed strings and ui.content set __metatable, so
225+
-- getmetatable returns false here rather than nil or a table
226+
pairs = function(v)
227+
local meta = getmetatable(v)
228+
local override = meta and rawget(meta, '__pairs')
229+
return (override or _pairs)(v)
230+
end
231+
ipairs = function(v)
232+
local meta = getmetatable(v)
233+
local override = meta and rawget(meta, '__ipairs')
234+
return (override or _ipairs)(v)
235+
end
226236
)");
227237
}
228238

0 commit comments

Comments
 (0)