2015-04-30 10:56 GMT+03:00 Olaf Dabrunz <[email protected]>:
> Example:
>
>     :let d = {'a': 99, 'b': 100}
>     :lockvar 1 d
>     :call extend(d, {'a': 123})
>         E741: Value is locked: extend() argument
>     :let d.a = 123
>     :let d
>         d                     {'a': 123, 'b': 100}
>
> The dictionary is locked, but the 'a' item is not, so extend() on 'a'
> should succeed in the same way as the 'let' does. According to ':he
> lockvar', a dictionary lock protects against item deletion and addition,
> but not against changing an existing item.
>
> BTW, protection against item deletion and addition works:
>
>     :call extend(d, {'x': 'new'})
>         E741: Value is locked: extend() argument
>
>
> diff -r 18d84ed365a5 src/eval.c
> --- a/src/eval.c        Wed Apr 22 22:18:22 2015 +0200
> +++ b/src/eval.c        Thu Apr 30 09:09:37 2015 +0200
> @@ -10524,6 +10524,8 @@ dict_extend(d1, d2, action)
>             }
>             if (di1 == NULL)
>             {
> +               if (tv_check_lock(d1->dv_lock, arg_errmsg, TRUE))
> +                   break;
>                 di1 = dictitem_copy(HI2DI(hi2));
>                 if (di1 != NULL && dict_add(d1, di1) == FAIL)
>                     dictitem_free(di1);
> @@ -10601,8 +10603,7 @@ f_extend(argvars, rettv)
>
>         d1 = argvars[0].vval.v_dict;
>         d2 = argvars[1].vval.v_dict;
> -       if (d1 != NULL && !tv_check_lock(d1->dv_lock, arg_errmsg, TRUE)
> -               && d2 != NULL)
> +       if (d1 != NULL && d2 != NULL)
>         {
>             /* Check the third argument. */
>             if (argvars[2].v_type != VAR_UNKNOWN)
> diff -r 18d84ed365a5 src/testdir/test55.in
> --- a/src/testdir/test55.in     Wed Apr 22 22:18:22 2015 +0200
> +++ b/src/testdir/test55.in     Thu Apr 30 09:09:37 2015 +0200
> @@ -408,6 +408,20 @@ let l = [0, 1, 2, 3]
>  :endtry
>  :$put =string(d)
>  :"
> +:$put ='extend() after lock on dict (existing: yes, new: no):'
> +:unlet! d
> +:let d = {'a': 99, 'b': 100}
> +:lockvar 1 d
> +:try
> +:  $put =string(extend(d, {'a': 123}))
> +:  $put ='did extend() existing item'

I think :try should be here, not above.

> +:  $put =string(extend(d, {'x': 'new'}))
> +:  $put ='did extend() with new item'
> +:catch
> +:  $put =v:exception[:14]
> +:endtry
> +:$put =string(d)
> +:"

Here some crucial tests are missing:

1. `extend(d, {'a': 456, 'x': 'new'})` without try/catch.
2. Same in a try/catch.
3. Both repeated with a second argument to `extend` where `keys(arg)`
returns `[old_key1, new_key2, old_key3]` (this is needed to make sure
that all old keys are modified).

Unless it is possible for `extend` to modify *all* old keys regardless
the internal order I would prefer the current behaviour where you at
least always know that nothing will be modified. It is a completely
useless behaviour to partially modify a dictionary depending on key
ordering which is not controlled by a plugin developer.

Test should also test the order of the `keys()` output to make sure
that it will be modified once changes that affect internal hash
ordering are pushed.

>  :$put ='No remove() of write-protected scope-level variable:'
>  :fun! Tfunc(this_is_a_loooooooooong_parameter_name)
>  :  try
> diff -r 18d84ed365a5 src/testdir/test55.ok
> --- a/src/testdir/test55.ok     Wed Apr 22 22:18:22 2015 +0200
> +++ b/src/testdir/test55.ok     Thu Apr 30 09:09:37 2015 +0200
> @@ -138,6 +138,10 @@ did map()
>  No extend() after lock on dict item:
>  Vim(put):E741:
>  {'a': 99, 'b': 100}
> +extend() after lock on dict (existing: yes, new: no):
> +did extend() existing item
> +Vim(put):E741:
> +{'a': 123, 'b': 100}
>  No remove() of write-protected scope-level variable:
>  Vim(put):E795:
>  No extend() of write-protected scope-level variable:
>
> --
> Olaf Dabrunz (oda <at> fctrace.org)
>
> --
> --
> You received this message from the "vim_dev" maillist.
> Do not top-post! Type your reply below the text you are replying to.
> For more information, visit http://www.vim.org/maillist.php
>
> ---
> You received this message because you are subscribed to the Google Groups 
> "vim_dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui