diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-01-21 10:27:22 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-01-21 10:27:22 -0300 |
commit | 0e9254dfa03d95c3aa2888cf78e9a30bc88d41bc (patch) | |
tree | ca3c956e03f8ecc03eb7ed155c8b6f5e3ebef801 /testes | |
parent | 6ccd24eff58340c00db2877c4558a63c6b859442 (diff) | |
download | lua-0e9254dfa03d95c3aa2888cf78e9a30bc88d41bc.tar.gz lua-0e9254dfa03d95c3aa2888cf78e9a30bc88d41bc.tar.bz2 lua-0e9254dfa03d95c3aa2888cf78e9a30bc88d41bc.zip |
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.
Diffstat (limited to 'testes')
-rw-r--r-- | testes/locals.lua | 77 |
1 files changed, 70 insertions, 7 deletions
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 | |||
521 | end | 521 | end |
522 | 522 | ||
523 | 523 | ||
524 | local function checktable (t1, t2) | ||
525 | assert(#t1 == #t2) | ||
526 | for i = 1, #t1 do | ||
527 | assert(t1[i] == t2[i]) | ||
528 | end | ||
529 | end | ||
530 | |||
531 | |||
524 | if rawget(_G, "T") then | 532 | if rawget(_G, "T") then |
525 | 533 | ||
526 | -- memory error inside closing function | 534 | -- memory error inside closing function |
@@ -632,6 +640,68 @@ if rawget(_G, "T") then | |||
632 | print'+' | 640 | print'+' |
633 | end | 641 | end |
634 | 642 | ||
643 | |||
644 | do | ||
645 | -- '__close' vs. return hooks in C functions | ||
646 | local trace = {} | ||
647 | |||
648 | local function hook (event) | ||
649 | trace[#trace + 1] = event .. " " .. (debug.getinfo(2).name or "?") | ||
650 | end | ||
651 | |||
652 | -- create tbc variables to be used by C function | ||
653 | local x = func2close(function (_,msg) | ||
654 | trace[#trace + 1] = "x" | ||
655 | end) | ||
656 | |||
657 | local y = func2close(function (_,msg) | ||
658 | trace[#trace + 1] = "y" | ||
659 | end) | ||
660 | |||
661 | debug.sethook(hook, "r") | ||
662 | local t = {T.testC([[ | ||
663 | toclose 2 # x | ||
664 | pushnum 10 | ||
665 | pushint 20 | ||
666 | toclose 3 # y | ||
667 | return 2 | ||
668 | ]], x, y)} | ||
669 | debug.sethook() | ||
670 | |||
671 | -- hooks ran before return hook from 'testC' | ||
672 | checktable(trace, | ||
673 | {"return sethook", "y", "return ?", "x", "return ?", "return testC"}) | ||
674 | -- results are correct | ||
675 | checktable(t, {10, 20}) | ||
676 | end | ||
677 | |||
678 | end | ||
679 | |||
680 | |||
681 | do -- '__close' vs. return hooks in Lua functions | ||
682 | local trace = {} | ||
683 | |||
684 | local function hook (event) | ||
685 | trace[#trace + 1] = event .. " " .. debug.getinfo(2).name | ||
686 | end | ||
687 | |||
688 | local function foo (...) | ||
689 | local x <close> = func2close(function (_,msg) | ||
690 | trace[#trace + 1] = "x" | ||
691 | end) | ||
692 | |||
693 | local y <close> = func2close(function (_,msg) | ||
694 | debug.sethook(hook, "r") | ||
695 | end) | ||
696 | |||
697 | return ... | ||
698 | end | ||
699 | |||
700 | local t = {foo(10,20,30)} | ||
701 | debug.sethook() | ||
702 | checktable(t, {10, 20, 30}) | ||
703 | checktable(trace, | ||
704 | {"return sethook", "return close", "x", "return close", "return foo"}) | ||
635 | end | 705 | end |
636 | 706 | ||
637 | 707 | ||
@@ -640,13 +710,6 @@ print "to-be-closed variables in coroutines" | |||
640 | do | 710 | do |
641 | -- yielding inside closing metamethods | 711 | -- yielding inside closing metamethods |
642 | 712 | ||
643 | local function checktable (t1, t2) | ||
644 | assert(#t1 == #t2) | ||
645 | for i = 1, #t1 do | ||
646 | assert(t1[i] == t2[i]) | ||
647 | end | ||
648 | end | ||
649 | |||
650 | local trace = {} | 713 | local trace = {} |
651 | local co = coroutine.wrap(function () | 714 | local co = coroutine.wrap(function () |
652 | 715 | ||