diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/UnitTestUtils.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/UnitTestUtils.swift index 07d20a4e1..87ab72bc4 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/UnitTestUtils.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/UnitTestUtils.swift @@ -38,6 +38,15 @@ func expectEqual( } } +func expectNotEqual( + _ lhs: T, _ rhs: T, + file: StaticString = #file, line: UInt = #line, column: UInt = #column +) throws { + if lhs == rhs { + throw MessageError("Expect to not be equal \"\(lhs)\" and \"\(rhs)\"", file: file, line: line, column: column) + } +} + func expectObject(_ value: JSValue, file: StaticString = #file, line: UInt = #line, column: UInt = #column) throws -> JSObject { switch value { case let .object(ref): return ref diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index 5110001fe..e876b60e0 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -746,4 +746,23 @@ try test("Grow Memory") { try expectEqual(string, jsString.description) } +try test("Hashable Conformance") { + let globalObject1 = JSObject.global.console.object! + let globalObject2 = JSObject.global.console.object! + try expectEqual(globalObject1.hashValue, globalObject2.hashValue) + // These are 2 different objects in Swift referencing the same object in JavaScript + try expectNotEqual(ObjectIdentifier(globalObject1), ObjectIdentifier(globalObject2)) + + let sameObjectSet: Set = [globalObject1, globalObject2] + try expectEqual(sameObjectSet.count, 1) + + let objectConstructor = JSObject.global.Object.function! + let obj = objectConstructor.new() + obj.a = 1.jsValue() + let firstHash = obj.hashValue + obj.b = 2.jsValue() + let secondHash = obj.hashValue + try expectEqual(firstHash, secondHash) +} + Expectation.wait(expectations) diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift b/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift index 9d8c52ff2..3bafe60b5 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSObject.swift @@ -135,6 +135,16 @@ extension JSObject: CustomStringConvertible { public var description: String { self.toString!().string! } } +extension JSObject: Hashable { + /// Hashes the essential components of this value by feeding them into the + /// given hasher. + /// + /// - Parameter hasher: The hasher to use when combining the components + /// of this instance. + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } +} /// A `JSObject` wrapper that enables throwing method calls capturing `this`. /// Exceptions produced by JavaScript functions will be thrown as `JSValue`.