function smi ( i32 ) { return ( ( i32 >>> 1 ) & 0x40000000 ) | ( i32 & 0xbfffffff ) ; } const defaultValueOf = Object . prototype . valueOf ; const usingWeakMap = typeof WeakMap === "function" ; let weakMap ; if ( usingWeakMap ) { weakMap = new WeakMap ( ) ; } let objHashUID = 0 ; let UID_HASH_KEY = "__immutablehash__" ; if ( typeof Symbol === "function" ) { UID_HASH_KEY = Symbol ( UID_HASH_KEY ) ; } const STRING_HASH_CACHE_MIN_STRLEN = 16 ; const STRING_HASH_CACHE_MAX_SIZE = 255 ; let STRING_HASH_CACHE_SIZE = 0 ; let stringHashCache = { } ; export const hash = function hash ( o ) { switch ( typeof o ) { case "boolean" : return o ? 0x42108421 : 0x42108420 ; case "number" : return hashNumber ( o ) ; case "string" : return o . length > STRING_HASH_CACHE_MIN_STRLEN ? cachedHashString ( o ) : hashString ( o ) ; case "object" : case "function" : if ( o === null ) { return 0x42108422 ; } if ( typeof o . hashCode === "function" ) { return smi ( o . hashCode ( o ) ) ; } if ( o . valueOf !== defaultValueOf && typeof o . valueOf === "function" ) { o = o . valueOf ( o ) ; } return hashJSObj ( o ) ; case "undefined" : return 0x42108423 ; default : if ( typeof o . toString === "function" ) { return hashString ( o . toString ( ) ) ; } throw new Error ( `Value type ${ typeof o } cannot be hashed.` ) ; } } ; function hashNumber ( n ) { if ( n !== n || n === Infinity ) { return 0 ; } let hash = n | 0 ; if ( hash !== n ) { hash ^= n * 0xffffffff ; } while ( n > 0xffffffff ) { n /= 0xffffffff ; hash ^= n ; } return smi ( hash ) ; } function cachedHashString ( string ) { let hashed = stringHashCache [ string ] ; if ( hashed === undefined ) { hashed = hashString ( string ) ; if ( STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE ) { STRING_HASH_CACHE_SIZE = 0 ; stringHashCache = { } ; } STRING_HASH_CACHE_SIZE ++ ; stringHashCache [ string ] = hashed ; } return hashed ; } function hashString ( string ) { let hashed = 0 ; for ( let ii = 0 ; ii < string . length ; ii ++ ) { hashed = ( 31 * hashed + string . charCodeAt ( ii ) ) | 0 ; } return smi ( hashed ) ; } export { hashString } ; function hashJSObj ( obj ) { let hashed ; if ( usingWeakMap ) { hashed = weakMap . get ( obj ) ; if ( hashed !== undefined ) { return hashed ; } } hashed = obj [ UID_HASH_KEY ] ; if ( hashed !== undefined ) { return hashed ; } if ( ! canDefineProperty ) { hashed = obj . propertyIsEnumerable && obj . propertyIsEnumerable [ UID_HASH_KEY ] ; if ( hashed !== undefined ) { return hashed ; } hashed = getIENodeHash ( obj ) ; if ( hashed !== undefined ) { return hashed ; } } hashed = ++ objHashUID ; if ( objHashUID & 0x40000000 ) { objHashUID = 0 ; } if ( usingWeakMap ) { weakMap . set ( obj , hashed ) ; } else if ( isExtensible !== undefined && isExtensible ( obj ) === false ) { throw new Error ( "Non-extensible objects are not allowed as keys." ) ; } else if ( canDefineProperty ) { Object . defineProperty ( obj , UID_HASH_KEY , { enumerable : false , configurable : false , writable : false , value : hashed , } ) ; } else if ( obj . propertyIsEnumerable !== undefined && obj . propertyIsEnumerable === obj . constructor . prototype . propertyIsEnumerable ) { obj . propertyIsEnumerable = function ( ) { return this . constructor . prototype . propertyIsEnumerable . apply ( this , arguments ) ; } ; obj . propertyIsEnumerable [ UID_HASH_KEY ] = hashed ; } else if ( obj . nodeType !== undefined ) { obj [ UID_HASH_KEY ] = hashed ; } else { throw new Error ( "Unable to set a non-enumerable property on object." ) ; } return hashed ; } const isExtensible = Object . isExtensible ; const canDefineProperty = ( function ( ) { try { Object . defineProperty ( { } , "@" , { } ) ; return true ; } catch ( e ) { return false ; } } ) ( ) ; function getIENodeHash ( node ) { if ( node && node . nodeType > 0 ) { switch ( node . nodeType ) { case 1 : return node . uniqueID ; case 9 : return node . documentElement && node . documentElement . uniqueID ; } } }