Jelajahi Sumber

Implement Equals and GetHashCode for ObjectWrapper (#880)

Marko Lahma 4 tahun lalu
induk
melakukan
3b1faa9d0d

+ 31 - 2
Jint.Tests/Runtime/Domain/Person.cs

@@ -13,6 +13,35 @@ namespace Jint.Tests.Runtime.Domain
         {
             return Name;
         }
-    }
 
-}
+        protected bool Equals(Person other)
+        {
+            return Name == other.Name;
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj))
+            {
+                return false;
+            }
+
+            if (ReferenceEquals(this, obj))
+            {
+                return true;
+            }
+
+            if (obj.GetType() != GetType())
+            {
+                return false;
+            }
+
+            return Equals((Person) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return (Name != null ? Name.GetHashCode() : 0);
+        }
+    }
+}

+ 21 - 0
Jint.Tests/Runtime/InteropTests.cs

@@ -2526,5 +2526,26 @@ namespace Jint.Tests.Runtime
             var ex = Assert.Throws<InvalidOperationException>(() => _engine.Execute("new Class(true);"));
             Assert.Equal("thrown as requested", ex.Message);
         }
+
+        [Fact]
+        public void ObjectWrapperOverridingEquality()
+        {
+            // equality same via name
+            _engine.SetValue("a", new Person { Name = "Name" });
+            _engine.SetValue("b", new Person { Name = "Name" });
+            _engine.Execute("const arr = [ null, a, undefined ];");
+            
+            Assert.Equal(1, _engine.Execute("arr.filter(x => x == b).length").GetCompletionValue().AsNumber());
+            Assert.Equal(1, _engine.Execute("arr.filter(x => x === b).length").GetCompletionValue().AsNumber());
+
+            Assert.True(_engine.Execute("arr.find(x => x == b) === a").GetCompletionValue().AsBoolean());
+            Assert.True(_engine.Execute("arr.find(x => x === b) == a").GetCompletionValue().AsBoolean());
+
+            Assert.Equal(1, _engine.Execute("arr.findIndex(x => x == b)").GetCompletionValue().AsNumber());
+            Assert.Equal(1, _engine.Execute("arr.findIndex(x => x === b)").GetCompletionValue().AsNumber());
+
+            Assert.Equal(1, _engine.Execute("arr.indexOf(b)").GetCompletionValue().AsNumber());
+            Assert.True(_engine.Execute("arr.includes(b)").GetCompletionValue().AsBoolean());
+        }
     }
 }

+ 31 - 1
Jint/Runtime/Interop/ObjectWrapper.cs

@@ -16,7 +16,7 @@ namespace Jint.Runtime.Interop
 	/// <summary>
 	/// Wraps a CLR instance
 	/// </summary>
-	public sealed class ObjectWrapper : ObjectInstance, IObjectWrapper
+	public sealed class ObjectWrapper : ObjectInstance, IObjectWrapper, IEquatable<ObjectWrapper>
     {
         private readonly TypeDescriptor _typeDescriptor;
 
@@ -449,5 +449,35 @@ namespace Jint.Runtime.Interop
             }
             return equals;
         }
+
+        public override bool Equals(JsValue obj)
+        {
+            return Equals(obj as ObjectWrapper);
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as ObjectWrapper);
+        }
+
+        public bool Equals(ObjectWrapper other)
+        {
+            if (ReferenceEquals(null, other))
+            {
+                return false;
+            }
+
+            if (ReferenceEquals(this, other))
+            {
+                return true;
+            }
+
+            return Equals(Target, other.Target);
+        }
+
+        public override int GetHashCode()
+        {
+            return Target?.GetHashCode() ?? 0;
+        }
     }
 }