From c712bb783a2c213d036255f6468b0c06df8efc79 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 17 Jan 2024 14:18:20 -0400 Subject: data: withReverseReferenceList: mirror withReverseContributionList --- .../wiki-data/withReverseContributionList.js | 12 +++-- .../wiki-data/withReverseReferenceList.js | 52 +++++++++++++++++++--- 2 files changed, 54 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/data/composite/wiki-data/withReverseContributionList.js b/src/data/composite/wiki-data/withReverseContributionList.js index 7b07e24a..eccb58b7 100644 --- a/src/data/composite/wiki-data/withReverseContributionList.js +++ b/src/data/composite/wiki-data/withReverseContributionList.js @@ -1,9 +1,9 @@ -// Analogous implementation for withReverseReferenceList, but contributions. +// Analogous implementation for withReverseReferenceList, for contributions. +// This is all duplicate code and both should be ported to the same underlying +// data form later on. // // This implementation uses a global cache (via WeakMap) to attempt to speed -// up subsequent similar accesses. Reverse contribution lists are the most -// costly in live-dev-server, but we intend to expand the impelemntation here -// to reverse reference lists in general later on. +// 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 @@ -57,6 +57,10 @@ export default templateCompositeFrom({ for (const referencingThing of data) { const referenceList = referencingThing[list]; + + // Destructuring {who} is the only unique part of the + // withReverseContributionList implementation, compared to + // withReverseReferneceList. for (const {who: referencedThing} of referenceList) { if (cacheRecord.has(referencedThing)) { cacheRecord.get(referencedThing).push(referencingThing); diff --git a/src/data/composite/wiki-data/withReverseReferenceList.js b/src/data/composite/wiki-data/withReverseReferenceList.js index a025b5ed..2d7a421b 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) ?? [], + }); + }, }, ], }); -- cgit 1.3.0-6-gf8a5