(input: object)
| 55 | } |
| 56 | |
| 57 | function hashObject(input: object): number { |
| 58 | const cachedHash = hashCache.get(input) |
| 59 | if (cachedHash !== undefined) { |
| 60 | return cachedHash |
| 61 | } |
| 62 | |
| 63 | let valueHash: number | undefined |
| 64 | if (input instanceof Date) { |
| 65 | valueHash = hashDate(input) |
| 66 | } else if ( |
| 67 | // Check if input is a Uint8Array or Buffer |
| 68 | (typeof Buffer !== `undefined` && input instanceof Buffer) || |
| 69 | input instanceof Uint8Array |
| 70 | ) { |
| 71 | // For small Uint8Arrays/Buffers (e.g., ULIDs, UUIDs), hash by content |
| 72 | // to enable proper equality comparisons. For large arrays, hash by reference |
| 73 | // to avoid performance costs. |
| 74 | if (input.byteLength <= UINT8ARRAY_CONTENT_HASH_THRESHOLD) { |
| 75 | valueHash = hashUint8Array(input) |
| 76 | } else { |
| 77 | // Deeply hashing large arrays would be too costly |
| 78 | // so we track them by reference and cache them in a weak map |
| 79 | return cachedReferenceHash(input) |
| 80 | } |
| 81 | } else if (input instanceof File) { |
| 82 | // Files are always hashed by reference due to their potentially large size |
| 83 | return cachedReferenceHash(input) |
| 84 | } else if (isTemporal(input)) { |
| 85 | valueHash = hashTemporal(input) |
| 86 | } else { |
| 87 | let plainObjectInput = input |
| 88 | let marker = OBJECT_MARKER |
| 89 | |
| 90 | if (input instanceof Array) { |
| 91 | marker = ARRAY_MARKER |
| 92 | } |
| 93 | |
| 94 | if (input instanceof Map) { |
| 95 | marker = MAP_MARKER |
| 96 | plainObjectInput = [...input.entries()] |
| 97 | } |
| 98 | |
| 99 | if (input instanceof Set) { |
| 100 | marker = SET_MARKER |
| 101 | plainObjectInput = [...input.entries()] |
| 102 | } |
| 103 | |
| 104 | valueHash = hashPlainObject(plainObjectInput, marker) |
| 105 | } |
| 106 | |
| 107 | hashCache.set(input, valueHash) |
| 108 | return valueHash |
| 109 | } |
| 110 | |
| 111 | function hashDate(input: Date): number { |
| 112 | const hasher = new MurmurHashStream() |
no test coverage detected