« get me outta code hell

yaml: reuse results of makeProcessDocument - 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>2024-05-07 13:12:50 -0300
committer(quasar) nebula <qznebula@protonmail.com>2024-05-07 13:12:50 -0300
commitf00c3273409fe316f304541b7287656db76d7b67 (patch)
tree3b26c371dccd68ef918983c489a86329871bc6aa
parentabd899d2952eafdcc9969147d2401f77c9d85599 (diff)
yaml: reuse results of makeProcessDocument
-rw-r--r--src/data/yaml.js41
1 files changed, 29 insertions, 12 deletions
diff --git a/src/data/yaml.js b/src/data/yaml.js
index 25a1dd0f..bd0b55dc 100644
--- a/src/data/yaml.js
+++ b/src/data/yaml.js
@@ -706,30 +706,47 @@ export async function loadYAMLDocumentsFromFile(file) {
   return {result: filteredDocuments, aggregate};
 }
 
+// Mapping from dataStep (spec) object each to a sub-map, from thing class to
+// processDocument function.
+const processDocumentFns = new WeakMap();
+
 export function processThingsFromDataStep(documents, dataStep) {
+  let submap;
+  if (processDocumentFns.has(dataStep)) {
+    submap = processDocumentFns.get(dataStep);
+  } else {
+    submap = new Map();
+    processDocumentFns.set(dataStep, submap);
+  }
+
   function processDocument(document, thingClassOrFn) {
     const thingClass =
       (thingClassOrFn.prototype instanceof Thing
         ? thingClassOrFn
         : thingClassOrFn(document));
 
-    if (typeof thingClass !== 'function') {
-      throw new Error(`Expected a thing class, got ${typeAppearance(thingClass)}`);
-    }
+    let fn;
+    if (submap.has(thingClass)) {
+      fn = submap.get(thingClass);
+    } else {
+      if (typeof thingClass !== 'function') {
+        throw new Error(`Expected a thing class, got ${typeAppearance(thingClass)}`);
+      }
 
-    if (!(thingClass.prototype instanceof Thing)) {
-      throw new Error(`Expected a thing class, got ${thingClass.name}`);
-    }
+      if (!(thingClass.prototype instanceof Thing)) {
+        throw new Error(`Expected a thing class, got ${thingClass.name}`);
+      }
 
-    const spec = thingClass[Thing.yamlDocumentSpec];
+      const spec = thingClass[Thing.yamlDocumentSpec];
+
+      if (!spec) {
+        throw new Error(`Class "${thingClass.name}" doesn't specify Thing.yamlDocumentSpec`);
+      }
 
-    if (!spec) {
-      throw new Error(`Class "${thingClass.name}" doesn't specify Thing.yamlDocumentSpec`);
+      fn = makeProcessDocument(thingClass, spec);
+      submap.set(thingClass, fn);
     }
 
-    // TODO: Making a function to only call it just like that is
-    // obviously pretty jank! It should be created once per data step.
-    const fn = makeProcessDocument(thingClass, spec);
     return fn(document);
   }