« get me outta code hell

html: Template.clone: use "ready" slot values - 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-11-19 12:31:35 -0400
committer(quasar) nebula <qznebula@protonmail.com>2024-11-19 12:31:35 -0400
commitec5f34cc804cdb47bb259a89c261ee6c44ea72e9 (patch)
tree37ea7edd6428a882a5b05917071be276d610f6cd
parent36e71fe735c13f452afdc5cd7b75fecedf27dab6 (diff)
html: Template.clone: use "ready" slot values
This doesn't fix the issue in the context we were trying to fix,
but it is semantically correct (where existing behavior is not),
which we are not proving with a unit test.
-rw-r--r--src/util/html.js24
1 files changed, 18 insertions, 6 deletions
diff --git a/src/util/html.js b/src/util/html.js
index 85464b72..913206d8 100644
--- a/src/util/html.js
+++ b/src/util/html.js
@@ -1469,7 +1469,13 @@ export class Template {
       this.#description,
     ]);
 
-    clone.setSlots(this.#slotValues);
+    // getSlotValue(), called via #getReadySlotValues(), is responsible for
+    // preparing slot values for consumption, which includes cloning mutable
+    // html/attributes. We reuse that behavior here, in a recursive manner,
+    // so that clone() is effectively "deep" - slots that may be mutated are
+    // cloned, so that this template and its clones will never mutate the same
+    // identities.
+    clone.setSlots(this.#getReadySlotValues());
 
     return clone;
   }
@@ -1795,17 +1801,23 @@ export class Template {
     return description;
   }
 
-  set content(_value) {
-    throw new Error(`Template content can't be changed after constructed`);
-  }
-
-  get content() {
+  #getReadySlotValues() {
     const slots = {};
 
     for (const slotName of Object.keys(this.description.slots ?? {})) {
       slots[slotName] = this.getSlotValue(slotName);
     }
 
+    return slots;
+  }
+
+  set content(_value) {
+    throw new Error(`Template content can't be changed after constructed`);
+  }
+
+  get content() {
+    const slots = this.#getReadySlotValues();
+
     try {
       return this.description.content(slots);
     } catch (caughtError) {