forked from aniani/vim
patch 8.2.4059: Vim9: an expression of a map cannot access script-local items
Problem: Vim9: an expression of a map cannot access script-local items. (Maxim Kim) Solution: Use the script ID of where the map was defined.
This commit is contained in:
@@ -2785,7 +2785,6 @@ handle_mapping(
|
|||||||
int save_m_noremap;
|
int save_m_noremap;
|
||||||
int save_m_silent;
|
int save_m_silent;
|
||||||
char_u *save_m_keys;
|
char_u *save_m_keys;
|
||||||
char_u *save_m_str;
|
|
||||||
#else
|
#else
|
||||||
# define save_m_noremap mp->m_noremap
|
# define save_m_noremap mp->m_noremap
|
||||||
# define save_m_silent mp->m_silent
|
# define save_m_silent mp->m_silent
|
||||||
@@ -2834,7 +2833,6 @@ handle_mapping(
|
|||||||
save_m_noremap = mp->m_noremap;
|
save_m_noremap = mp->m_noremap;
|
||||||
save_m_silent = mp->m_silent;
|
save_m_silent = mp->m_silent;
|
||||||
save_m_keys = NULL; // only saved when needed
|
save_m_keys = NULL; // only saved when needed
|
||||||
save_m_str = NULL; // only saved when needed
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle ":map <expr>": evaluate the {rhs} as an expression. Also
|
* Handle ":map <expr>": evaluate the {rhs} as an expression. Also
|
||||||
@@ -2851,8 +2849,7 @@ handle_mapping(
|
|||||||
may_garbage_collect = FALSE;
|
may_garbage_collect = FALSE;
|
||||||
|
|
||||||
save_m_keys = vim_strsave(mp->m_keys);
|
save_m_keys = vim_strsave(mp->m_keys);
|
||||||
save_m_str = vim_strsave(mp->m_str);
|
map_str = eval_map_expr(mp, NUL);
|
||||||
map_str = eval_map_expr(save_m_str, NUL);
|
|
||||||
|
|
||||||
// The mapping may do anything, but we expect it to take care of
|
// The mapping may do anything, but we expect it to take care of
|
||||||
// redrawing. Do put the cursor back where it was.
|
// redrawing. Do put the cursor back where it was.
|
||||||
@@ -2900,7 +2897,6 @@ handle_mapping(
|
|||||||
}
|
}
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
vim_free(save_m_keys);
|
vim_free(save_m_keys);
|
||||||
vim_free(save_m_str);
|
|
||||||
#endif
|
#endif
|
||||||
*keylenp = keylen;
|
*keylenp = keylen;
|
||||||
if (i == FAIL)
|
if (i == FAIL)
|
||||||
|
19
src/map.c
19
src/map.c
@@ -260,6 +260,7 @@ map_add(
|
|||||||
{
|
{
|
||||||
mp->m_script_ctx.sc_sid = sid;
|
mp->m_script_ctx.sc_sid = sid;
|
||||||
mp->m_script_ctx.sc_lnum = lnum;
|
mp->m_script_ctx.sc_lnum = lnum;
|
||||||
|
mp->m_script_ctx.sc_version = in_vim9script() ? SCRIPT_VERSION_VIM9 : 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1565,7 +1566,7 @@ check_abbr(
|
|||||||
}
|
}
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
if (mp->m_expr)
|
if (mp->m_expr)
|
||||||
s = eval_map_expr(mp->m_str, c);
|
s = eval_map_expr(mp, c);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
s = mp->m_str;
|
s = mp->m_str;
|
||||||
@@ -1600,7 +1601,7 @@ check_abbr(
|
|||||||
*/
|
*/
|
||||||
char_u *
|
char_u *
|
||||||
eval_map_expr(
|
eval_map_expr(
|
||||||
char_u *str,
|
mapblock_T *mp,
|
||||||
int c) // NUL or typed character for abbreviation
|
int c) // NUL or typed character for abbreviation
|
||||||
{
|
{
|
||||||
char_u *res;
|
char_u *res;
|
||||||
@@ -1609,10 +1610,12 @@ eval_map_expr(
|
|||||||
pos_T save_cursor;
|
pos_T save_cursor;
|
||||||
int save_msg_col;
|
int save_msg_col;
|
||||||
int save_msg_row;
|
int save_msg_row;
|
||||||
|
scid_T save_sctx_sid = current_sctx.sc_sid;
|
||||||
|
int save_sctx_version = current_sctx.sc_version;
|
||||||
|
|
||||||
// Remove escaping of CSI, because "str" is in a format to be used as
|
// Remove escaping of CSI, because "str" is in a format to be used as
|
||||||
// typeahead.
|
// typeahead.
|
||||||
expr = vim_strsave(str);
|
expr = vim_strsave(mp->m_str);
|
||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
vim_unescape_csi(expr);
|
vim_unescape_csi(expr);
|
||||||
@@ -1625,12 +1628,22 @@ eval_map_expr(
|
|||||||
save_cursor = curwin->w_cursor;
|
save_cursor = curwin->w_cursor;
|
||||||
save_msg_col = msg_col;
|
save_msg_col = msg_col;
|
||||||
save_msg_row = msg_row;
|
save_msg_row = msg_row;
|
||||||
|
if (mp->m_script_ctx.sc_version == SCRIPT_VERSION_VIM9)
|
||||||
|
{
|
||||||
|
current_sctx.sc_sid = mp->m_script_ctx.sc_sid;
|
||||||
|
current_sctx.sc_version = SCRIPT_VERSION_VIM9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: the evaluation may make "mp" invalid.
|
||||||
p = eval_to_string(expr, FALSE);
|
p = eval_to_string(expr, FALSE);
|
||||||
|
|
||||||
--textwinlock;
|
--textwinlock;
|
||||||
--ex_normal_lock;
|
--ex_normal_lock;
|
||||||
curwin->w_cursor = save_cursor;
|
curwin->w_cursor = save_cursor;
|
||||||
msg_col = save_msg_col;
|
msg_col = save_msg_col;
|
||||||
msg_row = save_msg_row;
|
msg_row = save_msg_row;
|
||||||
|
current_sctx.sc_sid = save_sctx_sid;
|
||||||
|
current_sctx.sc_version = save_sctx_version;
|
||||||
|
|
||||||
vim_free(expr);
|
vim_free(expr);
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ int map_to_exists_mode(char_u *rhs, int mode, int abbr);
|
|||||||
char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg, int forceit, int isabbrev, int isunmap, cmdidx_T cmdidx);
|
char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg, int forceit, int isabbrev, int isunmap, cmdidx_T cmdidx);
|
||||||
int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file);
|
int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file);
|
||||||
int check_abbr(int c, char_u *ptr, int col, int mincol);
|
int check_abbr(int c, char_u *ptr, int col, int mincol);
|
||||||
char_u *eval_map_expr(char_u *str, int c);
|
char_u *eval_map_expr(mapblock_T *mp, int c);
|
||||||
char_u *vim_strsave_escape_csi(char_u *p);
|
char_u *vim_strsave_escape_csi(char_u *p);
|
||||||
void vim_unescape_csi(char_u *p);
|
void vim_unescape_csi(char_u *p);
|
||||||
int makemap(FILE *fd, buf_T *buf);
|
int makemap(FILE *fd, buf_T *buf);
|
||||||
|
@@ -1184,6 +1184,44 @@ def Test_vim9script_autoload()
|
|||||||
&rtp = save_rtp
|
&rtp = save_rtp
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_autoload_mapping()
|
||||||
|
mkdir('Xdir/autoload', 'p')
|
||||||
|
var save_rtp = &rtp
|
||||||
|
exe 'set rtp^=' .. getcwd() .. '/Xdir'
|
||||||
|
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script autoload
|
||||||
|
|
||||||
|
g:toggle_loaded = 'yes'
|
||||||
|
|
||||||
|
export def Toggle(): string
|
||||||
|
return ":g:toggle_called = 'yes'\<CR>"
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
writefile(lines, 'Xdir/autoload/toggle.vim')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
import autoload 'toggle.vim'
|
||||||
|
|
||||||
|
nnoremap <silent> <expr> tt toggle.Toggle()
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
assert_false(exists("g:toggle_loaded"))
|
||||||
|
assert_false(exists("g:toggle_called"))
|
||||||
|
|
||||||
|
feedkeys("tt", 'xt')
|
||||||
|
assert_equal('yes', g:toggle_loaded)
|
||||||
|
assert_equal('yes', g:toggle_called)
|
||||||
|
|
||||||
|
nunmap tt
|
||||||
|
unlet g:toggle_loaded
|
||||||
|
unlet g:toggle_called
|
||||||
|
delete('Xdir', 'rf')
|
||||||
|
&rtp = save_rtp
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_vim9script_autoload_fails()
|
def Test_vim9script_autoload_fails()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script autoload
|
vim9script autoload
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
4059,
|
||||||
/**/
|
/**/
|
||||||
4058,
|
4058,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user