{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
#if GHCJS_FAST_WEAK
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE JavaScriptFFI #-}
#endif
module Reflex.FastWeak
( FastWeakTicket
, FastWeak
, mkFastWeakTicket
, getFastWeakTicketValue
, getFastWeakTicketWeak
, getFastWeakValue
, getFastWeakTicket
, emptyFastWeak
#ifdef GHCJS_FAST_WEAK
, unsafeFromRawJSVal
, unsafeToRawJSVal
, js_isNull
#endif
) where
import GHC.Exts (Any)
import Unsafe.Coerce
#ifdef GHCJS_FAST_WEAK
import GHCJS.Types
#else
import Control.Exception (evaluate)
import System.IO.Unsafe
import System.Mem.Weak
#endif
#ifdef GHCJS_FAST_WEAK
newtype FastWeakTicket a = FastWeakTicket JSVal
newtype FastWeak a = FastWeak JSVal
data Val a = Val { unVal :: a }
unsafeFromRawJSVal :: JSVal -> a
unsafeFromRawJSVal v = unVal (unsafeCoerce v)
unsafeToRawJSVal :: a -> JSVal
unsafeToRawJSVal v = unsafeCoerce (Val v)
#else
data FastWeakTicket a = FastWeakTicket
{ FastWeakTicket a -> a
_fastWeakTicket_val :: !a
, FastWeakTicket a -> Weak a
_fastWeakTicket_weak :: {-# UNPACK #-} !(Weak a)
}
type FastWeak a = Weak a
#endif
getFastWeakTicketValue :: FastWeakTicket a -> IO a
#ifdef GHCJS_FAST_WEAK
getFastWeakTicketValue t = do
v <- js_ticketVal t
return $ unsafeFromRawJSVal v
foreign import javascript unsafe "$r = $1.val;" js_ticketVal :: FastWeakTicket a -> IO JSVal
#else
getFastWeakTicketValue :: FastWeakTicket a -> IO a
getFastWeakTicketValue = a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> IO a) -> (FastWeakTicket a -> a) -> FastWeakTicket a -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FastWeakTicket a -> a
forall a. FastWeakTicket a -> a
_fastWeakTicket_val
#endif
getFastWeakValue :: FastWeak a -> IO (Maybe a)
#ifdef GHCJS_FAST_WEAK
getFastWeakValue w = do
r <- js_weakVal w
case js_isNull r of
True -> return Nothing
False -> return $ Just $ unsafeFromRawJSVal r
foreign import javascript unsafe "$1 === null" js_isNull :: JSVal -> Bool
foreign import javascript unsafe "$r = ($1.ticket === null) ? null : $1.ticket.val;" js_weakVal :: FastWeak a -> IO JSVal
#else
getFastWeakValue :: FastWeak a -> IO (Maybe a)
getFastWeakValue = FastWeak a -> IO (Maybe a)
forall v. Weak v -> IO (Maybe v)
deRefWeak
#endif
getFastWeakTicket :: forall a. FastWeak a -> IO (Maybe (FastWeakTicket a))
#ifdef GHCJS_FAST_WEAK
getFastWeakTicket w = do
r <- js_weakTicket w
case js_isNull r of
True -> return Nothing
False -> return $ Just $ FastWeakTicket r
foreign import javascript unsafe "$r = $1.ticket;" js_weakTicket :: FastWeak a -> IO JSVal
#else
getFastWeakTicket :: FastWeak a -> IO (Maybe (FastWeakTicket a))
getFastWeakTicket FastWeak a
w = do
FastWeak a -> IO (Maybe a)
forall v. Weak v -> IO (Maybe v)
deRefWeak FastWeak a
w IO (Maybe a)
-> (Maybe a -> IO (Maybe (FastWeakTicket a)))
-> IO (Maybe (FastWeakTicket a))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe a
Nothing -> Maybe (FastWeakTicket a) -> IO (Maybe (FastWeakTicket a))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (FastWeakTicket a)
forall a. Maybe a
Nothing
Just a
v -> Maybe (FastWeakTicket a) -> IO (Maybe (FastWeakTicket a))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (FastWeakTicket a) -> IO (Maybe (FastWeakTicket a)))
-> Maybe (FastWeakTicket a) -> IO (Maybe (FastWeakTicket a))
forall a b. (a -> b) -> a -> b
$ FastWeakTicket a -> Maybe (FastWeakTicket a)
forall a. a -> Maybe a
Just (FastWeakTicket a -> Maybe (FastWeakTicket a))
-> FastWeakTicket a -> Maybe (FastWeakTicket a)
forall a b. (a -> b) -> a -> b
$ FastWeakTicket :: forall a. a -> Weak a -> FastWeakTicket a
FastWeakTicket
{ _fastWeakTicket_val :: a
_fastWeakTicket_val = a
v
, _fastWeakTicket_weak :: FastWeak a
_fastWeakTicket_weak = FastWeak a
w
}
#endif
{-# NOINLINE mkFastWeakTicket #-}
mkFastWeakTicket :: a -> IO (FastWeakTicket a)
#ifdef GHCJS_FAST_WEAK
mkFastWeakTicket v = js_fastWeakTicket (unsafeToRawJSVal v)
foreign import javascript unsafe "$r = new h$FastWeakTicket($1);" js_fastWeakTicket :: JSVal -> IO (FastWeakTicket a)
#else
mkFastWeakTicket :: a -> IO (FastWeakTicket a)
mkFastWeakTicket a
v = do
a
v' <- a -> IO a
forall a. a -> IO a
evaluate a
v
Weak a
w <- a -> Maybe (IO ()) -> IO (Weak a)
forall k. k -> Maybe (IO ()) -> IO (Weak k)
mkWeakPtr a
v' Maybe (IO ())
forall a. Maybe a
Nothing
FastWeakTicket a -> IO (FastWeakTicket a)
forall (m :: * -> *) a. Monad m => a -> m a
return (FastWeakTicket a -> IO (FastWeakTicket a))
-> FastWeakTicket a -> IO (FastWeakTicket a)
forall a b. (a -> b) -> a -> b
$ FastWeakTicket :: forall a. a -> Weak a -> FastWeakTicket a
FastWeakTicket
{ _fastWeakTicket_val :: a
_fastWeakTicket_val = a
v'
, _fastWeakTicket_weak :: Weak a
_fastWeakTicket_weak = Weak a
w
}
#endif
getFastWeakTicketWeak :: FastWeakTicket a -> IO (FastWeak a)
#ifdef GHCJS_FAST_WEAK
foreign import javascript unsafe "$r = $1.weak;" getFastWeakTicketWeak' :: FastWeakTicket a -> IO (FastWeak a)
{-# INLINE getFastWeakTicketWeak #-}
getFastWeakTicketWeak = getFastWeakTicketWeak'
#else
getFastWeakTicketWeak :: FastWeakTicket a -> IO (FastWeak a)
getFastWeakTicketWeak = FastWeak a -> IO (FastWeak a)
forall (m :: * -> *) a. Monad m => a -> m a
return (FastWeak a -> IO (FastWeak a))
-> (FastWeakTicket a -> FastWeak a)
-> FastWeakTicket a
-> IO (FastWeak a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FastWeakTicket a -> FastWeak a
forall a. FastWeakTicket a -> Weak a
_fastWeakTicket_weak
#endif
emptyFastWeak :: FastWeak a
emptyFastWeak :: FastWeak a
emptyFastWeak = FastWeak Any -> FastWeak a
forall a b. a -> b
unsafeCoerce FastWeak Any
w
where w :: FastWeak Any
#ifdef GHCJS_FAST_WEAK
w = js_emptyWeak
#else
w :: FastWeak Any
w = IO (FastWeak Any) -> FastWeak Any
forall a. IO a -> a
unsafePerformIO (IO (FastWeak Any) -> FastWeak Any)
-> IO (FastWeak Any) -> FastWeak Any
forall a b. (a -> b) -> a -> b
$ do
FastWeak Any
w' <- Any -> Maybe (IO ()) -> IO (FastWeak Any)
forall k. k -> Maybe (IO ()) -> IO (Weak k)
mkWeakPtr Any
forall a. HasCallStack => a
undefined Maybe (IO ())
forall a. Maybe a
Nothing
FastWeak Any -> IO ()
forall v. Weak v -> IO ()
finalize FastWeak Any
w'
FastWeak Any -> IO (FastWeak Any)
forall (m :: * -> *) a. Monad m => a -> m a
return FastWeak Any
w'
#endif
{-# NOINLINE emptyFastWeak #-}
#ifdef GHCJS_FAST_WEAK
foreign import javascript unsafe "$r = new h$FastWeak(null);" js_emptyWeak :: FastWeak Any
#endif