• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

realm / realm-core / github_pull_request_312964

19 Feb 2025 07:31PM UTC coverage: 90.814% (-0.3%) from 91.119%
github_pull_request_312964

Pull #8071

Evergreen

web-flow
Bump serialize-javascript and mocha

Bumps [serialize-javascript](https://github.com/yahoo/serialize-javascript) to 6.0.2 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together.


Updates `serialize-javascript` from 6.0.0 to 6.0.2
- [Release notes](https://github.com/yahoo/serialize-javascript/releases)
- [Commits](https://github.com/yahoo/serialize-javascript/compare/v6.0.0...v6.0.2)

Updates `mocha` from 10.2.0 to 10.8.2
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v10.2.0...v10.8.2)

---
updated-dependencies:
- dependency-name: serialize-javascript
  dependency-type: indirect
- dependency-name: mocha
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #8071: Bump serialize-javascript and mocha

96552 of 179126 branches covered (53.9%)

212672 of 234185 relevant lines covered (90.81%)

3115802.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.38
/src/realm/array_backlink.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2016 Realm Inc.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 **************************************************************************/
18

19
#include <realm/array_backlink.hpp>
20
#include <realm/util/assert.hpp>
21
#include <realm/table.hpp>
22
#include <realm/group.hpp>
23
#include <realm/list.hpp>
24
#include <realm/set.hpp>
25
#include <realm/dictionary.hpp>
26

27
using namespace realm;
28

29
// nullify forward links corresponding to any backward links at index 'ndx'.
30
void ArrayBacklink::nullify_fwd_links(size_t ndx, CascadeState& state)
31
{
117,429✔
32
    uint64_t value = Array::get(ndx);
117,429✔
33
    if (value == 0) {
117,429✔
34
        return;
114,237✔
35
    }
114,237✔
36

37
    // Naming: Links go from source to target.
38
    // Backlinks go from target to source.
39
    // This array holds backlinks, hence it is the target.
40
    // The table which holds the corresponding fwd links is the source.
41

42
    // determine target table, column and key.
43
    REALM_ASSERT_DEBUG(dynamic_cast<Cluster*>(get_parent()));
3,192✔
44
    auto cluster = static_cast<Cluster*>(get_parent());
3,192✔
45
    const Table* target_table = cluster->get_owning_table();
3,192✔
46
    ColKey target_col_key = cluster->get_col_key(get_ndx_in_parent());
3,192✔
47
    ObjKey target_key = cluster->get_real_key(ndx);
3,192✔
48

49
    // determine the source table/col - which is the one holding the forward links
50
    TableRef source_table = target_table->get_opposite_table(target_col_key);
3,192✔
51
    ColKey src_col_key = target_table->get_opposite_column(target_col_key);
3,192✔
52

53
    // Now follow all backlinks to their origin and clear forward links.
54
    if ((value & 1) != 0) {
3,192✔
55
        // just a single one
56
        state.enqueue_for_nullification(*source_table, src_col_key, ObjKey(value >> 1),
2,898✔
57
                                        {target_table->get_key(), target_key});
2,898✔
58
    }
2,898✔
59
    else {
294✔
60
        // There is more than one backlink - Iterate through them all
61
        ref_type ref = to_ref(value);
294✔
62
        BPlusTree<int64_t> backlink_list(m_alloc);
294✔
63
        backlink_list.init_from_ref(ref);
294✔
64

65
        size_t sz = backlink_list.size();
294✔
66
        for (size_t i = 0; i < sz; i++) {
894✔
67
            state.enqueue_for_nullification(*source_table, src_col_key, ObjKey(backlink_list.get(i)),
600✔
68
                                            {target_table->get_key(), target_key});
600✔
69
        }
600✔
70
    }
294✔
71
}
3,192✔
72

73
void ArrayBacklink::add(size_t ndx, ObjKey key)
74
{
3,534,690✔
75
    uint64_t value = Array::get(ndx);
3,534,690✔
76

77
    // A backlink list of size 1 is stored as a single non-ref column value.
78
    if (value == 0) {
3,534,690✔
79
        set(ndx, key.value << 1 | 1); // Throws
403,908✔
80
        return;
403,908✔
81
    }
403,908✔
82

83
    // When increasing the size of the backlink list from 1 to 2, we need to
84
    // convert from the single non-ref column value representation, to a B+-tree
85
    // representation.
86
    BPlusTree<int64_t> backlink_list(m_alloc);
3,130,782✔
87
    if ((value & 1) != 0) {
3,130,782✔
88
        // Create new column to hold backlinks
89
        backlink_list.create();
31,215✔
90
        set_as_ref(ndx, backlink_list.get_ref());
31,215✔
91
        backlink_list.add(value >> 1);
31,215✔
92
    }
31,215✔
93
    else {
3,099,567✔
94
        backlink_list.init_from_ref(to_ref(value));
3,099,567✔
95
        backlink_list.set_parent(this, ndx);
3,099,567✔
96
        backlink_list.split_if_needed();
3,099,567✔
97
    }
3,099,567✔
98
    backlink_list.add(key.value); // Throws
3,130,782✔
99
}
3,130,782✔
100

101
// Return true if the last link was removed
102
bool ArrayBacklink::remove(size_t ndx, ObjKey key)
103
{
257,103✔
104
    uint64_t value = Array::get(ndx);
257,103✔
105
    REALM_ASSERT_DEBUG(value != 0);
257,103✔
106
    if (value == 0)
257,103✔
107
        return true;
×
108

109
    // If there is only a single backlink, it can be stored as
110
    // a tagged value
111
    if ((value & 1) != 0) {
257,103✔
112
        REALM_ASSERT_DEBUG(int64_t(value >> 1) == key.value);
129,525✔
113
        if (int64_t(value >> 1) == key.value) {
129,525✔
114
            set(ndx, 0);
129,525✔
115
            return true;
129,525✔
116
        }
129,525✔
117
        return false;
×
118
    }
129,525✔
119

120
    // if there is a list of backlinks we have to find
121
    // the right one and remove it.
122
    BPlusTree<int64_t> backlink_list(m_alloc);
127,578✔
123
    backlink_list.init_from_ref(ref_type(value));
127,578✔
124
    backlink_list.set_parent(this, ndx);
127,578✔
125
    backlink_list.split_if_needed();
127,578✔
126

127
    size_t last_ndx = backlink_list.size() - 1;
127,578✔
128
    size_t backlink_ndx = backlink_list.find_first(key.value);
127,578✔
129
    REALM_ASSERT_DEBUG(backlink_ndx != not_found);
127,578✔
130
    if (backlink_ndx != not_found) {
127,599✔
131
        if (backlink_ndx != last_ndx)
127,599✔
132
            backlink_list.set(backlink_ndx, backlink_list.get(last_ndx));
74,367✔
133
        backlink_list.erase(last_ndx); // Throws
127,599✔
134
    }
127,599✔
135

136
    // If there is only one backlink left we can inline it as tagged value
137
    if (last_ndx == 1) {
127,578✔
138
        uint64_t key_value = backlink_list.get(0);
22,140✔
139
        backlink_list.destroy();
22,140✔
140

141
        set(ndx, key_value << 1 | 1);
22,140✔
142
    }
22,140✔
143

144
    return false;
127,578✔
145
}
257,103✔
146

147
void ArrayBacklink::erase(size_t ndx)
148
{
127,167✔
149
    uint64_t value = Array::get(ndx);
127,167✔
150
    if (value && (value & 1) == 0) {
127,167✔
151
        Array::destroy_deep(ref_type(value), m_alloc);
219✔
152
    }
219✔
153
    Array::erase(ndx);
127,167✔
154
}
127,167✔
155

156
size_t ArrayBacklink::get_backlink_count(size_t ndx) const
157
{
951,852✔
158
    uint64_t value = Array::get(ndx);
951,852✔
159
    if (value == 0) {
951,852✔
160
        return 0;
427,626✔
161
    }
427,626✔
162

163
    // If there is only a single backlink, it can be stored as
164
    // a tagged value
165
    if ((value & 1) != 0) {
524,226✔
166
        return 1;
408,063✔
167
    }
408,063✔
168

169
    // return size of list
170
    MemRef mem(ref_type(value), m_alloc);
116,163✔
171
    return BPlusTree<int64_t>::size_from_header(mem.get_addr());
116,163✔
172
}
524,226✔
173

174
ObjKey ArrayBacklink::get_backlink(size_t ndx, size_t index) const
175
{
4,757,940✔
176
    uint64_t value = Array::get(ndx);
4,757,940✔
177
    REALM_ASSERT(value != 0);
4,757,940✔
178

179
    // If there is only a single backlink, it can be stored as
180
    // a tagged value
181
    if ((value & 1) != 0) {
4,757,940✔
182
        REALM_ASSERT(index == 0);
154,857✔
183
        return ObjKey(int64_t(value >> 1));
154,857✔
184
    }
154,857✔
185

186
    BPlusTree<int64_t> backlink_list(m_alloc);
4,603,083✔
187
    backlink_list.init_from_ref(ref_type(value));
4,603,083✔
188

189
    REALM_ASSERT(index < backlink_list.size());
4,603,083✔
190
    return ObjKey(backlink_list.get(index));
4,603,083✔
191
}
4,757,940✔
192

193
void ArrayBacklink::verify() const
194
{
1,218✔
195
#ifdef REALM_DEBUG
1,218✔
196
    Array::verify();
1,218✔
197

198
    REALM_ASSERT(dynamic_cast<Cluster*>(get_parent()));
1,218✔
199
    auto cluster = static_cast<Cluster*>(get_parent());
1,218✔
200
    const Table* target_table = cluster->get_owning_table();
1,218✔
201
    ColKey backlink_col_key = cluster->get_col_key(get_ndx_in_parent());
1,218✔
202

203
    TableRef src_table = target_table->get_opposite_table(backlink_col_key);
1,218✔
204
    ColKey src_col_key = target_table->get_opposite_column(backlink_col_key);
1,218✔
205

206
    // Verify that each backlink has a corresponding forward link
207
    for (size_t i = 0; i < size(); ++i) {
10,653✔
208
        ObjKey target_key = cluster->get_real_key(i);
9,435✔
209
        ObjLink target_link(target_table->get_key(), target_key);
9,435✔
210
        auto cnt = get_backlink_count(i);
9,435✔
211
        for (size_t j = 0; j < cnt; ++j) {
56,667✔
212
            Obj src_obj = src_table->get_object(get_backlink(i, j));
47,232✔
213
            if (src_col_key.is_dictionary()) {
47,232✔
214
                REALM_ASSERT(src_obj.get_dictionary_ptr(src_col_key)->find_any(target_link) != npos);
159✔
215
                continue;
159✔
216
            }
159✔
217

218
            if (src_col_key.get_type() == col_type_Mixed) {
47,073✔
219
                if (src_col_key.is_collection()) {
12✔
220
                    REALM_ASSERT(src_obj.get_collection_ptr(src_col_key)->find_any(target_link) != npos);
9✔
221
                }
9✔
222
                else {
3✔
223
                    auto val = src_obj.get<Mixed>(src_col_key);
3✔
224
                    if (val.is_type(type_TypedLink)) {
3✔
225
                        REALM_ASSERT(src_obj.get<Mixed>(src_col_key).get_link() == target_link);
3✔
226
                    }
3✔
227
                    else if (val.is_type(type_List)) {
×
228
                        DummyParent parent(src_table, val.get_ref());
×
229
                        Lst<Mixed> list(parent, 0);
×
230
                        REALM_ASSERT(list.find_any(target_link) != npos);
×
231
                    }
×
232
                    else if (val.is_type(type_Dictionary)) {
×
233
                        DummyParent parent(src_table, val.get_ref());
×
234
                        Dictionary dict(parent, 0);
×
235
                        REALM_ASSERT(dict.find_any(target_link) != npos);
×
236
                    }
×
237
                }
3✔
238
                continue;
12✔
239
            }
12✔
240

241
            if (src_col_key.is_list()) {
47,061✔
242
                REALM_ASSERT(src_obj.get_list<ObjKey>(src_col_key).find_first(target_key) != npos);
13,719✔
243
            }
13,719✔
244
            else if (src_col_key.is_set()) {
33,342✔
245
                REALM_ASSERT(src_obj.get_set<ObjKey>(src_col_key).find(target_key) != npos);
×
246
            }
×
247
            else {
33,342✔
248
                REALM_ASSERT(src_obj.get_unfiltered_link(src_col_key) == target_key);
33,342✔
249
            }
33,342✔
250
        }
47,061✔
251
    }
9,435✔
252
#endif
1,218✔
253
}
1,218✔
254

255
bool ArrayBacklink::verify_backlink(size_t ndx, int64_t link)
256
{
63,345✔
257
#ifdef REALM_DEBUG
63,345✔
258
    uint64_t value = Array::get(ndx);
63,345✔
259
    if (value == 0)
63,345✔
260
        return false;
×
261

262
    // If there is only a single backlink, it can be stored as
263
    // a tagged value
264
    if ((value & 1) != 0) {
63,345✔
265
        return int64_t(value >> 1) == link;
282✔
266
    }
282✔
267

268
    BPlusTree<int64_t> backlink_list(m_alloc);
63,063✔
269
    backlink_list.init_from_ref(ref_type(value));
63,063✔
270

271
    return backlink_list.find_first(link) != realm::not_found;
63,063✔
272
#else
273
    static_cast<void>(ndx);
274
    static_cast<void>(link);
275
    return true;
276
#endif
277
}
63,345✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc