« get me outta code hell

data: withReverseReferenceList: mirror withReverseContributionList - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/data/composite/wiki-data/withReverseReferenceList.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2024-01-17 14:18:20 -0400
committer(quasar) nebula <qznebula@protonmail.com>2024-01-17 16:10:10 -0400
commitc712bb783a2c213d036255f6468b0c06df8efc79 (patch)
tree9fd930423a978495e567aa1028612d893229a594 /src/data/composite/wiki-data/withReverseReferenceList.js
parentebe2a4d41c55be1250d4964ab16b788f70d5943b (diff)
data: withReverseReferenceList: mirror withReverseContributionList
Diffstat (limited to 'src/data/composite/wiki-data/withReverseReferenceList.js')
-rw-r--r--src/data/composite/wiki-data/withReverseReferenceList.js52
1 files changed, 46 insertions, 6 deletions
diff --git a/src/data/composite/wiki-data/withReverseReferenceList.js b/src/data/composite/wiki-data/withReverseReferenceList.js
index a025b5e..2d7a421 100644
--- a/src/data/composite/wiki-data/withReverseReferenceList.js
+++ b/src/data/composite/wiki-data/withReverseReferenceList.js
@@ -1,5 +1,15 @@
 // Check out the info on reverseReferenceList!
 // This is its composable form.
+//
+// This implementation uses a global cache (via WeakMap) to attempt to speed
+// up subsequent similar accesses.
+//
+// This has absolutely not been rigorously tested with altering properties of
+// data objects in a wiki data array which is reused. If a new wiki data array
+// is used, a fresh cache will always be created.
+//
+// Note that this implementation is mirrored in withReverseContributionList,
+// so any changes should be reflected there (until these are combined).
 
 import {input, templateCompositeFrom} from '#composite';
 
@@ -7,6 +17,12 @@ import {exitWithoutDependency} from '#composite/control-flow';
 
 import inputWikiData from './inputWikiData.js';
 
+// Mapping of reference list property to WeakMap.
+// Each WeakMap maps a wiki data array to another weak map,
+// which in turn maps each referenced thing to an array of
+// things referencing it.
+const caches = new Map();
+
 export default templateCompositeFrom({
   annotation: `withReverseReferenceList`,
 
@@ -28,14 +44,38 @@ export default templateCompositeFrom({
       dependencies: [input.myself(), input('data'), input('list')],
 
       compute: (continuation, {
-        [input.myself()]: thisThing,
+        [input.myself()]: myself,
         [input('data')]: data,
-        [input('list')]: refListProperty,
-      }) =>
-        continuation({
+        [input('list')]: list,
+      }) => {
+        if (!caches.has(list)) {
+          caches.set(list, new WeakMap());
+        }
+
+        const cache = caches.get(list);
+
+        if (!cache.has(data)) {
+          const cacheRecord = new WeakMap();
+
+          for (const referencingThing of data) {
+            const referenceList = referencingThing[list];
+            for (const referencedThing of referenceList) {
+              if (cacheRecord.has(referencedThing)) {
+                cacheRecord.get(referencedThing).push(referencingThing);
+              } else {
+                cacheRecord.set(referencedThing, [referencingThing]);
+              }
+            }
+          }
+
+          cache.set(data, cacheRecord);
+        }
+
+        return continuation({
           ['#reverseReferenceList']:
-            data.filter(thing => thing[refListProperty].includes(thisThing)),
-        }),
+            cache.get(data).get(myself) ?? [],
+        });
+      },
     },
   ],
 });