aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval/typval.c
diff options
context:
space:
mode:
authorSean Dewar <seandewar@users.noreply.github.com>2021-07-31 00:20:20 +0100
committerSean Dewar <seandewar@users.noreply.github.com>2021-09-16 00:13:41 +0100
commit9e38c4a79fe0351e9e18bc57cf48b960e8d31e88 (patch)
treea0ba140fd2bf69e6a85ef7e76b3a7b51a76f0f55 /src/nvim/eval/typval.c
parentffaf881b42fd22b8bf423c5754d48ce93f59bf4b (diff)
downloadrneovim-9e38c4a79fe0351e9e18bc57cf48b960e8d31e88.tar.gz
rneovim-9e38c4a79fe0351e9e18bc57cf48b960e8d31e88.tar.bz2
rneovim-9e38c4a79fe0351e9e18bc57cf48b960e8d31e88.zip
vim-patch:8.2.1473: items in a list given to :const can still be modified
Problem: Items in a list given to :const can still be modified. Solution: Work like ":lockvar! name" but don't lock referenced items. Make locking a blob work. https://github.com/vim/vim/commit/021bda56710d98c09a6b35610a476ab2dd8c58ad
Diffstat (limited to 'src/nvim/eval/typval.c')
-rw-r--r--src/nvim/eval/typval.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index d983ce14b5..b08fe274f0 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -2659,7 +2659,10 @@ void tv_copy(const typval_T *const from, typval_T *const to)
/// @param[out] tv Item to (un)lock.
/// @param[in] deep Levels to (un)lock, -1 to (un)lock everything.
/// @param[in] lock True if it is needed to lock an item, false to unlock.
-void tv_item_lock(typval_T *const tv, const int deep, const bool lock)
+/// @param[in] check_refcount If true, do not lock a list or dict with a
+/// reference count larger than 1.
+void tv_item_lock(typval_T *const tv, const int deep, const bool lock,
+ const bool check_refcount)
FUNC_ATTR_NONNULL_ALL
{
// TODO(ZyX-I): Make this not recursive
@@ -2688,19 +2691,19 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock)
switch (tv->v_type) {
case VAR_BLOB: {
blob_T *const b = tv->vval.v_blob;
- if (b != NULL) {
+ if (b != NULL && !(check_refcount && b->bv_refcount > 1)) {
CHANGE_LOCK(lock, b->bv_lock);
}
break;
}
case VAR_LIST: {
list_T *const l = tv->vval.v_list;
- if (l != NULL) {
+ if (l != NULL && !(check_refcount && l->lv_refcount > 1)) {
CHANGE_LOCK(lock, l->lv_lock);
if (deep < 0 || deep > 1) {
// Recursive: lock/unlock the items the List contains.
TV_LIST_ITER(l, li, {
- tv_item_lock(TV_LIST_ITEM_TV(li), deep - 1, lock);
+ tv_item_lock(TV_LIST_ITEM_TV(li), deep - 1, lock, check_refcount);
});
}
}
@@ -2708,12 +2711,12 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock)
}
case VAR_DICT: {
dict_T *const d = tv->vval.v_dict;
- if (d != NULL) {
+ if (d != NULL && !(check_refcount && d->dv_refcount > 1)) {
CHANGE_LOCK(lock, d->dv_lock);
if (deep < 0 || deep > 1) {
// recursive: lock/unlock the items the List contains
TV_DICT_ITER(d, di, {
- tv_item_lock(&di->di_tv, deep - 1, lock);
+ tv_item_lock(&di->di_tv, deep - 1, lock, check_refcount);
});
}
}