From 72cc4d62a32e40c1dcb75e868c51991075cc03e7 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 2 Oct 2023 10:40:27 -0300 Subject: data: withAlwaysReferenceByDirectory: kludge to avoid infinite recursion --- .../things/track/withAlwaysReferenceByDirectory.js | 51 +++++++++++++++++++--- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'src/data') diff --git a/src/data/composite/things/track/withAlwaysReferenceByDirectory.js b/src/data/composite/things/track/withAlwaysReferenceByDirectory.js index 7c59393c..d27f7b23 100644 --- a/src/data/composite/things/track/withAlwaysReferenceByDirectory.js +++ b/src/data/composite/things/track/withAlwaysReferenceByDirectory.js @@ -2,15 +2,22 @@ // just to the track's name, which means you don't have to always reference // some *other* (much more commonly referenced) track by directory instead // of more naturally by name. +// +// See the implementation for an important caveat about matching the original +// track against other tracks, which uses a custom implementation pulling (and +// duplicating) details from #find instead of using withOriginalRelease and the +// usual withResolvedReference / find.track() utilities. +// import {input, templateCompositeFrom} from '#composite'; import {isBoolean} from '#validators'; import {exitWithoutDependency, exposeUpdateValueOrContinue} from '#composite/control-flow'; -import {excludeFromList, withPropertyFromObject} from '#composite/data'; +import {withPropertyFromObject} from '#composite/data'; -import withOriginalRelease from './withOriginalRelease.js'; +// TODO: Kludge. (The usage of this, not so much the import.) +import CacheableObject from '../../../things/cacheable-object.js'; export default templateCompositeFrom({ annotation: `withAlwaysReferenceByDirectory`, @@ -22,15 +29,45 @@ export default templateCompositeFrom({ validate: input.value(isBoolean), }), - excludeFromList({ - list: 'trackData', - item: input.myself(), + // Remaining code is for defaulting to true if this track is a rerelease of + // another with the same name, so everything further depends on access to + // trackData as well as originalReleaseTrack. + + exitWithoutDependency({ + dependency: 'trackData', + mode: input.value('empty'), + value: input.value(false), }), - withOriginalRelease({ - data: '#trackData', + exitWithoutDependency({ + dependency: 'originalReleaseTrack', + value: input.value(false), }), + // "Slow" / uncached, manual search from trackData (with this track + // excluded). Otherwise there end up being pretty bad recursion issues + // (track1.alwaysReferencedByDirectory depends on searching through data + // including track2, which depends on evaluating track2.alwaysReferenced- + // ByDirectory, which depends on searcing through data including track1...) + // That said, this is 100% a kludge, since it involves duplicating find + // logic on a completely unrelated context. + { + dependencies: [input.myself(), 'trackData', 'originalReleaseTrack'], + compute: (continuation, { + [input.myself()]: thisTrack, + ['trackData']: trackData, + ['originalReleaseTrack']: ref, + }) => continuation({ + ['#originalRelease']: + (ref.startsWith('track:') + ? trackData.find(track => track.directory === ref.slice('track:'.length)) + : trackData.find(track => + track !== thisTrack && + !CacheableObject.getUpdateValue(track, 'originalReleaseTrack') && + track.name.toLowerCase() === ref.toLowerCase())), + }) + }, + exitWithoutDependency({ dependency: '#originalRelease', value: input.value(false), -- cgit 1.3.0-6-gf8a5