Skip to content

Commit fbd9a21

Browse files
committed
feat(refs): control max ref depth
1 parent 6abce3f commit fbd9a21

File tree

3 files changed

+64
-21
lines changed

3 files changed

+64
-21
lines changed

src/index.js

+17-20
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,15 @@ function subscribeToRefs ({
1717
data,
1818
depth,
1919
resolve
20-
}) {
20+
}, options) {
2121
const refKeys = Object.keys(refs)
2222
const missingKeys = Object.keys(subs).filter(refKey => refKeys.indexOf(refKey) < 0)
2323
// unbind keys that are no longer there
2424
missingKeys.forEach(refKey => {
2525
subs[refKey].unsub()
2626
delete subs[refKey]
2727
})
28-
if (!refKeys.length) return resolve(path)
29-
// TODO max depth param, default to 1?
30-
if (++depth > 3) throw new Error('more than 5 nested refs')
28+
if (!refKeys.length || ++depth > options.maxRefDepth) return resolve(path)
3129

3230
let resolvedCount = 0
3331
const totalToResolve = refKeys.length
@@ -59,7 +57,7 @@ function subscribeToRefs ({
5957
path: docPath,
6058
depth,
6159
resolve: deepResolve.bind(null, docPath)
62-
}),
60+
}, options),
6361
path: ref.path
6462
}
6563
})
@@ -71,7 +69,7 @@ function bindCollection ({
7169
collection,
7270
resolve,
7371
reject
74-
}) {
72+
}, options) {
7573
// TODO support pathes? nested.obj.list (walkSet)
7674
const array = vm[key] = []
7775
const originalResolve = resolve
@@ -96,7 +94,7 @@ function bindCollection ({
9694
path: newIndex,
9795
depth: 0,
9896
resolve: resolve.bind(null, doc)
99-
})
97+
}, options)
10098
},
10199
modified: ({ oldIndex, newIndex, doc }) => {
102100
const subs = arraySubs.splice(oldIndex, 1)[0]
@@ -113,7 +111,7 @@ function bindCollection ({
113111
path: newIndex,
114112
depth: 0,
115113
resolve
116-
})
114+
}, options)
117115
},
118116
removed: ({ oldIndex }) => {
119117
array.splice(oldIndex, 1)
@@ -147,7 +145,6 @@ function bindCollection ({
147145
}
148146
}
149147
docChanges.forEach(c => {
150-
// console.log(c)
151148
change[c.type](c)
152149
})
153150

@@ -161,7 +158,7 @@ function bindCollection ({
161158
}
162159
}
163160

164-
function updateDataFromDocumentSnapshot ({ snapshot, target, path, subs, depth = 0, resolve }) {
161+
function updateDataFromDocumentSnapshot ({ snapshot, target, path, subs, depth = 0, resolve }, options) {
165162
const [data, refs] = extractRefs(snapshot, walkGet(target, path))
166163
walkSet(target, path, data)
167164
subscribeToRefs({
@@ -172,10 +169,10 @@ function updateDataFromDocumentSnapshot ({ snapshot, target, path, subs, depth =
172169
path,
173170
depth,
174171
resolve
175-
})
172+
}, options)
176173
}
177174

178-
function subscribeToDocument ({ ref, target, path, depth, resolve }) {
175+
function subscribeToDocument ({ ref, target, path, depth, resolve }, options) {
179176
const subs = Object.create(null)
180177
const unbind = ref.onSnapshot(doc => {
181178
if (doc.exists) {
@@ -186,7 +183,7 @@ function subscribeToDocument ({ ref, target, path, depth, resolve }) {
186183
subs,
187184
depth,
188185
resolve
189-
})
186+
}, options)
190187
} else {
191188
walkSet(target, path, null)
192189
resolve(path)
@@ -205,7 +202,7 @@ function bindDocument ({
205202
document,
206203
resolve,
207204
reject
208-
}) {
205+
}, options) {
209206
// TODO warning check if key exists?
210207
// const boundRefs = Object.create(null)
211208

@@ -222,7 +219,7 @@ function bindDocument ({
222219
path: key,
223220
subs,
224221
resolve
225-
})
222+
}, options)
226223
} else {
227224
resolve()
228225
}
@@ -234,7 +231,7 @@ function bindDocument ({
234231
}
235232
}
236233

237-
function bind ({ vm, key, ref }) {
234+
function bind ({ vm, key, ref }, options = { maxRefDepth: 2 }) {
238235
return new Promise((resolve, reject) => {
239236
let unbind
240237
if (ref.where) {
@@ -244,15 +241,15 @@ function bind ({ vm, key, ref }) {
244241
collection: ref,
245242
resolve,
246243
reject
247-
})
244+
}, options)
248245
} else {
249246
unbind = bindDocument({
250247
vm,
251248
key,
252249
document: ref,
253250
resolve,
254251
reject
255-
})
252+
}, options)
256253
}
257254
vm._firestoreUnbinds[key] = unbind
258255
})
@@ -286,15 +283,15 @@ function install (Vue, options) {
286283
})
287284

288285
// TODO test if $bind exist and warns
289-
Vue.prototype.$bind = function (key, ref) {
286+
Vue.prototype.$bind = function (key, ref, options) {
290287
if (this._firestoreUnbinds[key]) {
291288
this.$unbind(key)
292289
}
293290
const promise = bind({
294291
vm: this,
295292
key,
296293
ref
297-
})
294+
}, options)
298295
this.$firestoreRefs[key] = ref
299296
return promise
300297
}

src/utils.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function walkSet (obj, path, value) {
5757
const key = keys.pop()
5858
const target = keys.reduce((target, key) => target[key], obj)
5959
// global isFinite is different from Number.isFinite
60-
// it convert values to numbers
60+
// it converts values to numbers
6161
if (isFinite(key)) target.splice(key, 1, value)
6262
else target[key] = value
6363
}

test/refs-documents.spec.js

+46
Original file line numberDiff line numberDiff line change
@@ -409,3 +409,49 @@ test('correctly updates arrays', async () => {
409409

410410
expect(spy).toHaveBeenCalledTimes(3)
411411
})
412+
413+
test('respects provided maxRefDepth', async () => {
414+
await item.update({ a })
415+
await a.set({ b })
416+
await b.set({ c })
417+
await d.set({ isD: true })
418+
await c.set({ d })
419+
420+
await vm.$bind('item', item, { maxRefDepth: 1 })
421+
expect(vm.item).toEqual({
422+
a: {
423+
b: b.path
424+
}
425+
})
426+
427+
await vm.$bind('item', item, { maxRefDepth: 3 })
428+
expect(vm.item).toEqual({
429+
a: {
430+
b: {
431+
c: {
432+
d: d.path
433+
}
434+
}
435+
}
436+
})
437+
})
438+
439+
test('does not fail with cyclic refs', async () => {
440+
await item.set({ item })
441+
await vm.$bind('item', item, { maxRefDepth: 5 })
442+
443+
expect(vm.item).toEqual({
444+
// it's easy to see we stop at 5 and we have 5 brackets
445+
item: {
446+
item: {
447+
item: {
448+
item: {
449+
item: {
450+
item: item.path
451+
}
452+
}
453+
}
454+
}
455+
}
456+
})
457+
})

0 commit comments

Comments
 (0)