فهرست منبع

Update to handle circular references

Shun Miyazawa 1 سال پیش
والد
کامیت
6a8d5e9eb7
2فایلهای تغییر یافته به همراه41 افزوده شده و 18 حذف شده
  1. 40 17
      packages/core/src/utils/is-deep-equals.ts
  2. 1 1
      packages/editor/src/client/stores/codemirror-editor.ts

+ 40 - 17
packages/core/src/utils/is-deep-equals.ts

@@ -1,34 +1,57 @@
-export const isDeepEquals = <T extends object>(obj1: T, obj2: T, isRecursively = true): boolean => {
-  const typedKeys1 = Object.keys(obj1) as (keyof T)[];
-  const typedKeys2 = Object.keys(obj2) as (keyof T)[];
+const isPrimitiveComparison = (value1: unknown, value2: unknown): boolean => {
+  return value1 === null || value2 === null || typeof value1 !== 'object' || typeof value2 !== 'object';
+};
+
+export const isDeepEquals = <T extends object>(obj1: T, obj2: T, visited = new WeakMap()): boolean => {
+  // If references are identical, return true
+  if (obj1 === obj2) {
+    return true;
+  }
+
+  // Use simple comparison for null or primitive values
+  if (isPrimitiveComparison(obj1, obj2)) {
+    return obj1 === obj2;
+  }
+
+  // Check for circular references
+  if (visited.has(obj1)) {
+    return visited.get(obj1) === obj2;
+  }
+  visited.set(obj1, obj2);
+
+  // Compare number of properties
+  const typedKeys1 = Object.keys(obj1) as (keyof typeof obj1)[];
+  const typedKeys2 = Object.keys(obj2) as (keyof typeof obj2)[];
 
 
   if (typedKeys1.length !== typedKeys2.length) {
   if (typedKeys1.length !== typedKeys2.length) {
     return false;
     return false;
   }
   }
 
 
+  // Compare all properties
   return typedKeys1.every((key) => {
   return typedKeys1.every((key) => {
     const val1 = obj1[key];
     const val1 = obj1[key];
     const val2 = obj2[key];
     const val2 = obj2[key];
 
 
-    if (!isRecursively) {
-      return val1 === val2;
-    }
-
-    if (typeof val1 === 'object' && typeof val2 === 'object') {
-      if (val1 === null || val2 === null) {
-        return val1 === val2;
+    // Handle arrays comparison
+    if (Array.isArray(val1) && Array.isArray(val2)) {
+      if (val1.length !== val2.length) {
+        return false;
       }
       }
 
 
-      // if array
-      if (Array.isArray(val1) && Array.isArray(val2)) {
-        return val1.length === val2.length && val1.every((item, i) => val2[i] === item);
-      }
+      return val1.every((item, i) => {
+        if (!isPrimitiveComparison(item, val2[i])) {
+          return isDeepEquals(item, val2[i], visited);
+        }
+        return item === val2[i];
+      });
+    }
 
 
-      // if object
-      return isDeepEquals(val1, val2);
+    // Recursively compare objects
+    if (!isPrimitiveComparison(val1, val2)) {
+      return isDeepEquals(val1 as object, val2 as object, visited);
     }
     }
 
 
-    // if primitive
+    // Compare primitive values
     return val1 === val2;
     return val1 === val2;
   });
   });
 };
 };

+ 1 - 1
packages/editor/src/client/stores/codemirror-editor.ts

@@ -32,7 +32,7 @@ export const useCodeMirrorEditorIsolated = (
 
 
   const shouldUpdate = swrKey != null && container != null && (
   const shouldUpdate = swrKey != null && container != null && (
     currentData == null
     currentData == null
-    || (isValid(newData) && !isDeepEquals(currentData, newData, false))
+    || (isValid(newData) && !isDeepEquals(currentData, newData))
   );
   );
 
 
   if (shouldUpdate) {
   if (shouldUpdate) {