summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-01-11 11:58:19 +0000
committerBram Moolenaar <Bram@vim.org>2022-01-11 11:58:19 +0000
commit19db9e6ba710ca32f0f5e0c2ca2ba69f8228b833 (patch)
tree985829b16070d2e27065d670fcb2ed42a03e160e
parent762838218feb223f53ab87d80928dadd991a1746 (diff)
downloadvim-git-19db9e6ba710ca32f0f5e0c2ca2ba69f8228b833.tar.gz
patch 8.2.4059: Vim9: an expression of a map cannot access script-local itemsv8.2.4059
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.
-rw-r--r--src/getchar.c6
-rw-r--r--src/map.c19
-rw-r--r--src/proto/map.pro2
-rw-r--r--src/testdir/test_vim9_import.vim38
-rw-r--r--src/version.c2
5 files changed, 58 insertions, 9 deletions
diff --git a/src/getchar.c b/src/getchar.c
index 6fecc1a28..08c1a9557 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -2785,7 +2785,6 @@ handle_mapping(
int save_m_noremap;
int save_m_silent;
char_u *save_m_keys;
- char_u *save_m_str;
#else
# define save_m_noremap mp->m_noremap
# define save_m_silent mp->m_silent
@@ -2834,7 +2833,6 @@ handle_mapping(
save_m_noremap = mp->m_noremap;
save_m_silent = mp->m_silent;
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
@@ -2851,8 +2849,7 @@ handle_mapping(
may_garbage_collect = FALSE;
save_m_keys = vim_strsave(mp->m_keys);
- save_m_str = vim_strsave(mp->m_str);
- map_str = eval_map_expr(save_m_str, NUL);
+ map_str = eval_map_expr(mp, NUL);
// The mapping may do anything, but we expect it to take care of
// redrawing. Do put the cursor back where it was.
@@ -2900,7 +2897,6 @@ handle_mapping(
}
#ifdef FEAT_EVAL
vim_free(save_m_keys);
- vim_free(save_m_str);
#endif
*keylenp = keylen;
if (i == FAIL)
diff --git a/src/map.c b/src/map.c
index 336425afe..181aa654b 100644
--- a/src/map.c
+++ b/src/map.c
@@ -260,6 +260,7 @@ map_add(
{
mp->m_script_ctx.sc_sid = sid;
mp->m_script_ctx.sc_lnum = lnum;
+ mp->m_script_ctx.sc_version = in_vim9script() ? SCRIPT_VERSION_VIM9 : 0;
}
else
{
@@ -1565,7 +1566,7 @@ check_abbr(
}
#ifdef FEAT_EVAL
if (mp->m_expr)
- s = eval_map_expr(mp->m_str, c);
+ s = eval_map_expr(mp, c);
else
#endif
s = mp->m_str;
@@ -1600,7 +1601,7 @@ check_abbr(
*/
char_u *
eval_map_expr(
- char_u *str,
+ mapblock_T *mp,
int c) // NUL or typed character for abbreviation
{
char_u *res;
@@ -1609,10 +1610,12 @@ eval_map_expr(
pos_T save_cursor;
int save_msg_col;
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
// typeahead.
- expr = vim_strsave(str);
+ expr = vim_strsave(mp->m_str);
if (expr == NULL)
return NULL;
vim_unescape_csi(expr);
@@ -1625,12 +1628,22 @@ eval_map_expr(
save_cursor = curwin->w_cursor;
save_msg_col = msg_col;
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);
+
--textwinlock;
--ex_normal_lock;
curwin->w_cursor = save_cursor;
msg_col = save_msg_col;
msg_row = save_msg_row;
+ current_sctx.sc_sid = save_sctx_sid;
+ current_sctx.sc_version = save_sctx_version;
vim_free(expr);
diff --git a/src/proto/map.pro b/src/proto/map.pro
index 359262354..42ebd4b61 100644
--- a/src/proto/map.pro
+++ b/src/proto/map.pro
@@ -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);
int ExpandMappings(regmatch_T *regmatch, int *num_file, char_u ***file);
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);
void vim_unescape_csi(char_u *p);
int makemap(FILE *fd, buf_T *buf);
diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim
index 395265bbd..ddf5b82b6 100644
--- a/src/testdir/test_vim9_import.vim
+++ b/src/testdir/test_vim9_import.vim
@@ -1184,6 +1184,44 @@ def Test_vim9script_autoload()
&rtp = save_rtp
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()
var lines =<< trim END
vim9script autoload
diff --git a/src/version.c b/src/version.c
index f5e2ee0c2..27f63212a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4059,
+/**/
4058,
/**/
4057,