@@ -2,14 +2,16 @@ import { smi } from './Math';
2
2
3
3
const defaultValueOf = Object . prototype . valueOf ;
4
4
5
- export function hash ( o ) {
5
+ export function hash ( o : unknown ) : number {
6
6
// eslint-disable-next-line eqeqeq
7
7
if ( o == null ) {
8
8
return hashNullish ( o ) ;
9
9
}
10
10
11
+ // @ts -expect-error don't care about object beeing typed as `{}` here
11
12
if ( typeof o . hashCode === 'function' ) {
12
13
// Drop any high bits from accidentally long hash codes.
14
+ // @ts -expect-error don't care about object beeing typed as `{}` here
13
15
return smi ( o . hashCode ( o ) ) ;
14
16
}
15
17
@@ -45,12 +47,12 @@ export function hash(o) {
45
47
}
46
48
}
47
49
48
- function hashNullish ( nullish ) {
50
+ function hashNullish ( nullish : null | undefined ) : number {
49
51
return nullish === null ? 0x42108422 : /* undefined */ 0x42108423 ;
50
52
}
51
53
52
54
// Compress arbitrarily large numbers into smi hashes.
53
- function hashNumber ( n ) {
55
+ function hashNumber ( n : number ) : number {
54
56
if ( n !== n || n === Infinity ) {
55
57
return 0 ;
56
58
}
@@ -65,7 +67,7 @@ function hashNumber(n) {
65
67
return smi ( hash ) ;
66
68
}
67
69
68
- function cachedHashString ( string ) {
70
+ function cachedHashString ( string : string ) : number {
69
71
let hashed = stringHashCache [ string ] ;
70
72
if ( hashed === undefined ) {
71
73
hashed = hashString ( string ) ;
@@ -80,7 +82,7 @@ function cachedHashString(string) {
80
82
}
81
83
82
84
// http://jsperf.com/hashing-strings
83
- function hashString ( string ) {
85
+ function hashString ( string : string ) : number {
84
86
// This is the hash from JVM
85
87
// The hash code for a string is computed as
86
88
// s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],
@@ -94,7 +96,7 @@ function hashString(string) {
94
96
return smi ( hashed ) ;
95
97
}
96
98
97
- function hashSymbol ( sym ) {
99
+ function hashSymbol ( sym : symbol ) : number {
98
100
let hashed = symbolMap [ sym ] ;
99
101
if ( hashed !== undefined ) {
100
102
return hashed ;
@@ -107,21 +109,25 @@ function hashSymbol(sym) {
107
109
return hashed ;
108
110
}
109
111
110
- function hashJSObj ( obj ) {
111
- let hashed ;
112
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
113
+ function hashJSObj ( obj : object | Function ) : number {
114
+ let hashed : number | undefined ;
112
115
if ( usingWeakMap ) {
116
+ // @ts -expect-error weakMap is defined
113
117
hashed = weakMap . get ( obj ) ;
114
118
if ( hashed !== undefined ) {
115
119
return hashed ;
116
120
}
117
121
}
118
122
123
+ // @ts -expect-error used for old code, will be removed
119
124
hashed = obj [ UID_HASH_KEY ] ;
120
125
if ( hashed !== undefined ) {
121
126
return hashed ;
122
127
}
123
128
124
129
if ( ! canDefineProperty ) {
130
+ // @ts -expect-error used for old code, will be removed
125
131
hashed = obj . propertyIsEnumerable && obj . propertyIsEnumerable [ UID_HASH_KEY ] ;
126
132
if ( hashed !== undefined ) {
127
133
return hashed ;
@@ -136,6 +142,7 @@ function hashJSObj(obj) {
136
142
hashed = nextHash ( ) ;
137
143
138
144
if ( usingWeakMap ) {
145
+ // @ts -expect-error weakMap is defined
139
146
weakMap . set ( obj , hashed ) ;
140
147
} else if ( isExtensible !== undefined && isExtensible ( obj ) === false ) {
141
148
throw new Error ( 'Non-extensible objects are not allowed as keys.' ) ;
@@ -157,15 +164,19 @@ function hashJSObj(obj) {
157
164
obj . propertyIsEnumerable = function ( ) {
158
165
return this . constructor . prototype . propertyIsEnumerable . apply (
159
166
this ,
167
+ // eslint-disable-next-line prefer-rest-params
160
168
arguments
161
169
) ;
162
170
} ;
171
+ // @ts -expect-error used for old code, will be removed
163
172
obj . propertyIsEnumerable [ UID_HASH_KEY ] = hashed ;
173
+ // @ts -expect-error used for old code, will be removed
164
174
} else if ( obj . nodeType !== undefined ) {
165
175
// At this point we couldn't get the IE `uniqueID` to use as a hash
166
176
// and we couldn't use a non-enumerable property to exploit the
167
177
// dontEnum bug so we simply add the `UID_HASH_KEY` on the node
168
178
// itself.
179
+ // @ts -expect-error used for old code, will be removed
169
180
obj [ UID_HASH_KEY ] = hashed ;
170
181
} else {
171
182
throw new Error ( 'Unable to set a non-enumerable property on object.' ) ;
@@ -178,6 +189,7 @@ function hashJSObj(obj) {
178
189
const isExtensible = Object . isExtensible ;
179
190
180
191
// True if Object.defineProperty works as expected. IE8 fails this test.
192
+ // TODO remove this as widely available https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
181
193
const canDefineProperty = ( function ( ) {
182
194
try {
183
195
Object . defineProperty ( { } , '@' , { } ) ;
@@ -190,24 +202,30 @@ const canDefineProperty = (function () {
190
202
191
203
// IE has a `uniqueID` property on DOM nodes. We can construct the hash from it
192
204
// and avoid memory leaks from the IE cloneNode bug.
193
- function getIENodeHash ( node ) {
205
+ // TODO remove this method as only used if `canDefineProperty` is false
206
+ function getIENodeHash ( node : unknown ) : number | undefined {
207
+ // @ts -expect-error don't care
194
208
if ( node && node . nodeType > 0 ) {
209
+ // @ts -expect-error don't care
195
210
switch ( node . nodeType ) {
196
211
case 1 : // Element
212
+ // @ts -expect-error don't care
197
213
return node . uniqueID ;
198
214
case 9 : // Document
215
+ // @ts -expect-error don't care
199
216
return node . documentElement && node . documentElement . uniqueID ;
200
217
}
201
218
}
202
219
}
203
220
204
- function valueOf ( obj ) {
221
+ function valueOf ( obj : object ) : unknown {
205
222
return obj . valueOf !== defaultValueOf && typeof obj . valueOf === 'function'
206
- ? obj . valueOf ( obj )
223
+ ? // @ts -expect-error weird the "obj" parameter as `valueOf` should not have a parameter
224
+ obj . valueOf ( obj )
207
225
: obj ;
208
226
}
209
227
210
- function nextHash ( ) {
228
+ function nextHash ( ) : number {
211
229
const nextHash = ++ _objHashUID ;
212
230
if ( _objHashUID & 0x40000000 ) {
213
231
_objHashUID = 0 ;
@@ -216,8 +234,9 @@ function nextHash() {
216
234
}
217
235
218
236
// If possible, use a WeakMap.
237
+ // TODO using WeakMap should be true everywhere now that WeakMap is widely supported: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
219
238
const usingWeakMap = typeof WeakMap === 'function' ;
220
- let weakMap ;
239
+ let weakMap : WeakMap < object , number > | undefined ;
221
240
if ( usingWeakMap ) {
222
241
weakMap = new WeakMap ( ) ;
223
242
}
@@ -226,12 +245,13 @@ const symbolMap = Object.create(null);
226
245
227
246
let _objHashUID = 0 ;
228
247
229
- let UID_HASH_KEY = '__immutablehash__' ;
248
+ // TODO remove string as Symbol is now widely supported: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
249
+ let UID_HASH_KEY : string | symbol = '__immutablehash__' as const ;
230
250
if ( typeof Symbol === 'function' ) {
231
251
UID_HASH_KEY = Symbol ( UID_HASH_KEY ) ;
232
252
}
233
253
234
254
const STRING_HASH_CACHE_MIN_STRLEN = 16 ;
235
255
const STRING_HASH_CACHE_MAX_SIZE = 255 ;
236
256
let STRING_HASH_CACHE_SIZE = 0 ;
237
- let stringHashCache = { } ;
257
+ let stringHashCache : { [ key : string ] : number } = { } ;
0 commit comments