diff --git a/src/jv_aux.c b/src/jv_aux.c index fd5ff96684..5aae72e075 100644 --- a/src/jv_aux.c +++ b/src/jv_aux.c @@ -454,6 +454,32 @@ jv jv_getpath(jv root, jv path) { // assumes paths is a sorted array of arrays static jv delpaths_sorted(jv object, jv paths, int start) { + // Resolve negative array indices against the array length, the way jv_get does at + // non-leaf levels and jv_dels at the leaf, so paths reaching the same element via a + // positive or a negative index are grouped and reconciled together. + if (jv_get_kind(object) == JV_KIND_ARRAY) { + int len = jv_array_length(jv_copy(object)); + int resort = 0; + for (int i=0; i INT_MAX) didx = INT_MAX; + int idx = (int)didx; + if (leaf ? didx < 0 : idx < 0) idx += len; + if (idx >= 0 && idx < len && didx != idx) { + paths = jv_array_set(paths, i, jv_array_set(path, start, jv_number(idx))); + resort = 1; + continue; + } + jv_free(path); + } + if (resort) + paths = jv_sort(paths, jv_copy(paths)); + } jv delkeys = jv_array(); for (int i=0; i start); diff --git a/tests/jq.test b/tests/jq.test index 9a80341f52..6c32bdcfe1 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -1185,6 +1185,19 @@ del(.[1], .[-6], .[2], .[-3:9]) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 3, 5, 6, 9] +# regression test for #3538 +del(.[0][-6], .[-1][6]) +[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] +[[0, 1, 2, 3, 5, 7, 8, 9]] + +delpaths([[-1, -6], [0, 6]]) +[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] +[[0, 1, 2, 3, 5, 7, 8, 9]] + +del(.[-0.5][1], .[-1][0]) +[[10, 20, 30]] +[[30]] + del(.[nan]) [1,2,3] [1,2,3]