From be473e1ab0c4b7fc61a7b99e067ffc12683b7c90 Mon Sep 17 00:00:00 2001
From: George Treviranus <geowtrev@gmail.com>
Date: Thu, 23 May 2024 10:36:28 -0500
Subject: [PATCH] feat: improves performance of module

---
 src/modules/jsxprops.ts | 89 +++++++++++++++++++----------------------
 1 file changed, 41 insertions(+), 48 deletions(-)

diff --git a/src/modules/jsxprops.ts b/src/modules/jsxprops.ts
index c34e666..2ca2044 100644
--- a/src/modules/jsxprops.ts
+++ b/src/modules/jsxprops.ts
@@ -16,11 +16,11 @@ const ATTRS = "attrs";
 const PROPS = "props";
 const DATA = "data";
 const HYPHEN_CHAR = "-";
-const SHORTHAND_MODULE_PROPS = ["hook", "on", ATTRS, PROPS, DATASET];
-export const DOM_PROPS = ["className", "tabIndex", "id"];
+const SHORTHAND_MODULE_PROPS = new Set(["hook", "on", ATTRS, PROPS, DATASET]);
+export const DOM_PROPS = new Set(["className", "tabIndex", "id"]);
 
 // See: https://github.com/snabbdom/snabbdom/blob/master/src/vnode.ts#L21
-const IGNORE_PROPS = [
+const IGNORE_PROPS = new Set([
   "key",
   "style",
   "class",
@@ -30,7 +30,16 @@ const IGNORE_PROPS = [
   "args",
   "is",
   ...SHORTHAND_MODULE_PROPS
-];
+]);
+
+const prefixToModule: Record<string, string> = {
+  [DATA]: DATASET,
+  hook: "hook",
+  on: "on",
+  attrs: ATTRS,
+  props: PROPS,
+  dataset: DATASET
+};
 
 const forwardProp = (
   data: VNodeData,
@@ -40,12 +49,10 @@ const forwardProp = (
   prefixedKey?: string
 ) => {
   if (data[moduleName]) {
-    data[moduleName]![key] = value;
+    data[moduleName][key] = value;
   } else {
     data[moduleName] = { [key]: value };
   }
-
-  // remove the old prop from vnode data
   delete data[prefixedKey || key];
 };
 
@@ -55,55 +62,41 @@ const forwardJsxProps = (oldVNode: VNode, _vnode: VNode) => {
   if (!vnode.data) return;
 
   for (const propKey in vnode.data) {
-    // ignore modules/props that don't need handling
-    if (IGNORE_PROPS.includes(propKey)) {
+    if (IGNORE_PROPS.has(propKey)) {
       continue;
     }
-    // forward all other props into modules
-    else {
-      const propValue = vnode.data[propKey];
-
-      // forward DOM properties
-      const propertyIndex = DOM_PROPS.indexOf(propKey);
-      if (propertyIndex > -1) {
-        forwardProp(vnode.data, PROPS, DOM_PROPS[propertyIndex], propValue);
-
-        continue;
-      }
 
-      // check if prop instructs a module (using prefix)
-      const hyphenIdx = propKey.indexOf(HYPHEN_CHAR);
-      if (hyphenIdx > 0) {
-        const prefix = propKey.slice(0, hyphenIdx);
-        const moduleTarget =
-          prefix === DATA
-            ? DATA
-            : SHORTHAND_MODULE_PROPS.find(
-                (moduleName) => moduleName === prefix
-              );
+    const propValue = vnode.data[propKey];
 
-        if (moduleTarget) {
-          const propName = propKey.slice(hyphenIdx + 1);
+    // forward dom properties to props module
+    if (DOM_PROPS.has(propKey)) {
+      forwardProp(vnode.data, PROPS, propKey, propValue);
+      continue;
+    }
 
-          if (moduleTarget === DATA) {
-            forwardProp(
-              vnode.data,
-              DATASET,
-              kebabToCamel(propName),
-              propValue,
-              propKey
-            );
-          } else {
-            forwardProp(vnode.data, moduleTarget, propName, propValue, propKey);
-          }
+    // forward module-prefixed props to the correct object
+    // e.g., `vnode.data['attrs-value']` --> `vnode.data.attrs.value`
+    const hyphenIdx = propKey.indexOf(HYPHEN_CHAR);
+    if (hyphenIdx > 0) {
+      const prefix = propKey.slice(0, hyphenIdx);
+      const moduleTarget = prefixToModule[prefix];
+
+      if (moduleTarget) {
+        const propName = propKey.slice(hyphenIdx + 1);
+        forwardProp(
+          vnode.data,
+          moduleTarget,
+          moduleTarget === DATASET ? kebabToCamel(propName) : propName,
+          propValue,
+          propKey
+        );
 
-          continue;
-        }
+        continue;
       }
-
-      // forward any other props into attributes
-      forwardProp(vnode.data, ATTRS, propKey, propValue);
     }
+
+    // everything else treated as an attribute
+    forwardProp(vnode.data, ATTRS, propKey, propValue);
   }
 };