From 0e9254dfa03d95c3aa2888cf78e9a30bc88d41bc Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 21 Jan 2021 10:27:22 -0300 Subject: Correct order of return hooks vs. close metamethods The return hook should be called only after closing variables (which are still part of the function). C functions were calling the hook before the metamethods. --- testes/locals.lua | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 7 deletions(-) (limited to 'testes') diff --git a/testes/locals.lua b/testes/locals.lua index 24a95d18..a25b2b9f 100644 --- a/testes/locals.lua +++ b/testes/locals.lua @@ -521,6 +521,14 @@ do -- tbc inside close methods end +local function checktable (t1, t2) + assert(#t1 == #t2) + for i = 1, #t1 do + assert(t1[i] == t2[i]) + end +end + + if rawget(_G, "T") then -- memory error inside closing function @@ -632,6 +640,68 @@ if rawget(_G, "T") then print'+' end + + do + -- '__close' vs. return hooks in C functions + local trace = {} + + local function hook (event) + trace[#trace + 1] = event .. " " .. (debug.getinfo(2).name or "?") + end + + -- create tbc variables to be used by C function + local x = func2close(function (_,msg) + trace[#trace + 1] = "x" + end) + + local y = func2close(function (_,msg) + trace[#trace + 1] = "y" + end) + + debug.sethook(hook, "r") + local t = {T.testC([[ + toclose 2 # x + pushnum 10 + pushint 20 + toclose 3 # y + return 2 + ]], x, y)} + debug.sethook() + + -- hooks ran before return hook from 'testC' + checktable(trace, + {"return sethook", "y", "return ?", "x", "return ?", "return testC"}) + -- results are correct + checktable(t, {10, 20}) + end + +end + + +do -- '__close' vs. return hooks in Lua functions + local trace = {} + + local function hook (event) + trace[#trace + 1] = event .. " " .. debug.getinfo(2).name + end + + local function foo (...) + local x = func2close(function (_,msg) + trace[#trace + 1] = "x" + end) + + local y = func2close(function (_,msg) + debug.sethook(hook, "r") + end) + + return ... + end + + local t = {foo(10,20,30)} + debug.sethook() + checktable(t, {10, 20, 30}) + checktable(trace, + {"return sethook", "return close", "x", "return close", "return foo"}) end @@ -640,13 +710,6 @@ print "to-be-closed variables in coroutines" do -- yielding inside closing metamethods - local function checktable (t1, t2) - assert(#t1 == #t2) - for i = 1, #t1 do - assert(t1[i] == t2[i]) - end - end - local trace = {} local co = coroutine.wrap(function () -- cgit v1.2.3-55-g6feb