{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Miso.Reload
(
reload
, live
) where
import Control.Concurrent
import Control.Monad
import Miso.DSL ((!), jsg, setField)
import qualified Miso.FFI.Internal as FFI
import Miso.Types (Component(..), Events, App)
import Miso.String (MisoString)
import Miso.Runtime (componentModel, initComponent, topLevelComponentId, Hydrate(..))
import Miso.Runtime.Internal (components, schedulerThread)
import Miso.Lens
import qualified Data.IntMap.Strict as IM
import Data.IORef
import Foreign hiding (void)
import Foreign.C.Types
foreign import ccall unsafe "miso_x_store"
x_store :: StablePtr a -> IO ()
foreign import ccall unsafe "miso_x_get"
x_get :: IO (StablePtr a)
foreign import ccall unsafe "miso_x_exists"
x_exists :: IO CInt
foreign import ccall unsafe "miso_x_clear"
x_clear :: IO ()
#define MISO_JS_PATH "js/miso.js"
reload
:: Eq model
=> Events
-> App model action
-> IO ()
reload :: forall model action.
Eq model =>
Events -> App model action -> IO ()
reload Events
events App model action
vcomp = do
CInt
exists <- IO CInt
x_exists
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
exists CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
(Any
_, IORef ThreadId
oldSchedulerRef) <- StablePtr (Any, IORef ThreadId) -> IO (Any, IORef ThreadId)
forall a. StablePtr a -> IO a
deRefStablePtr (StablePtr (Any, IORef ThreadId) -> IO (Any, IORef ThreadId))
-> IO (StablePtr (Any, IORef ThreadId)) -> IO (Any, IORef ThreadId)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (StablePtr (Any, IORef ThreadId))
forall a. IO (StablePtr a)
x_get
ThreadId -> IO ()
killThread (ThreadId -> IO ()) -> IO ThreadId -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IORef ThreadId -> IO ThreadId
forall a. IORef a -> IO a
readIORef IORef ThreadId
oldSchedulerRef
IO ()
x_clear
IO ()
clearPage
IO () -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Events -> Hydrate -> Bool -> App model action -> IO ()
forall parent model action.
(Eq parent, Eq model) =>
Events
-> Hydrate -> Bool -> Component parent () model action -> IO ()
initComponent Events
events Hydrate
Draw Bool
False App model action
vcomp)
StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId)
-> IO ()
forall a. StablePtr a -> IO ()
x_store (StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId)
-> IO ())
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId))
-> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId)
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId))
forall a. a -> IO (StablePtr a)
newStablePtr (IORef (IntMap (ComponentState Any Any Any Any))
forall parent props model action.
IORef (IntMap (ComponentState parent props model action))
components, IORef ThreadId
schedulerThread)
live
:: Eq model
=> Events
-> App model action
-> IO ()
live :: forall model action.
Eq model =>
Events -> App model action -> IO ()
live Events
events App model action
vcomp = do
CInt
exists <- IO CInt
x_exists
if CInt
exists CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1
then do
IO ()
clearBody
(IORef (IntMap (ComponentState Any Any model Any))
oldComponentsRef, IORef ThreadId
oldSchedulerRef) <- StablePtr
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId)
-> IO
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId)
forall a. StablePtr a -> IO a
deRefStablePtr (StablePtr
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId)
-> IO
(IORef (IntMap (ComponentState Any Any model Any)),
IORef ThreadId))
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any model Any)),
IORef ThreadId))
-> IO
(IORef (IntMap (ComponentState Any Any model Any)), IORef ThreadId)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO
(StablePtr
(IORef (IntMap (ComponentState Any Any model Any)),
IORef ThreadId))
forall a. IO (StablePtr a)
x_get
ThreadId -> IO ()
killThread (ThreadId -> IO ()) -> IO ThreadId -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IORef ThreadId -> IO ThreadId
forall a. IORef a -> IO a
readIORef IORef ThreadId
oldSchedulerRef
IntMap (ComponentState Any Any model Any)
_oldState <- IORef (IntMap (ComponentState Any Any model Any))
-> IO (IntMap (ComponentState Any Any model Any))
forall a. IORef a -> IO a
readIORef IORef (IntMap (ComponentState Any Any model Any))
oldComponentsRef
let oldModel :: model
oldModel = (IntMap (ComponentState Any Any model Any)
_oldState IntMap (ComponentState Any Any model Any)
-> Key -> ComponentState Any Any model Any
forall a. IntMap a -> Key -> a
IM.! Key
topLevelComponentId) ComponentState Any Any model Any
-> Lens (ComponentState Any Any model Any) model -> model
forall record field. record -> Lens record field -> field
^. Lens (ComponentState Any Any model Any) model
forall parent props model action.
Lens (ComponentState parent props model action) model
componentModel
initialVComp :: App model action
initialVComp = App model action
vcomp { model = oldModel }
IORef (IntMap (ComponentState Any Any model Any))
-> IntMap (ComponentState Any Any model Any) -> IO ()
forall a. IORef a -> a -> IO ()
atomicWriteIORef IORef (IntMap (ComponentState Any Any model Any))
forall parent props model action.
IORef (IntMap (ComponentState parent props model action))
components IntMap (ComponentState Any Any model Any)
_oldState
Events -> Hydrate -> Bool -> App model action -> IO ()
forall parent model action.
(Eq parent, Eq model) =>
Events
-> Hydrate -> Bool -> Component parent () model action -> IO ()
initComponent Events
events Hydrate
Draw Bool
True App model action
initialVComp
IO ()
FFI.flush
IO ()
x_clear
StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId)
-> IO ()
forall a. StablePtr a -> IO ()
x_store (StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId)
-> IO ())
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId))
-> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId)
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId))
forall a. a -> IO (StablePtr a)
newStablePtr (IORef (IntMap (ComponentState Any Any Any Any))
forall parent props model action.
IORef (IntMap (ComponentState parent props model action))
components, IORef ThreadId
schedulerThread)
else do
IO () -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Events -> Hydrate -> Bool -> App model action -> IO ()
forall parent model action.
(Eq parent, Eq model) =>
Events
-> Hydrate -> Bool -> Component parent () model action -> IO ()
initComponent Events
events Hydrate
Draw Bool
False App model action
vcomp)
StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId)
-> IO ()
forall a. StablePtr a -> IO ()
x_store (StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId)
-> IO ())
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId))
-> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId)
-> IO
(StablePtr
(IORef (IntMap (ComponentState Any Any Any Any)), IORef ThreadId))
forall a. a -> IO (StablePtr a)
newStablePtr (IORef (IntMap (ComponentState Any Any Any Any))
forall parent props model action.
IORef (IntMap (ComponentState parent props model action))
components, IORef ThreadId
schedulerThread)
clearPage, clearBody, clearHead :: IO ()
clearPage :: IO ()
clearPage = IO ()
clearBody IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
clearHead
clearBody :: IO ()
clearBody = do
JSVal
body_ <- MisoString -> IO JSVal
jsg MisoString
"document" IO JSVal -> MisoString -> IO JSVal
forall o. ToObject o => o -> MisoString -> IO JSVal
! (MisoString
"body" :: MisoString)
JSVal -> MisoString -> MisoString -> IO ()
forall o v.
(ToObject o, ToJSVal v) =>
o -> MisoString -> v -> IO ()
setField JSVal
body_ MisoString
"innerHTML" (MisoString
"" :: MisoString)
clearHead :: IO ()
clearHead = do
JSVal
head_ <- MisoString -> IO JSVal
jsg MisoString
"document" IO JSVal -> MisoString -> IO JSVal
forall o. ToObject o => o -> MisoString -> IO JSVal
! (MisoString
"head" :: MisoString)
JSVal -> MisoString -> MisoString -> IO ()
forall o v.
(ToObject o, ToJSVal v) =>
o -> MisoString -> v -> IO ()
setField JSVal
head_ MisoString
"innerHTML" (MisoString
"" :: MisoString)