« get me outta code hell

data: withAlwaysReferenceByDirectory: kludge to avoid infinite recursion - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-10-02 10:40:27 -0300
committer(quasar) nebula <qznebula@protonmail.com>2023-10-02 10:40:27 -0300
commit72cc4d62a32e40c1dcb75e868c51991075cc03e7 (patch)
tree680cc5490532f59f46c2b87414a76dfa63d93830
parent7c938421035502484ed0e15b11064421bd7fcfce (diff)
data: withAlwaysReferenceByDirectory: kludge to avoid infinite recursion
-rw-r--r--src/data/composite/things/track/withAlwaysReferenceByDirectory.js51
1 files changed, 44 insertions, 7 deletions
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),