0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.2.1706: Vim9: crash after running into the "Multiple closures" error

Problem:    Vim9: crash after running into the "Multiple closures" error.
Solution:   When a function fails still update any closures. (closes #6973)
This commit is contained in:
Bram Moolenaar 2020-09-18 21:25:32 +02:00
parent e8df010498
commit 7cbfaa51de
3 changed files with 23 additions and 7 deletions

View File

@ -1294,6 +1294,20 @@ def Test_call_closure_not_compiled()
GetResult(g:Ref)->assert_equal('sometext') GetResult(g:Ref)->assert_equal('sometext')
enddef enddef
def Test_double_closure_fails()
let lines =<< trim END
vim9script
def Func()
let var = 0
for i in range(2)
timer_start(0, {-> var})
endfor
enddef
Func()
END
CheckScriptFailure(lines, 'Multiple closures not supported yet')
enddef
def Test_sort_return_type() def Test_sort_return_type()
let res: list<number> let res: list<number>
res = [1, 2, 3]->sort() res = [1, 2, 3]->sort()

View File

@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1706,
/**/ /**/
1705, 1705,
/**/ /**/

View File

@ -2676,15 +2676,11 @@ call_def_function(
continue; continue;
func_return: func_return:
// Restore previous function. If the frame pointer is zero then there // Restore previous function. If the frame pointer is where we started
// is none and we are done. // then there is none and we are done.
if (ectx.ec_frame_idx == initial_frame_idx) if (ectx.ec_frame_idx == initial_frame_idx)
{
if (handle_closure_in_use(&ectx, FALSE) == FAIL)
// only fails when out of memory
goto failed;
goto done; goto done;
}
if (func_return(&ectx) == FAIL) if (func_return(&ectx) == FAIL)
// only fails when out of memory // only fails when out of memory
goto failed; goto failed;
@ -2703,6 +2699,10 @@ done:
ret = OK; ret = OK;
failed: failed:
// Also deal with closures when failed, they may already be in use
// somewhere.
handle_closure_in_use(&ectx, FALSE);
// When failed need to unwind the call stack. // When failed need to unwind the call stack.
while (ectx.ec_frame_idx != initial_frame_idx) while (ectx.ec_frame_idx != initial_frame_idx)
func_return(&ectx); func_return(&ectx);