To: vim_dev@googlegroups.com Subject: Patch 8.2.3211 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3211 Problem: Vim9: argument types are not checked at compile time. Solution: Add several more type checks. Fix type check for matchaddpos(). (Yegappan Lakshmanan, closes #8619) Files: src/channel.c, src/evalfunc.c, src/evalvars.c, src/if_cscope.c, src/job.c, src/proto/typval.pro, src/testdir/test_vim9_builtin.vim, src/time.c, src/typval.c *** ../vim-8.2.3210/src/channel.c 2021-07-20 17:51:48.239744107 +0200 --- src/channel.c 2021-07-24 16:10:53.142934592 +0200 *************** *** 4890,4898 **** void f_ch_log(typval_T *argvars, typval_T *rettv UNUSED) { ! char_u *msg = tv_get_string(&argvars[0]); channel_T *channel = NULL; if (argvars[1].v_type != VAR_UNKNOWN) channel = get_channel_arg(&argvars[1], FALSE, FALSE, 0); --- 4890,4904 ---- void f_ch_log(typval_T *argvars, typval_T *rettv UNUSED) { ! char_u *msg; channel_T *channel = NULL; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || check_for_opt_chan_or_job_arg(argvars, 1) == FAIL)) + return; + + msg = tv_get_string(&argvars[0]); if (argvars[1].v_type != VAR_UNKNOWN) channel = get_channel_arg(&argvars[1], FALSE, FALSE, 0); *** ../vim-8.2.3210/src/evalfunc.c 2021-07-23 20:37:52.018322443 +0200 --- src/evalfunc.c 2021-07-24 16:10:53.146934583 +0200 *************** *** 542,548 **** } /* ! * Check "type" which is the third argument of extend(). */ static int arg_extend3(type_T *type, argcontext_T *context) --- 542,549 ---- } /* ! * Check "type" which is the third argument of extend() (number or string or ! * any) */ static int arg_extend3(type_T *type, argcontext_T *context) *************** *** 557,563 **** } /* ! * Check "type" which is the second argument of remove(). */ static int arg_remove2(type_T *type, argcontext_T *context) --- 558,565 ---- } /* ! * Check "type" which is the second argument of remove() (number or string or ! * any) */ static int arg_remove2(type_T *type, argcontext_T *context) *************** *** 572,578 **** } /* ! * Check "type" which is the first argument of repeat(). */ static int arg_repeat1(type_T *type, argcontext_T *context) --- 574,581 ---- } /* ! * Check "type" which is the first argument of repeat() (string or number or ! * list or any) */ static int arg_repeat1(type_T *type, argcontext_T *context) *************** *** 588,594 **** } /* ! * Check "type" which is the first argument of slice(). */ static int arg_slice1(type_T *type, argcontext_T *context) --- 591,598 ---- } /* ! * Check "type" which is the first argument of slice() (list or blob or string ! * or any) */ static int arg_slice1(type_T *type, argcontext_T *context) *************** *** 604,610 **** } /* ! * Check "type" which is the first argument of count(). */ static int arg_count1(type_T *type, argcontext_T *context) --- 608,615 ---- } /* ! * Check "type" which is the first argument of count() (string or list or dict ! * or any) */ static int arg_count1(type_T *type, argcontext_T *context) *************** *** 620,626 **** } /* ! * Check "type" which is the first argument of cursor(). */ static int arg_cursor1(type_T *type, argcontext_T *context) --- 625,632 ---- } /* ! * Check "type" which is the first argument of cursor() (number or string or ! * list or any) */ static int arg_cursor1(type_T *type, argcontext_T *context) *************** *** 666,671 **** --- 672,678 ---- static argcheck_T arg2_string_bool[] = {arg_string, arg_bool}; static argcheck_T arg2_string_or_list_dict[] = {arg_string_or_list_any, arg_dict_any}; static argcheck_T arg2_string_string_or_number[] = {arg_string, arg_string_or_nr}; + static argcheck_T arg2_string_chan_or_job[] = {arg_string, arg_chan_or_job}; static argcheck_T arg2_list_number[] = {arg_list_number, arg_list_number}; static argcheck_T arg2_list_number_bool[] = {arg_list_number, arg_bool}; static argcheck_T arg2_list_any_string[] = {arg_list_any, arg_string}; *************** *** 690,700 **** --- 697,710 ---- static argcheck_T arg2_buffer_bool[] = {arg_buffer, arg_bool}; static argcheck_T arg2_buffer_lnum[] = {arg_buffer, arg_lnum}; static argcheck_T arg2_buffer_list_any[] = {arg_buffer, arg_list_any}; + static argcheck_T arg2_buffer_any[] = {arg_buffer, NULL}; static argcheck_T arg3_string[] = {arg_string, arg_string, arg_string}; static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number}; static argcheck_T arg3_number_number_dict[] = {arg_number, arg_number, arg_dict_any}; + static argcheck_T arg3_number_string_string[] = {arg_number, arg_string, arg_string}; static argcheck_T arg3_number_string_any[] = {arg_number, arg_string, NULL}; static argcheck_T arg3_number_string_buffer[] = {arg_number, arg_string, arg_buffer}; + static argcheck_T arg3_number_any_dict[] = {arg_number, NULL, arg_dict_any}; 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 arg3_string_string_dict[] = {arg_string, arg_string, arg_dict_any}; *************** *** 707,712 **** --- 717,723 ---- static argcheck_T arg3_buffer_lnum_lnum[] = {arg_buffer, arg_lnum, arg_lnum}; static argcheck_T arg3_buffer_number_number[] = {arg_buffer, arg_number, arg_number}; static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_any}; + static argcheck_T arg3_buffer_string_any[] = {arg_buffer, arg_string, NULL}; static argcheck_T arg4_number_number_string_any[] = {arg_number, arg_number, arg_string, NULL}; static argcheck_T arg4_string_string_number_string[] = {arg_string, arg_string, arg_number, arg_string}; static argcheck_T arg5_number[] = {arg_number, arg_number, arg_number, arg_number, arg_number}; *************** *** 726,737 **** static argcheck_T arg2_mapfilter[] = {arg_list_or_dict_or_blob, NULL}; static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool, arg_bool}; static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number, arg_number, arg_dict_any}; ! static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_number, arg_number, arg_number, arg_dict_any}; static argcheck_T arg23_reduce[] = {arg_list_or_blob, NULL, NULL}; static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string, arg_number}; static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob, arg_remove2, arg_number}; static argcheck_T arg2_repeat[] = {arg_repeat1, arg_number}; static argcheck_T arg15_search[] = {arg_string, arg_string, arg_number, arg_number, NULL}; static argcheck_T arg3_setbufline[] = {arg_buffer, arg_lnum, arg_str_or_nr_or_list}; static argcheck_T arg2_setline[] = {arg_lnum, NULL}; static argcheck_T arg24_setloclist[] = {arg_number, arg_list_any, arg_string, arg_dict_any}; --- 737,749 ---- static argcheck_T arg2_mapfilter[] = {arg_list_or_dict_or_blob, NULL}; static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool, arg_bool}; static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number, arg_number, arg_dict_any}; ! static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any, arg_number, arg_number, arg_dict_any}; static argcheck_T arg23_reduce[] = {arg_list_or_blob, NULL, NULL}; static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string, arg_number}; static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob, arg_remove2, arg_number}; static argcheck_T arg2_repeat[] = {arg_repeat1, arg_number}; static argcheck_T arg15_search[] = {arg_string, arg_string, arg_number, arg_number, NULL}; + static argcheck_T arg37_searchpair[] = {arg_string, arg_string, arg_string, arg_string, NULL, arg_number, arg_number}; static argcheck_T arg3_setbufline[] = {arg_buffer, arg_lnum, arg_str_or_nr_or_list}; static argcheck_T arg2_setline[] = {arg_lnum, NULL}; static argcheck_T arg24_setloclist[] = {arg_number, arg_list_any, arg_string, arg_dict_any}; *************** *** 1146,1152 **** ret_job, JOB_FUNC(f_ch_getjob)}, {"ch_info", 1, 1, FEARG_1, arg1_chan_or_job, ret_dict_any, JOB_FUNC(f_ch_info)}, ! {"ch_log", 1, 2, FEARG_1, NULL, ret_void, JOB_FUNC(f_ch_log)}, {"ch_logfile", 1, 2, FEARG_1, arg2_string, ret_void, JOB_FUNC(f_ch_logfile)}, --- 1158,1164 ---- ret_job, JOB_FUNC(f_ch_getjob)}, {"ch_info", 1, 1, FEARG_1, arg1_chan_or_job, ret_dict_any, JOB_FUNC(f_ch_info)}, ! {"ch_log", 1, 2, FEARG_1, arg2_string_chan_or_job, ret_void, JOB_FUNC(f_ch_log)}, {"ch_logfile", 1, 2, FEARG_1, arg2_string, ret_void, JOB_FUNC(f_ch_logfile)}, *************** *** 1202,1208 **** ret_float, FLOAT_FUNC(f_cosh)}, {"count", 2, 4, FEARG_1, arg24_count, ret_number, f_count}, ! {"cscope_connection",0,3, 0, NULL, ret_number, f_cscope_connection}, {"cursor", 1, 3, FEARG_1, arg13_cursor, ret_number, f_cursor}, --- 1214,1220 ---- ret_float, FLOAT_FUNC(f_cosh)}, {"count", 2, 4, FEARG_1, arg24_count, ret_number, f_count}, ! {"cscope_connection",0,3, 0, arg3_number_string_string, ret_number, f_cscope_connection}, {"cursor", 1, 3, FEARG_1, arg13_cursor, ret_number, f_cursor}, *************** *** 1310,1316 **** ret_list_dict_any, f_getbufinfo}, {"getbufline", 2, 3, FEARG_1, arg3_buffer_lnum_lnum, ret_list_string, f_getbufline}, ! {"getbufvar", 2, 3, FEARG_1, NULL, ret_any, f_getbufvar}, {"getchangelist", 0, 1, FEARG_1, arg1_buffer, ret_list_any, f_getchangelist}, --- 1322,1328 ---- ret_list_dict_any, f_getbufinfo}, {"getbufline", 2, 3, FEARG_1, arg3_buffer_lnum_lnum, ret_list_string, f_getbufline}, ! {"getbufvar", 2, 3, FEARG_1, arg3_buffer_string_any, ret_any, f_getbufvar}, {"getchangelist", 0, 1, FEARG_1, arg1_buffer, ret_list_any, f_getchangelist}, *************** *** 1650,1658 **** ret_string, f_printf}, {"prompt_getprompt", 1, 1, FEARG_1, arg1_buffer, ret_string, JOB_FUNC(f_prompt_getprompt)}, ! {"prompt_setcallback", 2, 2, FEARG_1, NULL, 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_buffer_string, ret_void, JOB_FUNC(f_prompt_setprompt)}, --- 1662,1670 ---- ret_string, f_printf}, {"prompt_getprompt", 1, 1, FEARG_1, arg1_buffer, ret_string, JOB_FUNC(f_prompt_getprompt)}, ! {"prompt_setcallback", 2, 2, FEARG_1, arg2_buffer_any, ret_void, JOB_FUNC(f_prompt_setcallback)}, ! {"prompt_setinterrupt", 2, 2, FEARG_1, arg2_buffer_any, ret_void, JOB_FUNC(f_prompt_setinterrupt)}, {"prompt_setprompt", 2, 2, FEARG_1, arg2_buffer_string, ret_void, JOB_FUNC(f_prompt_setprompt)}, *************** *** 1780,1788 **** ret_dict_any, f_searchcount}, {"searchdecl", 1, 3, FEARG_1, arg3_string_bool_bool, ret_number_bool, f_searchdecl}, ! {"searchpair", 3, 7, 0, NULL, ret_number, f_searchpair}, ! {"searchpairpos", 3, 7, 0, NULL, ret_list_number, f_searchpairpos}, {"searchpos", 1, 5, FEARG_1, arg15_search, ret_list_number, f_searchpos}, --- 1792,1800 ---- ret_dict_any, f_searchcount}, {"searchdecl", 1, 3, FEARG_1, arg3_string_bool_bool, ret_number_bool, f_searchdecl}, ! {"searchpair", 3, 7, 0, arg37_searchpair, ret_number, f_searchpair}, ! {"searchpairpos", 3, 7, 0, arg37_searchpair, ret_list_number, f_searchpairpos}, {"searchpos", 1, 5, FEARG_1, arg15_search, ret_list_number, f_searchpos}, *************** *** 1792,1798 **** ret_string, f_serverlist}, {"setbufline", 3, 3, FEARG_3, arg3_setbufline, ret_number_bool, f_setbufline}, ! {"setbufvar", 3, 3, FEARG_3, NULL, ret_void, f_setbufvar}, {"setcellwidths", 1, 1, FEARG_1, arg1_list_any, ret_void, f_setcellwidths}, --- 1804,1810 ---- ret_string, f_serverlist}, {"setbufline", 3, 3, FEARG_3, arg3_setbufline, ret_number_bool, f_setbufline}, ! {"setbufvar", 3, 3, FEARG_3, arg3_buffer_string_any, ret_void, f_setbufvar}, {"setcellwidths", 1, 1, FEARG_1, arg1_list_any, ret_void, f_setcellwidths}, *************** *** 1950,1956 **** ret_string, f_swapname}, {"synID", 3, 3, 0, arg3_lnum_number_bool, ret_number, f_synID}, ! {"synIDattr", 2, 3, FEARG_1, NULL, ret_string, f_synIDattr}, {"synIDtrans", 1, 1, FEARG_1, arg1_number, ret_number, f_synIDtrans}, --- 1962,1968 ---- ret_string, f_swapname}, {"synID", 3, 3, 0, arg3_lnum_number_bool, ret_number, f_synID}, ! {"synIDattr", 2, 3, FEARG_1, arg3_number_string_string, ret_string, f_synIDattr}, {"synIDtrans", 1, 1, FEARG_1, arg1_number, ret_number, f_synIDtrans}, *************** *** 2102,2108 **** ret_list_dict_any, TIMER_FUNC(f_timer_info)}, {"timer_pause", 2, 2, FEARG_1, arg2_number_bool, ret_void, TIMER_FUNC(f_timer_pause)}, ! {"timer_start", 2, 3, FEARG_1, NULL, ret_number, TIMER_FUNC(f_timer_start)}, {"timer_stop", 1, 1, FEARG_1, arg1_number, ret_void, TIMER_FUNC(f_timer_stop)}, --- 2114,2120 ---- ret_list_dict_any, TIMER_FUNC(f_timer_info)}, {"timer_pause", 2, 2, FEARG_1, arg2_number_bool, ret_void, TIMER_FUNC(f_timer_pause)}, ! {"timer_start", 2, 3, FEARG_1, arg3_number_any_dict, ret_number, TIMER_FUNC(f_timer_start)}, {"timer_stop", 1, 1, FEARG_1, arg1_number, ret_void, TIMER_FUNC(f_timer_stop)}, *************** *** 8044,8049 **** --- 8056,8073 ---- long lnum_stop = 0; long time_limit = 0; + if (in_vim9script() + && (check_for_string_arg(argvars, 0) == FAIL + || check_for_string_arg(argvars, 1) == FAIL + || check_for_string_arg(argvars, 2) == FAIL + || check_for_opt_string_arg(argvars, 3) == FAIL + || (argvars[3].v_type != VAR_UNKNOWN + && argvars[4].v_type != VAR_UNKNOWN + && (check_for_opt_number_arg(argvars, 5) == FAIL + || (argvars[5].v_type != VAR_UNKNOWN + && check_for_opt_number_arg(argvars, 6) == FAIL))))) + goto theend; + // Get the three pattern arguments: start, middle, end. Will result in an // error if not a valid argument. spat = tv_get_string_chk(&argvars[0]); *************** *** 9245,9250 **** --- 9269,9281 ---- char_u modebuf[NUMBUFLEN]; int modec; + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || (check_for_string_arg(argvars, 1) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_opt_string_arg(argvars, 2) == FAIL)))) + return; + id = (int)tv_get_number(&argvars[0]); what = tv_get_string(&argvars[1]); if (argvars[2].v_type != VAR_UNKNOWN) *** ../vim-8.2.3210/src/evalvars.c 2021-07-22 15:14:21.723834160 +0200 --- src/evalvars.c 2021-07-24 16:10:53.146934583 +0200 *************** *** 4112,4117 **** --- 4112,4122 ---- dictitem_T *v; int done = FALSE; + if (in_vim9script() + && (check_for_buffer_arg(argvars, 0) == FAIL + || check_for_string_arg(argvars, 1) == FAIL)) + return; + varname = tv_get_string_chk(&argvars[1]); buf = tv_get_buf_from_arg(&argvars[0]); *************** *** 4251,4256 **** --- 4256,4267 ---- if (check_secure()) return; + + if (in_vim9script() + && (check_for_buffer_arg(argvars, 0) == FAIL + || check_for_string_arg(argvars, 1) == FAIL)) + return; + varname = tv_get_string_chk(&argvars[1]); buf = tv_get_buf_from_arg(&argvars[0]); varp = &argvars[2]; *** ../vim-8.2.3210/src/if_cscope.c 2021-07-24 13:57:25.477296535 +0200 --- src/if_cscope.c 2021-07-24 16:10:53.146934583 +0200 *************** *** 2496,2501 **** --- 2496,2509 ---- char_u *prepend = NULL; char_u buf[NUMBUFLEN]; + if (in_vim9script() + && (check_for_opt_number_arg(argvars, 0) == FAIL + || (argvars[0].v_type != VAR_UNKNOWN + && (check_for_opt_string_arg(argvars, 1) == FAIL + || (argvars[1].v_type != VAR_UNKNOWN + && check_for_opt_string_arg(argvars, 2) == FAIL))))) + return; + if (argvars[0].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_UNKNOWN) { *** ../vim-8.2.3210/src/job.c 2021-07-23 20:37:52.018322443 +0200 --- src/job.c 2021-07-24 16:10:53.146934583 +0200 *************** *** 1658,1663 **** --- 1658,1667 ---- if (check_secure()) return; + + if (in_vim9script() && check_for_buffer_arg(argvars, 0) == FAIL) + return; + buf = tv_get_buf(&argvars[0], FALSE); if (buf == NULL) return; *************** *** 1681,1686 **** --- 1685,1694 ---- if (check_secure()) return; + + if (in_vim9script() && check_for_buffer_arg(argvars, 0) == FAIL) + return; + buf = tv_get_buf(&argvars[0], FALSE); if (buf == NULL) return; *** ../vim-8.2.3210/src/proto/typval.pro 2021-07-23 20:37:52.022322433 +0200 --- src/proto/typval.pro 2021-07-24 16:10:53.146934583 +0200 *************** *** 21,26 **** --- 21,27 ---- int check_for_dict_arg(typval_T *args, int idx); int check_for_opt_dict_arg(typval_T *args, int idx); int check_for_chan_or_job_arg(typval_T *args, int idx); + int check_for_opt_chan_or_job_arg(typval_T *args, int idx); int check_for_job_arg(typval_T *args, int idx); int check_for_string_or_number_arg(typval_T *args, int idx); int check_for_buffer_arg(typval_T *args, int idx); *** ../vim-8.2.3210/src/testdir/test_vim9_builtin.vim 2021-07-24 15:44:26.877784139 +0200 --- src/testdir/test_vim9_builtin.vim 2021-07-24 16:14:19.698484827 +0200 *************** *** 445,450 **** --- 445,459 ---- endif enddef + def Test_ch_log() + if !has('channel') + CheckFeature channel + else + CheckDefAndScriptFailure2(['ch_log(true)'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['ch_log("a", 1)'], 'E1013: Argument 2: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 2') + endif + enddef + def Test_ch_logfile() if !has('channel') CheckFeature channel *************** *** 654,659 **** --- 663,676 ---- count({a: 1.1, b: 2.2, c: 1.1}, 1.1)->assert_equal(2) enddef + def Test_cscope_connection() + CheckFeature cscope + assert_equal(0, cscope_connection()) + CheckDefAndScriptFailure2(['cscope_connection("a")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['cscope_connection(1, 2)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['cscope_connection(1, "b", 3)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3') + enddef + def Test_cursor() new setline(1, range(4)) *************** *** 1144,1149 **** --- 1161,1171 ---- CheckDefAndScriptFailure2(['getbufline("a", 2, 0z10)'], 'E1013: Argument 3: type mismatch, expected string but got blob', 'E1174: String required for argument 3') enddef + def Test_getbufvar() + CheckDefAndScriptFailure2(['getbufvar(true, "v")'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['getbufvar(1, 2, 3)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') + enddef + def Test_getchangelist() new setline(1, 'some text') *************** *** 1862,1869 **** def Test_matchaddpos() CheckDefAndScriptFailure2(['matchaddpos(1, [1])'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') ! CheckDefAndScriptFailure2(['matchaddpos("a", "b")'], 'E1013: Argument 2: type mismatch, expected list but got string', 'E1211: List required for argument 2') ! CheckDefFailure(['matchaddpos("a", ["2"])'], 'E1013: Argument 2: type mismatch, expected list but got list') CheckDefAndScriptFailure2(['matchaddpos("a", [1], "c")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') CheckDefAndScriptFailure2(['matchaddpos("a", [1], 1, "d")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4') CheckDefAndScriptFailure2(['matchaddpos("a", [1], 1, 1, [])'], 'E1013: Argument 5: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 5') --- 1884,1890 ---- def Test_matchaddpos() CheckDefAndScriptFailure2(['matchaddpos(1, [1])'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') ! CheckDefAndScriptFailure2(['matchaddpos("a", "b")'], 'E1013: Argument 2: type mismatch, expected list but got string', 'E1211: List required for argument 2') CheckDefAndScriptFailure2(['matchaddpos("a", [1], "c")'], 'E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3') CheckDefAndScriptFailure2(['matchaddpos("a", [1], 1, "d")'], 'E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4') CheckDefAndScriptFailure2(['matchaddpos("a", [1], 1, 1, [])'], 'E1013: Argument 5: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 5') *************** *** 2148,2153 **** --- 2169,2190 ---- endif enddef + def Test_prompt_setcallback() + if !has('channel') + CheckFeature channel + else + CheckDefAndScriptFailure2(['prompt_setcallback(true, "1")'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1') + endif + enddef + + def Test_prompt_setinterrupt() + if !has('channel') + CheckFeature channel + else + CheckDefAndScriptFailure2(['prompt_setinterrupt(true, "1")'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1') + endif + enddef + def Test_prompt_setprompt() if !has('channel') CheckFeature channel *************** *** 2575,2587 **** lines =<< trim END def TestPair() ! echo searchpair("a", "b", "c", "d", "1", "f") enddef defcompile END CheckScriptSuccess(lines) bwipe! enddef def Test_searchpos() --- 2612,2631 ---- lines =<< trim END def TestPair() ! echo searchpair("a", "b", "c", "d", "1", 99) enddef defcompile END CheckScriptSuccess(lines) bwipe! + CheckDefAndScriptFailure2(['searchpair(1, "b", "c")'], 'E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['searchpair("a", 2, "c")'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['searchpair("a", "b", 3)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3') + CheckDefAndScriptFailure2(['searchpair("a", "b", "c", 4)'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4') + # BUG: Vim crashes with the following test + #CheckDefAndScriptFailure2(['searchpair("a", "b", "c", "d", "1", "f")'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4') + #CheckDefAndScriptFailure2(['searchpair("a", "b", "c", "d", "1", 3, "g")'], 'E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4') enddef def Test_searchpos() *************** *** 2676,2681 **** --- 2720,2728 ---- setbufvar('%', 'myvar', 123) getbufvar('%', 'myvar')->assert_equal(123) + + CheckDefAndScriptFailure2(['setbufvar(true, "v", 3)'], 'E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1') + CheckDefAndScriptFailure2(['setbufvar(1, 2, 3)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') enddef def Test_setbufline() *************** *** 3112,3117 **** --- 3159,3170 ---- CheckDefAndScriptFailure2(['synID(1, 1, 2)'], 'E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3') enddef + def Test_synIDattr() + CheckDefAndScriptFailure2(['synIDattr("a", "b")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['synIDattr(1, 2)'], 'E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2') + CheckDefAndScriptFailure2(['synIDattr(1, "b", 3)'], 'E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3') + enddef + def Test_synIDtrans() CheckDefFailure(['synIDtrans("a")'], 'E1013: Argument 1: type mismatch, expected number but got string') enddef *************** *** 3379,3384 **** --- 3432,3442 ---- timer_stop(id) enddef + def Test_timer_start() + CheckDefAndScriptFailure2(['timer_start("a", "1")'], 'E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1') + CheckDefAndScriptFailure2(['timer_start(1, "1", [1])'], 'E1013: Argument 3: type mismatch, expected dict but got list', 'E1206: Dictionary required for argument 3') + enddef + def Test_timer_stop() CheckDefFailure(['timer_stop("x")'], 'E1013: Argument 1: type mismatch, expected number but got string') assert_equal(0, timer_stop(100)) *** ../vim-8.2.3210/src/time.c 2021-07-20 21:07:32.972058844 +0200 --- src/time.c 2021-07-24 16:10:53.146934583 +0200 *************** *** 799,805 **** void f_timer_start(typval_T *argvars, typval_T *rettv) { ! long msec = (long)tv_get_number(&argvars[0]); timer_T *timer; int repeat = 0; callback_T callback; --- 799,805 ---- void f_timer_start(typval_T *argvars, typval_T *rettv) { ! long msec; timer_T *timer; int repeat = 0; callback_T callback; *************** *** 808,813 **** --- 808,820 ---- rettv->vval.v_number = -1; if (check_secure()) return; + + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || check_for_opt_dict_arg(argvars, 2) == FAIL)) + return; + + msec = (long)tv_get_number(&argvars[0]); if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_DICT *** ../vim-8.2.3210/src/typval.c 2021-07-23 20:37:52.022322433 +0200 --- src/typval.c 2021-07-24 16:10:53.146934583 +0200 *************** *** 523,528 **** --- 523,539 ---- } /* + * Give an error and return FAIL unless "args[idx]" is an optional channel or a + * job. + */ + int + check_for_opt_chan_or_job_arg(typval_T *args, int idx) + { + return (args[idx].v_type == VAR_UNKNOWN + || check_for_chan_or_job_arg(args, idx) != FAIL); + } + + /* * Give an error and return FAIL unless "args[idx]" is a job. */ int *** ../vim-8.2.3210/src/version.c 2021-07-24 15:44:26.877784139 +0200 --- src/version.c 2021-07-24 16:12:32.150719631 +0200 *************** *** 757,758 **** --- 757,760 ---- { /* Add new patch number below this line */ + /**/ + 3211, /**/ -- hundred-and-one symptoms of being an internet addict: 226. You sit down at the computer right after dinner and your spouse says "See you in the morning." /// 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 ///