patch 9.1.1356: Vim9: crash when unletting variable

Problem:  Vim9: crash when unletting variable
Solution: fix crash, allow to use :unlet
          (Hirohito Higashi)

closes: #17226

Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Hirohito Higashi
2025-05-01 08:56:39 +02:00
committed by Christian Brabandt
parent f57c065e75
commit f5bfc48c05
5 changed files with 17 additions and 18 deletions

View File

@ -2,7 +2,6 @@
int lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx);
int arg_exists(char_u *name, size_t len, int *idxp, type_T **type, int *gen_load_outer, cctx_T *cctx);
void update_script_var_block_id(char_u *name, int block_id);
int script_is_vim9(void);
int script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack);
int cctx_class_method_idx(cctx_T *cctx, char_u *name, size_t len, class_T **cl_ret);
int cctx_class_member_idx(cctx_T *cctx, char_u *name, size_t len, class_T **cl_ret);

View File

@ -2499,12 +2499,11 @@ def Test_unlet()
assert_false(exists('g:somevar'))
unlet! g:somevar
# also works for script-local variable in legacy Vim script
s:somevar = 'legacy'
# script-local variable cannot be removed in Vim9 script
s:somevar = 'local'
assert_true(exists('s:somevar'))
unlet s:somevar
assert_false(exists('s:somevar'))
unlet! s:somevar
v9.CheckDefExecFailure(['unlet s:somevar'], 'E1081:', 1)
v9.CheckDefExecFailure(['unlet! s:somevar'], 'E1081:', 1)
if 0
unlet g:does_not_exist
@ -2677,13 +2676,21 @@ def Test_unlet()
'enddef',
'defcompile',
], 'E1081:')
v9.CheckScriptFailure([
v9.CheckScriptSuccess([
'vim9script',
'var svar = 123',
'func Func()',
' unlet s:svar',
'endfunc',
'Func()',
])
v9.CheckScriptFailure([
'vim9script',
'var svar = 123',
'def Func()',
' vim9cmd unlet s:svar',
'enddef',
'defcompile',
], 'E1081:')
v9.CheckScriptFailure([
'vim9script',

View File

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

View File

@ -99,7 +99,7 @@ check_vim9_unlet(char_u *name)
if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
{
// "unlet s:var" is allowed in legacy script.
if (*name == 's' && !script_is_vim9())
if (*name == 's' && !in_vim9script())
return OK;
semsg(_(e_cannot_unlet_str), name);
return FAIL;

View File

@ -287,15 +287,6 @@ update_script_var_block_id(char_u *name, int block_id)
sav->sav_block_id = block_id;
}
/*
* Return TRUE if the script context is Vim9 script.
*/
int
script_is_vim9(void)
{
return SCRIPT_ITEM(current_sctx.sc_sid)->sn_version == SCRIPT_VERSION_VIM9;
}
/*
* Lookup a variable (without s: prefix) in the current script.
* "cctx" is NULL at the script level, "cstack" is NULL in a function.
@ -306,7 +297,7 @@ script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
{
if (current_sctx.sc_sid <= 0)
return FAIL;
if (script_is_vim9())
if (current_script_is_vim9())
{
// Check script variables that were visible where the function was
// defined.