To: vim_dev@googlegroups.com Subject: Patch 8.2.3173 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3173 Problem: Vim9: argument types are not checked at compile time. Solution: Add more type checks. (Yegappan Lakshmanan, closes #8581) Files: src/diff.c, src/errors.h, src/evalfunc.c, src/globals.h, src/job.c, src/proto/typval.pro, src/strings.c, src/terminal.c, src/testdir/test_vim9_builtin.vim, src/typval.c *** ../vim-8.2.3172/src/diff.c 2021-05-24 14:20:50.547669201 +0200 --- src/diff.c 2021-07-17 18:08:29.488121885 +0200 *************** *** 3283,3289 **** f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { #ifdef FEAT_DIFF ! linenr_T lnum = tv_get_lnum(argvars); static linenr_T prev_lnum = 0; static varnumber_T changedtick = 0; static int fnum = 0; --- 3283,3289 ---- f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { #ifdef FEAT_DIFF ! linenr_T lnum; static linenr_T prev_lnum = 0; static varnumber_T changedtick = 0; static int fnum = 0; *************** *** 3293,3298 **** --- 3293,3306 ---- int filler_lines; int col; + if (in_vim9script() + && ((argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_NUMBER + && check_for_string_arg(argvars, 0) == FAIL) + || check_for_number_arg(argvars, 1) == FAIL)) + return; + + lnum = tv_get_lnum(argvars); if (lnum < 0) // ignore type error in {lnum} arg lnum = 0; if (lnum != prev_lnum *** ../vim-8.2.3172/src/errors.h 2021-07-15 12:48:08.807766847 +0200 --- src/errors.h 2021-07-17 18:08:29.488121885 +0200 *************** *** 502,504 **** --- 502,508 ---- INIT(= N_("E1209: Invalid value for a line number: \"%s\"")); EXTERN char e_number_required_for_argument_nr[] INIT(= N_("E1210: Number required for argument %d")); + EXTERN char e_list_required_for_argument_nr[] + INIT(= N_("E1211: List required for argument %d")); + EXTERN char e_bool_required_for_argument_nr[] + INIT(= N_("E1211: Bool required for argument %d")); *** ../vim-8.2.3172/src/evalfunc.c 2021-07-15 12:48:08.807766847 +0200 --- src/evalfunc.c 2021-07-17 18:08:29.488121885 +0200 *************** *** 499,507 **** --- 499,510 ---- static argcheck_T arg2_dict_string_or_nr[] = {arg_dict_any, arg_string_or_nr}; static argcheck_T arg2_string_dict[] = {arg_string, arg_dict_any}; static argcheck_T arg2_string_nr[] = {arg_string, arg_number}; + static argcheck_T arg2_string_bool[] = {arg_string, arg_bool}; //static argcheck_T arg2_listblob_item[] = {arg_list_or_blob, arg_item_of_prev}; static argcheck_T arg2_str_or_nr_or_list_dict[] = {arg_str_or_nr_or_list, arg_dict_any}; static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any}; + static argcheck_T arg2_string_or_nr_string[] = {arg_string_or_nr, arg_string}; + static argcheck_T arg2_string_or_nr_nr[] = {arg_string_or_nr, arg_number}; static argcheck_T arg2_chan_or_job_dict[] = {arg_chan_or_job, arg_dict_any}; static argcheck_T arg2_nr_dict_any[] = {arg_number, arg_dict_any}; //static argcheck_T arg2_string_number[] = {arg_string, arg_number}; *************** *** 510,521 **** static argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool}; static argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number}; static argcheck_T arg2_execute[] = {arg_string_or_list_string, arg_string}; - static argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list_string, arg_string}; - static argcheck_T arg2_setline[] = {arg_string_or_nr, NULL}; - static argcheck_T arg3_setbufline[] = {arg_string_or_nr, arg_string_or_nr, arg_str_or_nr_or_list}; static argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3}; static argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3}; static argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; /* * Functions that return the return type of a builtin function. --- 513,525 ---- static argcheck_T arg3_string_nr_bool[] = {arg_string, arg_number, arg_bool}; static argcheck_T arg3_string_string_nr[] = {arg_string, arg_string, arg_number}; static argcheck_T arg2_execute[] = {arg_string_or_list_string, arg_string}; static argcheck_T arg23_extend[] = {arg_list_or_dict, arg_same_as_prev, arg_extend3}; static argcheck_T arg23_extendnew[] = {arg_list_or_dict, arg_same_struct_as_prev, arg_extend3}; static argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number}; + static argcheck_T arg3_setbufline[] = {arg_string_or_nr, arg_string_or_nr, arg_str_or_nr_or_list}; + static argcheck_T arg2_setline[] = {arg_string_or_nr, NULL}; + static argcheck_T arg23_win_execute[] = {arg_number, arg_string_or_list_string, arg_string}; + static argcheck_T arg4_match_func[] = {arg_string_or_list_any, arg_string, arg_number, arg_number}; /* * Functions that return the return type of a builtin function. *************** *** 931,937 **** ret_string, JOB_FUNC(f_ch_status)}, {"changenr", 0, 0, 0, NULL, ret_number, f_changenr}, ! {"char2nr", 1, 2, FEARG_1, NULL, ret_number, f_char2nr}, {"charclass", 1, 1, FEARG_1, arg1_string, ret_number, f_charclass}, --- 935,941 ---- ret_string, JOB_FUNC(f_ch_status)}, {"changenr", 0, 0, 0, NULL, ret_number, f_changenr}, ! {"char2nr", 1, 2, FEARG_1, arg2_string_bool, ret_number, f_char2nr}, {"charclass", 1, 1, FEARG_1, arg1_string, ret_number, f_charclass}, *************** *** 987,993 **** ret_number_bool, f_did_filetype}, {"diff_filler", 1, 1, FEARG_1, arg1_string_or_nr, ret_number, f_diff_filler}, ! {"diff_hlID", 2, 2, FEARG_1, NULL, ret_number, f_diff_hlID}, {"echoraw", 1, 1, FEARG_1, arg1_string, ret_void, f_echoraw}, --- 991,997 ---- ret_number_bool, f_did_filetype}, {"diff_filler", 1, 1, FEARG_1, arg1_string_or_nr, ret_number, f_diff_filler}, ! {"diff_hlID", 2, 2, FEARG_1, arg2_string_or_nr_nr, ret_number, f_diff_hlID}, {"echoraw", 1, 1, FEARG_1, arg1_string, ret_void, f_echoraw}, *************** *** 1251,1257 **** ret_string, f_json_encode}, {"keys", 1, 1, FEARG_1, arg1_dict_any, ret_list_string, f_keys}, ! {"last_buffer_nr", 0, 0, 0, arg1_string_or_nr, // obsolete ret_number, f_last_buffer_nr}, {"len", 1, 1, FEARG_1, NULL, ret_number, f_len}, --- 1255,1261 ---- ret_string, f_json_encode}, {"keys", 1, 1, FEARG_1, arg1_dict_any, ret_list_string, f_keys}, ! {"last_buffer_nr", 0, 0, 0, NULL, // obsolete ret_number, f_last_buffer_nr}, {"len", 1, 1, FEARG_1, NULL, ret_number, f_len}, *************** *** 1297,1303 **** ret_first_cont, f_mapnew}, {"mapset", 3, 3, FEARG_1, NULL, ret_void, f_mapset}, ! {"match", 2, 4, FEARG_1, NULL, ret_any, f_match}, {"matchadd", 2, 5, FEARG_1, NULL, ret_number, f_matchadd}, --- 1301,1307 ---- ret_first_cont, f_mapnew}, {"mapset", 3, 3, FEARG_1, NULL, ret_void, f_mapset}, ! {"match", 2, 4, FEARG_1, arg4_match_func, ret_any, f_match}, {"matchadd", 2, 5, FEARG_1, NULL, ret_number, f_matchadd}, *************** *** 1307,1323 **** ret_list_string, f_matcharg}, {"matchdelete", 1, 2, FEARG_1, arg2_number, ret_number_bool, f_matchdelete}, ! {"matchend", 2, 4, FEARG_1, NULL, ret_number, f_matchend}, {"matchfuzzy", 2, 3, FEARG_1, NULL, ret_list_string, f_matchfuzzy}, {"matchfuzzypos", 2, 3, FEARG_1, NULL, ret_list_any, f_matchfuzzypos}, ! {"matchlist", 2, 4, FEARG_1, NULL, ret_list_string, f_matchlist}, ! {"matchstr", 2, 4, FEARG_1, NULL, ret_string, f_matchstr}, ! {"matchstrpos", 2, 4, FEARG_1, NULL, ret_list_any, f_matchstrpos}, {"max", 1, 1, FEARG_1, arg1_list_or_dict, ret_number, f_max}, --- 1311,1327 ---- ret_list_string, f_matcharg}, {"matchdelete", 1, 2, FEARG_1, arg2_number, ret_number_bool, f_matchdelete}, ! {"matchend", 2, 4, FEARG_1, arg4_match_func, ret_number, f_matchend}, {"matchfuzzy", 2, 3, FEARG_1, NULL, ret_list_string, f_matchfuzzy}, {"matchfuzzypos", 2, 3, FEARG_1, NULL, ret_list_any, f_matchfuzzypos}, ! {"matchlist", 2, 4, FEARG_1, arg4_match_func, ret_list_string, f_matchlist}, ! {"matchstr", 2, 4, FEARG_1, arg4_match_func, ret_string, f_matchstr}, ! {"matchstrpos", 2, 4, FEARG_1, arg4_match_func, ret_list_any, f_matchstrpos}, {"max", 1, 1, FEARG_1, arg1_list_or_dict, ret_number, f_max}, *************** *** 1413,1419 **** ret_void, JOB_FUNC(f_prompt_setcallback)}, {"prompt_setinterrupt", 2, 2, FEARG_1, NULL, ret_void, JOB_FUNC(f_prompt_setinterrupt)}, ! {"prompt_setprompt", 2, 2, FEARG_1, NULL, ret_void, JOB_FUNC(f_prompt_setprompt)}, {"prop_add", 3, 3, FEARG_1, NULL, ret_void, PROP_FUNC(f_prop_add)}, --- 1417,1423 ---- ret_void, JOB_FUNC(f_prompt_setcallback)}, {"prompt_setinterrupt", 2, 2, FEARG_1, NULL, ret_void, JOB_FUNC(f_prompt_setinterrupt)}, ! {"prompt_setprompt", 2, 2, FEARG_1, arg2_string_or_nr_string, ret_void, JOB_FUNC(f_prompt_setprompt)}, {"prop_add", 3, 3, FEARG_1, NULL, ret_void, PROP_FUNC(f_prop_add)}, *************** *** 1651,1657 **** ret_string, f_state}, {"str2float", 1, 1, FEARG_1, arg1_string, ret_float, FLOAT_FUNC(f_str2float)}, ! {"str2list", 1, 2, FEARG_1, NULL, ret_list_number, f_str2list}, {"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool, ret_number, f_str2nr}, --- 1655,1661 ---- ret_string, f_state}, {"str2float", 1, 1, FEARG_1, arg1_string, ret_float, FLOAT_FUNC(f_str2float)}, ! {"str2list", 1, 2, FEARG_1, arg2_string_bool, ret_list_number, f_str2list}, {"str2nr", 1, 3, FEARG_1, arg3_string_nr_bool, ret_number, f_str2nr}, *************** *** 1659,1665 **** ret_number, f_strcharlen}, {"strcharpart", 2, 4, FEARG_1, NULL, ret_string, f_strcharpart}, ! {"strchars", 1, 2, FEARG_1, NULL, ret_number, f_strchars}, {"strdisplaywidth", 1, 2, FEARG_1, arg2_string_nr, ret_number, f_strdisplaywidth}, --- 1663,1669 ---- ret_number, f_strcharlen}, {"strcharpart", 2, 4, FEARG_1, NULL, ret_string, f_strcharpart}, ! {"strchars", 1, 2, FEARG_1, arg2_string_bool, ret_number, f_strchars}, {"strdisplaywidth", 1, 2, FEARG_1, arg2_string_nr, ret_number, f_strdisplaywidth}, *************** *** 1709,1717 **** ret_string, f_synIDattr}, {"synIDtrans", 1, 1, FEARG_1, arg1_number, ret_number, f_synIDtrans}, ! {"synconcealed", 2, 2, 0, NULL, ret_list_any, f_synconcealed}, ! {"synstack", 2, 2, 0, NULL, ret_list_number, f_synstack}, {"system", 1, 2, FEARG_1, NULL, ret_string, f_system}, --- 1713,1721 ---- ret_string, f_synIDattr}, {"synIDtrans", 1, 1, FEARG_1, arg1_number, ret_number, f_synIDtrans}, ! {"synconcealed", 2, 2, 0, arg2_string_or_nr_nr, ret_list_any, f_synconcealed}, ! {"synstack", 2, 2, 0, arg2_string_or_nr_nr, ret_list_number, f_synstack}, {"system", 1, 2, FEARG_1, NULL, ret_string, f_system}, *************** *** 1771,1777 **** ret_list_number, TERM_FUNC(f_term_list)}, {"term_scrape", 2, 2, FEARG_1, NULL, ret_list_dict_any, TERM_FUNC(f_term_scrape)}, ! {"term_sendkeys", 2, 2, FEARG_1, NULL, ret_void, TERM_FUNC(f_term_sendkeys)}, {"term_setansicolors", 2, 2, FEARG_1, NULL, ret_void, --- 1775,1781 ---- ret_list_number, TERM_FUNC(f_term_list)}, {"term_scrape", 2, 2, FEARG_1, NULL, ret_list_dict_any, TERM_FUNC(f_term_scrape)}, ! {"term_sendkeys", 2, 2, FEARG_1, arg2_string_or_nr_string, ret_void, TERM_FUNC(f_term_sendkeys)}, {"term_setansicolors", 2, 2, FEARG_1, NULL, ret_void, *************** *** 1781,1797 **** NULL #endif }, ! {"term_setapi", 2, 2, FEARG_1, NULL, ret_void, TERM_FUNC(f_term_setapi)}, ! {"term_setkill", 2, 2, FEARG_1, NULL, ret_void, TERM_FUNC(f_term_setkill)}, ! {"term_setrestore", 2, 2, FEARG_1, NULL, ret_void, TERM_FUNC(f_term_setrestore)}, {"term_setsize", 3, 3, FEARG_1, NULL, ret_void, TERM_FUNC(f_term_setsize)}, {"term_start", 1, 2, FEARG_1, NULL, ret_number, TERM_FUNC(f_term_start)}, ! {"term_wait", 1, 2, FEARG_1, NULL, ret_void, TERM_FUNC(f_term_wait)}, {"terminalprops", 0, 0, 0, NULL, ret_dict_string, f_terminalprops}, --- 1785,1801 ---- NULL #endif }, ! {"term_setapi", 2, 2, FEARG_1, arg2_string_or_nr_string, ret_void, TERM_FUNC(f_term_setapi)}, ! {"term_setkill", 2, 2, FEARG_1, arg2_string_or_nr_string, ret_void, TERM_FUNC(f_term_setkill)}, ! {"term_setrestore", 2, 2, FEARG_1, arg2_string_or_nr_string, ret_void, TERM_FUNC(f_term_setrestore)}, {"term_setsize", 3, 3, FEARG_1, NULL, ret_void, TERM_FUNC(f_term_setsize)}, {"term_start", 1, 2, FEARG_1, NULL, ret_number, TERM_FUNC(f_term_start)}, ! {"term_wait", 1, 2, FEARG_1, arg2_string_or_nr_nr, ret_void, TERM_FUNC(f_term_wait)}, {"terminalprops", 0, 0, 0, NULL, ret_dict_string, f_terminalprops}, *************** *** 2473,2480 **** static void f_char2nr(typval_T *argvars, typval_T *rettv) { ! if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL) return; if (has_mbyte) { int utf8 = 0; --- 2477,2488 ---- static void f_char2nr(typval_T *argvars, typval_T *rettv) { ! if (in_vim9script() ! && (check_for_string_arg(argvars, 0) == FAIL ! || (argvars[1].v_type != VAR_UNKNOWN ! && check_for_bool_arg(argvars, 1) == FAIL))) return; + if (has_mbyte) { int utf8 = 0; *************** *** 6304,6309 **** --- 6312,6328 ---- rettv->vval.v_string = NULL; } + if (in_vim9script() + && ((argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_LIST + && check_for_string_arg(argvars, 0) == FAIL) + || (check_for_string_arg(argvars, 1) == FAIL) + || (argvars[2].v_type != VAR_UNKNOWN + && (check_for_number_arg(argvars, 2) == FAIL + || (argvars[3].v_type != VAR_UNKNOWN + && check_for_number_arg(argvars, 3) == FAIL))))) + goto theend; + if (argvars[0].v_type == VAR_LIST) { if ((l = argvars[0].vval.v_list) == NULL) *************** *** 8961,8966 **** --- 8980,8992 ---- rettv_list_set(rettv, NULL); + if (in_vim9script() + && ((argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_NUMBER + && check_for_string_arg(argvars, 0) == FAIL) + || check_for_number_arg(argvars, 1) == FAIL)) + return; + #if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL) lnum = tv_get_lnum(argvars); // -1 on type error col = (colnr_T)tv_get_number(&argvars[1]) - 1; // -1 on type error *************** *** 9017,9022 **** --- 9043,9055 ---- rettv_list_set(rettv, NULL); + if (in_vim9script() + && ((argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_NUMBER + && check_for_string_arg(argvars, 0) == FAIL) + || check_for_number_arg(argvars, 1) == FAIL)) + return; + #ifdef FEAT_SYN_HL lnum = tv_get_lnum(argvars); // -1 on type error col = (colnr_T)tv_get_number(&argvars[1]) - 1; // -1 on type error *** ../vim-8.2.3172/src/globals.h 2021-07-15 12:48:08.807766847 +0200 --- src/globals.h 2021-07-17 18:08:29.488121885 +0200 *************** *** 1699,1704 **** --- 1699,1705 ---- EXTERN char e_readonlysbx[] INIT(= N_("E794: Cannot set variable in the sandbox: \"%s\"")); EXTERN char e_stringreq[] INIT(= N_("E928: String required")); EXTERN char e_numberreq[] INIT(= N_("E889: Number required")); + EXTERN char e_boolreq[] INIT(= N_("E839: Number required")); EXTERN char e_emptykey[] INIT(= N_("E713: Cannot use empty key for Dictionary")); EXTERN char e_dictreq[] INIT(= N_("E715: Dictionary required")); EXTERN char e_listidx[] INIT(= N_("E684: list index out of range: %ld")); *** ../vim-8.2.3172/src/job.c 2021-06-05 20:51:34.737122348 +0200 --- src/job.c 2021-07-17 18:08:29.488121885 +0200 *************** *** 1725,1730 **** --- 1725,1737 ---- buf_T *buf; char_u *text; + if (in_vim9script() + && ((argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_NUMBER + && check_for_string_arg(argvars, 0) == FAIL) + || check_for_string_arg(argvars, 1) == FAIL)) + return; + if (check_secure()) return; buf = tv_get_buf(&argvars[0], FALSE); *** ../vim-8.2.3172/src/proto/typval.pro 2021-07-15 12:48:08.807766847 +0200 --- src/proto/typval.pro 2021-07-17 18:08:29.488121885 +0200 *************** *** 12,17 **** --- 12,19 ---- int check_for_string_arg(typval_T *args, int idx); int check_for_nonempty_string_arg(typval_T *args, int idx); int check_for_number_arg(typval_T *args, int idx); + int check_for_bool_arg(typval_T *args, int idx); + int check_for_list_arg(typval_T *args, int idx); int check_for_dict_arg(typval_T *args, int idx); char_u *tv_get_string(typval_T *varp); char_u *tv_get_string_strict(typval_T *varp); *** ../vim-8.2.3172/src/strings.c 2021-07-15 12:48:08.807766847 +0200 --- src/strings.c 2021-07-17 18:08:29.492121879 +0200 *************** *** 902,907 **** --- 902,913 ---- if (rettv_list_alloc(rettv) == FAIL) return; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_bool_arg(argvars, 1) == FAIL))) + return; + if (argvars[1].v_type != VAR_UNKNOWN) utf8 = (int)tv_get_bool_chk(&argvars[1], NULL); *************** *** 1108,1113 **** --- 1114,1125 ---- { varnumber_T skipcc = FALSE; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_bool_arg(argvars, 1) == FAIL))) + return; + if (argvars[1].v_type != VAR_UNKNOWN) skipcc = tv_get_bool(&argvars[1]); if (skipcc < 0 || skipcc > 1) *** ../vim-8.2.3172/src/terminal.c 2021-07-15 12:48:08.807766847 +0200 --- src/terminal.c 2021-07-17 18:08:29.492121879 +0200 *************** *** 6093,6102 **** void f_term_sendkeys(typval_T *argvars, typval_T *rettv UNUSED) { ! buf_T *buf = term_get_buf(argvars, "term_sendkeys()"); char_u *msg; term_T *term; if (buf == NULL) return; --- 6093,6110 ---- void f_term_sendkeys(typval_T *argvars, typval_T *rettv UNUSED) { ! buf_T *buf; char_u *msg; term_T *term; + if (in_vim9script() + && ((argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_NUMBER + && check_for_string_arg(argvars, 0) == FAIL) + || check_for_string_arg(argvars, 1) == FAIL)) + return; + + buf = term_get_buf(argvars, "term_sendkeys()"); if (buf == NULL) return; *************** *** 6193,6202 **** void f_term_setapi(typval_T *argvars, typval_T *rettv UNUSED) { ! buf_T *buf = term_get_buf(argvars, "term_setapi()"); term_T *term; char_u *api; if (buf == NULL) return; term = buf->b_term; --- 6201,6218 ---- void f_term_setapi(typval_T *argvars, typval_T *rettv UNUSED) { ! buf_T *buf; term_T *term; char_u *api; + if (in_vim9script() + && ((argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_NUMBER + && check_for_string_arg(argvars, 0) == FAIL) + || check_for_string_arg(argvars, 1) == FAIL)) + return; + + buf = term_get_buf(argvars, "term_setapi()"); if (buf == NULL) return; term = buf->b_term; *************** *** 6215,6224 **** f_term_setrestore(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { #if defined(FEAT_SESSION) ! buf_T *buf = term_get_buf(argvars, "term_setrestore()"); term_T *term; char_u *cmd; if (buf == NULL) return; term = buf->b_term; --- 6231,6248 ---- f_term_setrestore(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { #if defined(FEAT_SESSION) ! buf_T *buf; term_T *term; char_u *cmd; + if (in_vim9script() + && ((argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_NUMBER + && check_for_string_arg(argvars, 0) == FAIL) + || check_for_string_arg(argvars, 1) == FAIL)) + return; + + buf = term_get_buf(argvars, "term_setrestore()"); if (buf == NULL) return; term = buf->b_term; *************** *** 6237,6246 **** void f_term_setkill(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { ! buf_T *buf = term_get_buf(argvars, "term_setkill()"); term_T *term; char_u *how; if (buf == NULL) return; term = buf->b_term; --- 6261,6278 ---- void f_term_setkill(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { ! buf_T *buf; term_T *term; char_u *how; + if (in_vim9script() + && ((argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_NUMBER + && check_for_string_arg(argvars, 0) == FAIL) + || check_for_string_arg(argvars, 1) == FAIL)) + return; + + buf = term_get_buf(argvars, "term_setkill()"); if (buf == NULL) return; term = buf->b_term; *************** *** 6286,6293 **** void f_term_wait(typval_T *argvars, typval_T *rettv UNUSED) { ! buf_T *buf = term_get_buf(argvars, "term_wait()"); if (buf == NULL) return; if (buf->b_term->tl_job == NULL) --- 6318,6334 ---- void f_term_wait(typval_T *argvars, typval_T *rettv UNUSED) { ! buf_T *buf; ! ! if (in_vim9script() ! && ((argvars[0].v_type != VAR_STRING ! && argvars[0].v_type != VAR_NUMBER ! && check_for_string_arg(argvars, 0) == FAIL) || ! (argvars[1].v_type != VAR_UNKNOWN ! && check_for_number_arg(argvars, 1) == FAIL))) ! return; + buf = term_get_buf(argvars, "term_wait()"); if (buf == NULL) return; if (buf->b_term->tl_job == NULL) *** ../vim-8.2.3172/src/testdir/test_vim9_builtin.vim 2021-07-16 10:39:23.841410531 +0200 --- src/testdir/test_vim9_builtin.vim 2021-07-17 18:08:29.492121879 +0200 *************** *** 473,478 **** --- 473,484 ---- char2nr('あ', true)->assert_equal(12354) assert_fails('char2nr(true)', 'E1174:') + CheckDefAndScriptFailure2(['char2nr(10)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['char2nr("a", 2)'], 'E1013: Argument 2: type mismatch, expected bool but got number', 'E1211: Bool required for argument 2') + assert_equal(97, char2nr('a', 1)) + assert_equal(97, char2nr('a', 0)) + assert_equal(97, char2nr('a', true)) + assert_equal(97, char2nr('a', false)) enddef def Test_charclass() *************** *** 602,607 **** --- 608,618 ---- assert_equal(0, diff_filler('.')) enddef + def Test_diff_hlID() + CheckDefAndScriptFailure2(['diff_hlID(0z10, 1)'], 'E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['diff_hlID(1, "a")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') + enddef + def Test_echoraw() CheckDefAndScriptFailure2(['echoraw(1)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') CheckDefAndScriptFailure2(['echoraw(["x"])'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') *************** *** 1599,1604 **** --- 1610,1630 ---- delete('Xtmpfile') enddef + def Test_match() + CheckDefAndScriptFailure2(['match(0z12, "p")'], 'E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['match(["s"], [2])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['match("s", "p", "q")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') + CheckDefAndScriptFailure2(['match("s", "p", 1, "r")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4') + assert_equal(2, match('ab12cd', '12')) + assert_equal(-1, match('ab12cd', '34')) + assert_equal(6, match('ab12cd12ef', '12', 4)) + assert_equal(2, match('abcd', '..', 0, 3)) + assert_equal(1, match(['a', 'b', 'c'], 'b')) + assert_equal(-1, match(['a', 'b', 'c'], 'd')) + assert_equal(3, match(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2)) + assert_equal(5, match(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2, 2)) + enddef + def Test_matcharg() CheckDefFailure(['matcharg("x")'], 'E1013: Argument 1: type mismatch, expected number but got string') enddef *************** *** 1609,1614 **** --- 1635,1705 ---- CheckDefFailure(['matchdelete(1, "x")'], 'E1013: Argument 2: type mismatch, expected number but got string') enddef + def Test_matchend() + CheckDefAndScriptFailure2(['matchend(0z12, "p")'], 'E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['matchend(["s"], [2])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['matchend("s", "p", "q")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') + CheckDefAndScriptFailure2(['matchend("s", "p", 1, "r")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4') + assert_equal(4, matchend('ab12cd', '12')) + assert_equal(-1, matchend('ab12cd', '34')) + assert_equal(8, matchend('ab12cd12ef', '12', 4)) + assert_equal(4, matchend('abcd', '..', 0, 3)) + assert_equal(1, matchend(['a', 'b', 'c'], 'b')) + assert_equal(-1, matchend(['a', 'b', 'c'], 'd')) + assert_equal(3, matchend(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2)) + assert_equal(5, matchend(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2, 2)) + enddef + + def Test_matchlist() + CheckDefAndScriptFailure2(['matchlist(0z12, "p")'], 'E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['matchlist(["s"], [2])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['matchlist("s", "p", "q")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') + CheckDefAndScriptFailure2(['matchlist("s", "p", 1, "r")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4') + var l: list = ['12', '', '', '', '', '', '', '', '', ''] + assert_equal(l, matchlist('ab12cd', '12')) + assert_equal([], matchlist('ab12cd', '34')) + assert_equal(l, matchlist('ab12cd12ef', '12', 4)) + l[0] = 'cd' + assert_equal(l, matchlist('abcd', '..', 0, 3)) + l[0] = 'b' + assert_equal(l, matchlist(['a', 'b', 'c'], 'b')) + assert_equal([], matchlist(['a', 'b', 'c'], 'd')) + assert_equal(l, matchlist(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2)) + assert_equal(l, matchlist(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2, 2)) + enddef + + def Test_matchstr() + CheckDefAndScriptFailure2(['matchstr(0z12, "p")'], 'E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['matchstr(["s"], [2])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['matchstr("s", "p", "q")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') + CheckDefAndScriptFailure2(['matchstr("s", "p", 1, "r")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4') + assert_equal('12', matchstr('ab12cd', '12')) + assert_equal('', matchstr('ab12cd', '34')) + assert_equal('12', matchstr('ab12cd12ef', '12', 4)) + assert_equal('cd', matchstr('abcd', '..', 0, 3)) + assert_equal('b', matchstr(['a', 'b', 'c'], 'b')) + assert_equal('', matchstr(['a', 'b', 'c'], 'd')) + assert_equal('b', matchstr(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2)) + assert_equal('b', matchstr(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2, 2)) + enddef + + def Test_matchstrpos() + CheckDefAndScriptFailure2(['matchstrpos(0z12, "p")'], 'E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['matchstrpos(["s"], [2])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['matchstrpos("s", "p", "q")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') + CheckDefAndScriptFailure2(['matchstrpos("s", "p", 1, "r")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4') + assert_equal(['12', 2, 4], matchstrpos('ab12cd', '12')) + assert_equal(['', -1, -1], matchstrpos('ab12cd', '34')) + assert_equal(['12', 6, 8], matchstrpos('ab12cd12ef', '12', 4)) + assert_equal(['cd', 2, 4], matchstrpos('abcd', '..', 0, 3)) + assert_equal(['b', 1, 0, 1], matchstrpos(['a', 'b', 'c'], 'b')) + assert_equal(['', -1, -1, -1], matchstrpos(['a', 'b', 'c'], 'd')) + assert_equal(['b', 3, 0, 1], + matchstrpos(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2)) + assert_equal(['b', 5, 0, 1], + matchstrpos(['a', 'b', 'c', 'b', 'd', 'b'], 'b', 2, 2)) + enddef + def Test_max() g:flag = true var l1: list = g:flag *************** *** 1792,1797 **** --- 1883,1896 ---- endif enddef + def Test_prompt_setprompt() + if !has('channel') + CheckFeature channel + endif + CheckDefAndScriptFailure2(['prompt_setprompt([], "p")'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['prompt_setprompt(1, [])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + enddef + def Test_prop_find() CheckDefAndScriptFailure2(['prop_find([1, 2])'], 'E1013: Argument 1: type mismatch, expected dict but got list', 'E715: Dictionary required') CheckDefAndScriptFailure2(['prop_find([1, 2], "k")'], 'E1013: Argument 1: type mismatch, expected dict but got list', 'E715: Dictionary required') *************** *** 2407,2412 **** --- 2506,2519 ---- endif enddef + def Test_str2list() + CheckDefAndScriptFailure2(['str2list(10)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['str2list("a", 2)'], 'E1013: Argument 2: type mismatch, expected bool but got number', 'E1211: Bool required for argument 2') + assert_equal([97], str2list('a')) + assert_equal([97], str2list('a', 1)) + assert_equal([97], str2list('a', true)) + enddef + def Test_str2nr() str2nr("1'000'000", 10, true)->assert_equal(1000000) *************** *** 2426,2431 **** --- 2533,2543 ---- def Test_strchars() strchars("A\u20dd", true)->assert_equal(1) + CheckDefAndScriptFailure2(['strchars(10)'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['strchars("a", 2)'], 'E1013: Argument 2: type mismatch, expected bool but got number', 'E1211: Bool required for argument 2') + assert_equal(3, strchars('abc')) + assert_equal(3, strchars('abc', 1)) + assert_equal(3, strchars('abc', true)) enddef def Test_strdisplaywidth() *************** *** 2521,2526 **** --- 2633,2648 ---- CheckDefFailure(['synIDtrans("a")'], 'E1013: Argument 1: type mismatch, expected number but got string') enddef + def Test_synconcealed() + CheckDefAndScriptFailure2(['synconcealed(0z10, 1)'], 'E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['synconcealed(1, "a")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') + enddef + + def Test_synstack() + CheckDefAndScriptFailure2(['synstack(0z10, 1)'], 'E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['synstack(1, "a")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') + enddef + def Test_tabpagebuflist() CheckDefFailure(['tabpagebuflist("t")'], 'E1013: Argument 1: type mismatch, expected number but got string') assert_equal([bufnr('')], tabpagebuflist()) *************** *** 2607,2612 **** --- 2729,2757 ---- endif enddef + def Test_term_sendkeys() + CheckRunVimInTerminal + CheckDefAndScriptFailure2(['term_sendkeys([], "p")'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['term_sendkeys(1, [])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + enddef + + def Test_term_setapi() + CheckRunVimInTerminal + CheckDefAndScriptFailure2(['term_setapi([], "p")'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['term_setapi(1, [])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + enddef + + def Test_term_setkill() + CheckRunVimInTerminal + CheckDefAndScriptFailure2(['term_setkill([], "p")'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['term_setkill(1, [])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + enddef + + def Test_term_setrestore() + CheckRunVimInTerminal + CheckDefAndScriptFailure2(['term_setrestore([], "p")'], 'E1013: Argument 1: type mismatch, expected string but got list', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['term_setrestore(1, [])'], 'E1013: Argument 2: type mismatch, expected string but got list', 'E1174: String required for argument 2') + enddef def Test_term_start() if !has('terminal') MissingFeature 'terminal' *************** *** 2619,2624 **** --- 2764,2775 ---- endif enddef + def Test_term_wait() + CheckRunVimInTerminal + CheckDefAndScriptFailure2(['term_wait(0z10, 1)'], 'E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['term_wait(1, "a")'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2') + enddef + def Test_test_alloc_fail() CheckDefAndScriptFailure2(['test_alloc_fail("a", 10, 20)'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E474: Invalid argument') CheckDefAndScriptFailure2(['test_alloc_fail(10, "b", 20)'], 'E1013: Argument 2: type mismatch, expected number but got string', 'E474: Invalid argument') *** ../vim-8.2.3172/src/typval.c 2021-07-15 12:48:08.811766844 +0200 --- src/typval.c 2021-07-17 18:08:29.492121879 +0200 *************** *** 352,358 **** #endif /* ! * Give an error and return FAIL unless "tv" is a string. */ int check_for_string_arg(typval_T *args, int idx) --- 352,358 ---- #endif /* ! * Give an error and return FAIL unless "args[idx]" is a string. */ int check_for_string_arg(typval_T *args, int idx) *************** *** 385,391 **** } /* ! * Give an error and return FAIL unless "tv" is a number. */ int check_for_number_arg(typval_T *args, int idx) --- 385,391 ---- } /* ! * Give an error and return FAIL unless "args[idx]" is a number. */ int check_for_number_arg(typval_T *args, int idx) *************** *** 402,408 **** } /* ! * Give an error and return FAIL unless "tv" is a dict. */ int check_for_dict_arg(typval_T *args, int idx) --- 402,445 ---- } /* ! * Give an error and return FAIL unless "args[idx]" is a bool. ! */ ! int ! check_for_bool_arg(typval_T *args, int idx) ! { ! if (args[idx].v_type != VAR_BOOL ! && !(args[idx].v_type == VAR_NUMBER ! && (args[idx].vval.v_number == 0 ! || args[idx].vval.v_number == 1))) ! { ! if (idx >= 0) ! semsg(_(e_bool_required_for_argument_nr), idx + 1); ! else ! emsg(_(e_boolreq)); ! return FAIL; ! } ! return OK; ! } ! ! /* ! * Give an error and return FAIL unless "args[idx]" is a list. ! */ ! int ! check_for_list_arg(typval_T *args, int idx) ! { ! if (args[idx].v_type != VAR_LIST) ! { ! if (idx >= 0) ! semsg(_(e_list_required_for_argument_nr), idx + 1); ! else ! emsg(_(e_listreq)); ! return FAIL; ! } ! return OK; ! } ! ! /* ! * Give an error and return FAIL unless "args[idx]" is a dict. */ int check_for_dict_arg(typval_T *args, int idx) *** ../vim-8.2.3172/src/version.c 2021-07-16 10:39:23.841410531 +0200 --- src/version.c 2021-07-17 18:09:49.588034766 +0200 *************** *** 757,758 **** --- 757,760 ---- { /* Add new patch number below this line */ + /**/ + 3173, /**/ -- "The question of whether computers can think is just like the question of whether submarines can swim." -- Edsger W. Dijkstra /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///