import { isObject , isFunction , isDefined } from '@esfx/internal-guards' ; const refData = Symbol . for ( "@esfx/ref:refData" ) ; /**
 * A reference to a lexical value.
 */ export interface Reference < T > { value : T ; [ Symbol . toStringTag ] : string ; } interface InternalReference < T > extends Reference < T > { readonly [ refData ] : ReferenceData < T > ; } interface ReferenceData < T > { get : ( ) => T ; set ? : ( value : T ) => void ; } const refPrototype = { get value ( ) { const data = this [ refData ] ; if ( ! data ) throw new ReferenceError ( "Object is not a Reference." ) ; const { get } = data ; return get ( ) ; } , set value ( _ ) { const data = this [ refData ] ; if ( ! data ) throw new ReferenceError ( "Object is not a Reference." ) ; const { set } = data ; if ( ! set ) throw new ReferenceError ( "ref is readonly." ) ; set ( _ ) ; } , get [ Symbol . toStringTag ] ( ) { return "Reference" ; } } ; Object . freeze ( refPrototype ) ; param get param set export function ref < T > ( get , set ? ) { const refObj = Object . create ( refPrototype , { [ refData ] : { enumerable : false , configurable : false , writable : false , value : { get , set } } } ) ; Object . freeze ( refObj ) ; return refObj ; } export namespace ref { ref . is = function ( value ) : value is Reference < unknown > { return isObject ( value ) && refData in value ; } ; ref . for = function < T > ( value ) { return ref < T > ( ( ) => value , _ => value = _ ) ; } ; export function deref < T > ( value ) { return ref . is ( value ) ? value . value : value ; } ; /**
     * Creates a `ref` to a property of an object.
     */ export function at < T , K extends keyof T > ( object , key , readonly = false ) { return ref < T [ K ] > ( ( ) => object [ key ] , readonly ? undefined : _ => object [ key ] = _ ) ; } function outForGetSet < T > ( get , set ) { let wasSet = false ; return ref < T > ( ( ) => { if ( ! wasSet ) throw new TypeError ( "ref not set." ) ; return get ( ) ; } , _ => { set ( _ ) ; wasSet = true ; } ) ; } function outForValue < T > ( ) { let value , wasSet = false ; return ref < T > ( ( ) => { if ( ! wasSet ) throw new TypeError ( "ref not set." ) ; return value ; } , _ => { value = _ ; wasSet = true ; } ) ; } /**
     * Creates a `ref` that must be set before it can be read.
     */ export function out < T > ( ) ; export function out < T > ( get , set ) ; export function out < T > ( get ? , set ? ) { if ( isDefined ( get ) || isDefined ( set ) ) { if ( ! isFunction ( get ) ) throw new TypeError ( "Function expected: get" ) ; if ( ! isFunction ( set ) ) throw new TypeError ( "Function expected: set" ) ; return outForGetSet ( get , set ) ; } return outForValue < T > ( ) ; } Object . defineProperty ( ref , Symbol . hasInstance , { enumerable : false , configurable : true , writable : false , value : ref . is , } ) ; export const prototype = refPrototype ; } export declare namespace ref { /**
     * Determines whether `value` is a [[ref]].
     */ function _is ( value ) ; export { _is as is } ; /**
     * Creates a `ref` for an initial value.
     */ function _for < T > ( value ) ; export { _for as for } ; }