To: vim_dev@googlegroups.com Subject: Patch 8.2.1202 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1202 Problem: Vim9: crash when calling a closure from a builtin function. Solution: Use the current execution context. (closes #6441) Files: src/vim9execute.c, src/testdir/test_vim9_func.vim *** ../vim-8.2.1201/src/vim9execute.c 2020-07-13 18:17:53.279714725 +0200 --- src/vim9execute.c 2020-07-13 20:40:50.416487591 +0200 *************** *** 461,466 **** --- 461,470 ---- return OK; } + // Ugly global to avoid passing the execution context around through many + // layers. + static ectx_T *current_ectx = NULL; + /* * Call a builtin function by index. */ *************** *** 470,481 **** typval_T argvars[MAX_FUNC_ARGS]; int idx; int did_emsg_before = did_emsg; if (call_prepare(argcount, argvars, ectx) == FAIL) return FAIL; ! // Call the builtin function. call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1)); // Clear the arguments. for (idx = 0; idx < argcount; ++idx) --- 474,489 ---- typval_T argvars[MAX_FUNC_ARGS]; int idx; int did_emsg_before = did_emsg; + ectx_T *prev_ectx = current_ectx; if (call_prepare(argcount, argvars, ectx) == FAIL) return FAIL; ! // Call the builtin function. Set "current_ectx" so that when it ! // recursively invokes call_def_function() a closure context can be set. ! current_ectx = ectx; call_internal_func_by_idx(func_idx, argvars, STACK_TV_BOT(-1)); + current_ectx = prev_ectx; // Clear the arguments. for (idx = 0; idx < argcount; ++idx) *************** *** 749,756 **** if (partial != NULL) { ! ectx.ec_outer_stack = partial->pt_ectx_stack; ! ectx.ec_outer_frame = partial->pt_ectx_frame; } // dummy frame entries --- 757,773 ---- if (partial != NULL) { ! if (partial->pt_ectx_stack == NULL && current_ectx != NULL) ! { ! // TODO: is this always the right way? ! ectx.ec_outer_stack = ¤t_ectx->ec_stack; ! ectx.ec_outer_frame = current_ectx->ec_frame_idx; ! } ! else ! { ! ectx.ec_outer_stack = partial->pt_ectx_stack; ! ectx.ec_outer_frame = partial->pt_ectx_frame; ! } } // dummy frame entries *** ../vim-8.2.1201/src/testdir/test_vim9_func.vim 2020-07-13 18:55:44.937073001 +0200 --- src/testdir/test_vim9_func.vim 2020-07-13 20:39:12.432751764 +0200 *************** *** 1019,1023 **** --- 1019,1042 ---- assert_equal(6765, Fibonacci(20)) enddef + def TreeWalk(dir: string): list + return readdir(dir)->map({_, val -> + fnamemodify(dir .. '/' .. val, ':p')->isdirectory() + ? {val : TreeWalk(dir .. '/' .. val)} + : val + }) + enddef + + def Test_closure_in_map() + mkdir('XclosureDir/tdir', 'p') + writefile(['111'], 'XclosureDir/file1') + writefile(['222'], 'XclosureDir/file2') + writefile(['333'], 'XclosureDir/tdir/file3') + + assert_equal(['file1', 'file2', {'tdir': ['file3']}], TreeWalk('XclosureDir')) + + delete('XclosureDir', 'rf') + enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker *** ../vim-8.2.1201/src/version.c 2020-07-13 18:55:44.941072990 +0200 --- src/version.c 2020-07-13 20:26:44.230775161 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 1202, /**/ -- hundred-and-one symptoms of being an internet addict: 26. You check your mail. It says "no new messages." So you check it again. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///