@@ -28,7 +28,7 @@ module Miso.Internal
2828 ) where
2929-----------------------------------------------------------------------------
3030import Control.Exception (throwIO )
31- import Control.Concurrent (ThreadId , killThread , threadDelay )
31+ import Control.Concurrent (ThreadId , killThread )
3232import Control.Monad (forM , forM_ , when , void )
3333import Control.Monad.IO.Class
3434import qualified Data.Aeson as A
@@ -37,6 +37,7 @@ import Data.IORef (IORef, newIORef, atomicModifyIORef', readIORef, ato
3737import Data.Map.Strict (Map )
3838import qualified Data.Map.Strict as M
3939import qualified Data.Sequence as S
40+ import Data.Sequence (Seq )
4041import qualified JavaScript.Array as JSArray
4142import Language.Javascript.JSaddle
4243import Prelude hiding (null )
@@ -89,7 +90,7 @@ initialize App {..} getView = do
8990 atomicWriteIORef componentModel newModel
9091 syncPoint
9192 eventLoop newModel
92- componentMainThread <- FFI. forkJSM (eventLoop model)
93+ _ <- FFI. forkJSM (eventLoop model)
9394 registerComponent ComponentState {.. }
9495 delegator componentMount componentVTree events (logLevel `elem` [DebugEvents , DebugAll ])
9596 forM_ initialAction componentSink
@@ -106,12 +107,12 @@ data Prerender
106107data ComponentState model action
107108 = ComponentState
108109 { componentName :: MisoString
109- , componentMainThread :: ThreadId
110110 , componentSubThreads :: [ThreadId ]
111111 , componentMount :: JSVal
112112 , componentVTree :: IORef VTree
113113 , componentSink :: action -> JSM ()
114114 , componentModel :: IORef model
115+ , componentActions :: IORef (Seq action )
115116 }
116117-----------------------------------------------------------------------------
117118-- | componentMap
@@ -205,19 +206,33 @@ drawComponent prerender name App {..} snk = do
205206 ref <- liftIO (newIORef vtree)
206207 pure (name, mountElement, ref)
207208-----------------------------------------------------------------------------
209+ -- | Drains the event queue before unmounting, executed synchronously
210+ drain
211+ :: App effect model action a
212+ -> ComponentState model action
213+ -> JSM ()
214+ drain app@ App {.. } cs@ ComponentState {.. } = do
215+ actions <- liftIO $ atomicModifyIORef' componentActions $ \ actions -> (S. empty, actions)
216+ if S. null actions then pure () else go actions
217+ where
218+ go as = do
219+ x <- liftIO (readIORef componentModel)
220+ y <- foldEffects translate update componentSink (toList as) x
221+ liftIO (atomicWriteIORef componentModel y)
222+ drain app cs
223+ -----------------------------------------------------------------------------
208224-- | Helper function for cleanly destroying a @Component@
209225unmount
210226 :: Function
211227 -> App effect model action a
212228 -> ComponentState model action
213229 -> JSM ()
214- unmount mountCallback App {.. } ComponentState {.. } = do
230+ unmount mountCallback app @ App {.. } cs @ ComponentState {.. } = do
215231 undelegator componentMount componentVTree events (logLevel `elem` [DebugEvents , DebugAll ])
216232 freeFunction mountCallback
217233 liftIO (mapM_ killThread componentSubThreads)
218- liftIO $ do
219- killThread componentMainThread
220- modifyIORef' componentMap (M. delete componentName)
234+ drain app cs
235+ liftIO $ modifyIORef' componentMap (M. delete componentName)
221236-----------------------------------------------------------------------------
222237-- | Internal function for construction of a Virtual DOM.
223238--
@@ -243,9 +258,7 @@ runView prerender (Embed attributes (SomeComponent (Component key mount app))) s
243258 FFI. syncCallback $ do
244259 M. lookup mount <$> liftIO (readIORef componentMap) >>= \ case
245260 Nothing -> pure ()
246- Just componentState -> do
247- liftIO (threadDelay (millis 1 ))
248- -- dmj ^ introduce 1ms delay to account for recursive component unmounting
261+ Just componentState ->
249262 unmount mountCallback app componentState
250263 vcomp <- createNode " vcomp" HTML key " div"
251264 setAttrs vcomp attributes snk (logLevel app) (events app)
@@ -352,10 +365,6 @@ registerComponent componentState = liftIO
352365 $ modifyIORef' componentMap
353366 $ M. insert (componentName componentState) componentState
354367-----------------------------------------------------------------------------
355- -- | Millisecond helper, converts microseconds to milliseconds
356- millis :: Int -> Int
357- millis = (* 1000 )
358- -----------------------------------------------------------------------------
359368-- | Registers components in the global state
360369renderStyles :: [CSS ] -> JSM ()
361370renderStyles styles =
0 commit comments