diff --git a/parse/location.js b/parse/location.js index 6cd2baf1..c190fa21 100644 --- a/parse/location.js +++ b/parse/location.js @@ -112,4 +112,13 @@ const parseLocation = (ctx, l) => { return res } -module.exports = parseLocation +// We use a "visitied list" to prevent endless recursion. +const seen = Symbol('parseLocation seen items') +const parseLocationWithoutCycles = (ctx, l, ...args) => { + if (ctx[seen] && ctx[seen].includes(l)) return null + + const newSeen = ctx[seen] ? [...ctx[seen], l] : [l] + return parseLocation({...ctx, [seen]: newSeen}, l, ...args) +} + +module.exports = parseLocationWithoutCycles diff --git a/test/parse/location.js b/test/parse/location.js index 5e45a632..0f1aedf3 100644 --- a/test/parse/location.js +++ b/test/parse/location.js @@ -137,7 +137,10 @@ test('handles recursive references properly', (t) => { type: 'S', name: 'Northern Platform', lid: 'a=b@L=northern-platform', - crd: {x: 44444444, y: 33333333} + crd: {x: 44444444, y: 33333333}, + // This doesn't make sense semantically, but we test if + // `parseLocation` falls into an endless recursive loop. + entryLocL: [0] } const common = {locL: [southernInput, northernInput]} const _ctx = {...ctx, res: {common}}