# HG changeset patch # User Bram Moolenaar # Date 1642453203 -3600 # Node ID 63f8dbcf6a749f1f189bf19f355ae2acbc595412 # Parent 19849ccc38a070a0acc0497990b5fda208465fe4 patch 8.2.4124: Vim9: method in compiled function may not see script item Commit: https://github.com/vim/vim/commit/6389baa6691fde4ca56ec6243ed83322543df300 Author: Bram Moolenaar Date: Mon Jan 17 20:50:40 2022 +0000 patch 8.2.4124: Vim9: method in compiled function may not see script item Problem: Vim9: method in compiled function may not see script item. Solution: Make sure not to skip to the next line. (closes https://github.com/vim/vim/issues/9496) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1717,7 +1717,7 @@ let g:dict_one = #{one: 1} let $TESTVAR = 'testvar' " type casts -def Test_expr7t() +def Test_expr7() var lines =<< trim END var ls: list = ['a', g:string_empty] var ln: list = [g:anint, g:thefour] @@ -1743,7 +1743,7 @@ def Test_expr7t() enddef " test low level expression -def Test_expr7_number() +def Test_expr8_number() # number constant var lines =<< trim END assert_equal(0, 0) @@ -1756,7 +1756,7 @@ def Test_expr7_number() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_float() +def Test_expr8_float() # float constant if !has('float') MissingFeature 'float' @@ -1771,7 +1771,7 @@ def Test_expr7_float() endif enddef -def Test_expr7_blob() +def Test_expr8_blob() # blob constant var lines =<< trim END assert_equal(g:blob_empty, 0z) @@ -1803,7 +1803,7 @@ def Test_expr7_blob() CheckDefAndScriptFailure(["var x = 0z123"], 'E973:', 1) enddef -def Test_expr7_string() +def Test_expr8_string() # string constant var lines =<< trim END assert_equal(g:string_empty, '') @@ -1820,7 +1820,7 @@ def Test_expr7_string() CheckDefAndScriptFailure(["var x = 'abc"], 'E115:', 1) enddef -def Test_expr7_vimvar() +def Test_expr8_vimvar() v:errors = [] var errs: list = v:errors CheckDefFailure(['var errs: list = v:errors'], 'E1012:') @@ -1845,7 +1845,7 @@ def Test_expr7_vimvar() bwipe! enddef -def Test_expr7_special() +def Test_expr8_special() # special constant var lines =<< trim END assert_equal(g:special_true, true) @@ -1882,7 +1882,7 @@ def Test_expr7_special() CheckDefAndScriptFailure(['v:none = 22'], 'E46:', 1) enddef -def Test_expr7_list() +def Test_expr8_list() # list var lines =<< trim END assert_equal(g:list_empty, []) @@ -1955,7 +1955,7 @@ def Test_expr7_list() CheckDefAndScriptFailure(lines + ['echo numbers[a :b]'], 'E1004:', 4) enddef -def Test_expr7_list_vim9script() +def Test_expr8_list_vim9script() var lines =<< trim END var l = [ 11, @@ -2043,7 +2043,7 @@ def LambdaUsingArg(x: number): func x == 2 enddef -def Test_expr7_lambda() +def Test_expr8_lambda() var lines =<< trim END var La = () => 'result' # comment @@ -2129,7 +2129,7 @@ def Test_expr7_lambda() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_lambda_block() +def Test_expr8_lambda_block() var lines =<< trim END var Func = (s: string): string => { return 'hello ' .. s @@ -2209,7 +2209,7 @@ def NewLambdaUsingArg(x: number): func x == 2 enddef -def Test_expr7_new_lambda() +def Test_expr8_new_lambda() var lines =<< trim END var La = () => 'result' assert_equal('result', La()) @@ -2294,7 +2294,7 @@ def Test_expr7_new_lambda() CheckDefAndScriptFailure(['var Fx = (a) => [0', ' 1]'], 'E696:', 2) enddef -def Test_expr7_lambda_vim9script() +def Test_expr8_lambda_vim9script() var lines =<< trim END var v = 10->((a) => a @@ -2313,7 +2313,7 @@ def Test_expr7_lambda_vim9script() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_funcref() +def Test_expr8_funcref() var lines =<< trim END def RetNumber(): number return 123 @@ -2350,7 +2350,7 @@ enddef let g:test_space_dict = {'': 'empty', ' ': 'space'} let g:test_hash_dict = #{one: 1, two: 2} -def Test_expr7_dict() +def Test_expr8_dict() # dictionary var lines =<< trim END assert_equal(g:dict_empty, {}) @@ -2461,7 +2461,7 @@ def Test_expr7_dict() CheckDefExecAndScriptFailure(['{}[getftype("file")]'], 'E716: Key not present in Dictionary: ""', 1) enddef -def Test_expr7_dict_vim9script() +def Test_expr8_dict_vim9script() var lines =<< trim END var d = { ['one']: @@ -2592,7 +2592,7 @@ def Test_expr7_dict_vim9script() CheckScriptSuccess(lines) enddef -def Test_expr7_dict_in_block() +def Test_expr8_dict_in_block() var lines =<< trim END vim9script command MyCommand { @@ -2615,7 +2615,7 @@ def Test_expr7_dict_in_block() delcommand YourCommand enddef -def Test_expr7_call_2bool() +def Test_expr8_call_2bool() var lines =<< trim END vim9script @@ -2663,7 +2663,7 @@ def Test_expr_member() CheckDefExecAndScriptFailure(["var d: dict", "d = g:list_empty"], 'E1012: Type mismatch; expected dict but got list', 2) enddef -def Test_expr7_any_index_slice() +def Test_expr8_any_index_slice() var lines =<< trim END # getting the one member should clear the list only after getting the item assert_equal('bbb', ['aaa', 'bbb', 'ccc'][1]) @@ -2817,7 +2817,7 @@ def SetSomeVar() b:someVar = &fdm enddef -def Test_expr7_option() +def Test_expr8_option() var lines =<< trim END # option set ts=11 @@ -2844,7 +2844,7 @@ def Test_expr7_option() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_environment() +def Test_expr8_environment() var lines =<< trim END # environment variable assert_equal('testvar', $TESTVAR) @@ -2856,7 +2856,7 @@ def Test_expr7_environment() CheckDefAndScriptFailure(["$"], ['E1002:', 'E15:'], 1) enddef -def Test_expr7_register() +def Test_expr8_register() var lines =<< trim END @a = 'register a' assert_equal('register a', @a) @@ -2882,7 +2882,7 @@ def Test_expr7_register() enddef " This is slow when run under valgrind. -def Test_expr7_namespace() +def Test_expr8_namespace() var lines =<< trim END g:some_var = 'some' assert_equal('some', get(g:, 'some_var')) @@ -2911,7 +2911,7 @@ def Test_expr7_namespace() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_namespace_loop_def() +def Test_expr8_namespace_loop_def() var lines =<< trim END # check using g: in a for loop more than DO_NOT_FREE_CNT times var exists = 0 @@ -2930,8 +2930,8 @@ def Test_expr7_namespace_loop_def() enddef " NOTE: this is known to be slow. To skip use: -" :let $TEST_SKIP_PAT = 'Test_expr7_namespace_loop_script' -def Test_expr7_namespace_loop_script() +" :let $TEST_SKIP_PAT = 'Test_expr8_namespace_loop_script' +def Test_expr8_namespace_loop_script() var lines =<< trim END vim9script # check using g: in a for loop more than DO_NOT_FREE_CNT times @@ -2950,7 +2950,7 @@ def Test_expr7_namespace_loop_script() CheckScriptSuccess(lines) enddef -def Test_expr7_parens() +def Test_expr8_parens() # (expr) var lines =<< trim END assert_equal(4, (6 * 4) / 6) @@ -2982,7 +2982,7 @@ def Test_expr7_parens() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_negate_add() +def Test_expr8_negate_add() var lines =<< trim END assert_equal(-99, -99) assert_equal(-99, - 99) @@ -3031,7 +3031,7 @@ def LegacyReturn(): string legacy return #{key: 'ok'}.key enddef -def Test_expr7_legacy_script() +def Test_expr8_legacy_script() var lines =<< trim END let s:legacy = 'legacy' def GetLocal(): string @@ -3065,7 +3065,7 @@ def s:Echo4Arg(arg: any): string return arg enddef -def Test_expr7_call() +def Test_expr8_call() var lines =<< trim END assert_equal('yes', 'yes'->Echo()) assert_equal(true, !range(5)->empty()) @@ -3098,7 +3098,7 @@ def Test_expr7_call() delete('Xruntime', 'rf') enddef -def Test_expr7_method_call() +def Test_expr8_method_call() var lines =<< trim END new setline(1, ['first', 'last']) @@ -3175,7 +3175,7 @@ def Test_expr7_method_call() CheckDefExecFailure(lines, 'E1013:') enddef -def Test_expr7_method_call_linebreak() +def Test_expr8_method_call_linebreak() # this was giving an error when skipping over the expression var lines =<< trim END vim9script @@ -3191,8 +3191,34 @@ def Test_expr7_method_call_linebreak() CheckScriptSuccess(lines) enddef - -def Test_expr7_not() +def Test_expr8_method_call_import() + var lines =<< trim END + vim9script + export def Square(items: list): list + return map(items, (_, i) => i * i) + enddef + END + call writefile(lines, 'Xsquare.vim') + + lines =<< trim END + vim9script + import './Xsquare.vim' + + def Test(): list + return range(5) + ->Xsquare.Square() + ->map((_, i) => i * 10) + enddef + + assert_equal([0, 10, 40, 90, 160], Test()) + END + CheckScriptSuccess(lines) + + delete('Xsquare.vim') +enddef + + +def Test_expr8_not() var lines =<< trim END assert_equal(true, !'') assert_equal(true, ![]) @@ -3244,7 +3270,7 @@ enddef let g:anumber = 42 -def Test_expr7_negate() +def Test_expr8_negate() var lines =<< trim END var nr = 1 assert_equal(-1, -nr) @@ -3253,7 +3279,7 @@ def Test_expr7_negate() CheckDefAndScriptSuccess(lines) enddef -func Test_expr7_fails() +func Test_expr8_fails() call CheckDefFailure(["var x = (12"], "E1097:", 3) call CheckScriptFailure(['vim9script', "var x = (12"], 'E110:', 2) @@ -3313,7 +3339,7 @@ func CallMe2(one, two) return a:one .. a:two endfunc -def Test_expr7_trailing() +def Test_expr8_trailing() var lines =<< trim END # user function call assert_equal(123, g:CallMe(123)) @@ -3349,7 +3375,7 @@ def Test_expr7_trailing() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_string_subscript() +def Test_expr8_string_subscript() var lines =<< trim END var text = 'abcdef' assert_equal('f', text[-1]) @@ -3448,7 +3474,7 @@ def Test_expr7_string_subscript() CheckDefAndScriptFailure(lines, ['E1012: Type mismatch; expected number but got string', 'E1030: Using a String as a Number: "2"'], 1) enddef -def Test_expr7_list_subscript() +def Test_expr8_list_subscript() var lines =<< trim END var list = [0, 1, 2, 3, 4] assert_equal(0, list[0]) @@ -3491,7 +3517,7 @@ def Test_expr7_list_subscript() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_dict_subscript() +def Test_expr8_dict_subscript() var lines =<< trim END var l = [{lnum: 2}, {lnum: 1}] var res = l[0].lnum > l[1].lnum @@ -3512,7 +3538,7 @@ def Test_expr7_dict_subscript() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_blob_subscript() +def Test_expr8_blob_subscript() var lines =<< trim END var b = 0z112233 assert_equal(0x11, b[0]) @@ -3524,7 +3550,7 @@ def Test_expr7_blob_subscript() CheckDefAndScriptSuccess(lines) enddef -def Test_expr7_subscript_linebreak() +def Test_expr8_subscript_linebreak() var lines =<< trim END var range = range( 3) @@ -3567,7 +3593,7 @@ def Test_expr7_subscript_linebreak() CheckDefAndScriptFailure(lines, ['E1127:', 'E116:'], 2) enddef -func Test_expr7_trailing_fails() +func Test_expr8_trailing_fails() call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8))'], 'E107:', 2) call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8)) ()'], 'E274:', 2) endfunc diff --git a/src/version.c b/src/version.c --- 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 */ /**/ + 4124, +/**/ 4123, /**/ 4122, diff --git a/src/vim9expr.c b/src/vim9expr.c --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -1732,21 +1732,23 @@ compile_subscript( } else { + int fail; + int save_len = cctx->ctx_ufunc->uf_lines.ga_len; + *paren = NUL; - if (compile_expr8(arg, cctx, ppconst) == FAIL - || *skipwhite(*arg) != NUL) + // do not look in the next line + cctx->ctx_ufunc->uf_lines.ga_len = 1; + fail = compile_expr8(arg, cctx, ppconst) == FAIL + || *skipwhite(*arg) != NUL; + *paren = '('; + cctx->ctx_ufunc->uf_lines.ga_len = save_len; + if (fail) { - *paren = '('; semsg(_(e_invalid_expression_str), pstart); return FAIL; } - *paren = '('; } - // Remember the next instruction index, where the instructions - // for arguments are being written. - expr_isn_end = cctx->ctx_instr.ga_len; - // Compile the arguments. if (**arg != '(') { @@ -1756,6 +1758,11 @@ compile_subscript( semsg(_(e_missing_parenthesis_str), *arg); return FAIL; } + + // Remember the next instruction index, where the instructions + // for arguments are being written. + expr_isn_end = cctx->ctx_instr.ga_len; + *arg = skipwhite(*arg + 1); if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL) return FAIL;