{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
module Miso.Reload
(
reload
, live
) where
import Control.Monad
#if __GLASGOW_HASKELL__ > 865
import GHC.Conc.Sync (threadLabel)
import GHC.Conc (listThreads, killThread)
#endif
#ifdef WASM
import Miso.DSL.TH.File (evalFile)
#endif
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, resetComponentState, Hydrate(..))
import Miso.Runtime.Internal (components)
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
#ifdef WASM
$(evalFile MISO_JS_PATH)
#endif
IO () -> IO ()
resetComponentState IO ()
clearPage
#if __GLASGOW_HASKELL__ > 865
[ThreadId]
threads <- IO [ThreadId]
listThreads
[ThreadId] -> (ThreadId -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ThreadId]
threads ((ThreadId -> IO ()) -> IO ()) -> (ThreadId -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ThreadId
threadId -> do
ThreadId -> IO (Maybe String)
threadLabel ThreadId
threadId IO (Maybe String) -> (Maybe String -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Just String
"scheduler" ->
ThreadId -> IO ()
killThread ThreadId
threadId
Maybe String
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
#endif
Events -> Hydrate -> App model action -> IO ()
forall parent model action.
(Eq parent, Eq model) =>
Events -> Hydrate -> Component parent () model action -> IO ()
initComponent Events
events Hydrate
Draw App model action
vcomp
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
#if __GLASGOW_HASKELL__ > 865
[ThreadId]
threads <- IO [ThreadId]
listThreads
[ThreadId] -> (ThreadId -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ThreadId]
threads ((ThreadId -> IO ()) -> IO ()) -> (ThreadId -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ThreadId
threadId -> do
ThreadId -> IO (Maybe String)
threadLabel ThreadId
threadId IO (Maybe String) -> (Maybe String -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Just String
"scheduler" ->
ThreadId -> IO ()
killThread ThreadId
threadId
Maybe String
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
#endif
IO ()
clearPage
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))
-> IO (IntMap (ComponentState Any Any model Any)))
-> IO (IORef (IntMap (ComponentState Any Any model Any)))
-> IO (IntMap (ComponentState Any Any model Any))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< StablePtr (IORef (IntMap (ComponentState Any Any model Any)))
-> IO (IORef (IntMap (ComponentState Any Any model Any)))
forall a. StablePtr a -> IO a
deRefStablePtr (StablePtr (IORef (IntMap (ComponentState Any Any model Any)))
-> IO (IORef (IntMap (ComponentState Any Any model Any))))
-> IO
(StablePtr (IORef (IntMap (ComponentState Any Any model Any))))
-> IO (IORef (IntMap (ComponentState Any Any model Any)))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO (StablePtr (IORef (IntMap (ComponentState Any Any model Any))))
forall a. IO (StablePtr a)
x_get
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 -> App model action -> IO ()
forall parent model action.
(Eq parent, Eq model) =>
Events -> Hydrate -> Component parent () model action -> IO ()
initComponent Events
events Hydrate
Draw App model action
initialVComp
IO ()
FFI.flush
IO ()
x_clear
StablePtr (IORef (IntMap (ComponentState Any Any Any Any)))
-> IO ()
forall a. StablePtr a -> IO ()
x_store (StablePtr (IORef (IntMap (ComponentState Any Any Any Any)))
-> IO ())
-> IO (StablePtr (IORef (IntMap (ComponentState Any Any Any Any))))
-> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IORef (IntMap (ComponentState Any Any Any Any))
-> IO (StablePtr (IORef (IntMap (ComponentState Any Any Any Any))))
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
else do
#ifdef WASM
$(evalFile MISO_JS_PATH)
#endif
StablePtr (IORef (IntMap (ComponentState Any Any Any Any)))
-> IO ()
forall a. StablePtr a -> IO ()
x_store (StablePtr (IORef (IntMap (ComponentState Any Any Any Any)))
-> IO ())
-> IO (StablePtr (IORef (IntMap (ComponentState Any Any Any Any))))
-> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IORef (IntMap (ComponentState Any Any Any Any))
-> IO (StablePtr (IORef (IntMap (ComponentState Any Any Any Any))))
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
IO () -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Events -> Hydrate -> App model action -> IO ()
forall parent model action.
(Eq parent, Eq model) =>
Events -> Hydrate -> Component parent () model action -> IO ()
initComponent Events
events Hydrate
Draw App model action
vcomp)
clearPage :: IO ()
clearPage :: IO ()
clearPage = 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)
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)