@@ -57,6 +57,8 @@ module Reflex.Dom.Builder.Immediate
5757 , phantom2
5858#endif
5959 , drawChildUpdate
60+ , ChildReadyState (..)
61+ , ChildReadyStateInt (..)
6062 , mkHasFocus
6163 , insertBefore
6264 , EventType
@@ -76,6 +78,11 @@ module Reflex.Dom.Builder.Immediate
7678 , WindowConfig (..)
7779 , Window (..)
7880 , wrapWindow
81+ -- * Internal
82+ , traverseDMapWithKeyWithAdjust'
83+ , hoistTraverseWithKeyWithAdjust
84+ , traverseIntMapWithKeyWithAdjust'
85+ , hoistTraverseIntMapWithKeyWithAdjust
7986 ) where
8087
8188import Foreign.JavaScript.TH
@@ -152,6 +159,10 @@ import GHCJS.DOM.UIEvent
152159import GHCJS.DOM.KeyboardEvent as KeyboardEvent
153160import qualified GHCJS.DOM.Window as Window
154161import Language.Javascript.JSaddle (call, eval)
162+import Data.IntMap.Strict (IntMap)
163+import qualified Data.IntMap.Strict as IntMap
164+import Data.FastMutableIntMap (PatchIntMap (..))
165+import qualified Data.FastMutableIntMap as FastMutableIntMap
155166
156167import Reflex.Requester.Base
157168import Reflex.Requester.Class
@@ -165,10 +176,10 @@ instance MonadJSM m => MonadJSM (ImmediateDomBuilderT t m) where
165176#endif
166177
167178data ImmediateDomBuilderEnv t
168− = ImmediateDomBuilderEnv { _immediateDomBuilderEnv_document :: Document
169− , _immediateDomBuilderEnv_parent :: Node
170− , _immediateDomBuilderEnv_unreadyChildren :: IORef Word -- Number of children who still aren't fully rendered
171− , _immediateDomBuilderEnv_commitAction :: JSM () -- Action to take when all children are ready --TODO: we should probably get rid of this once we invoke it
179+ = ImmediateDomBuilderEnv { _immediateDomBuilderEnv_document :: {-# UNPACK #-} !Document
180+ , _immediateDomBuilderEnv_parent :: {-# UNPACK #-} !Node
181+ , _immediateDomBuilderEnv_unreadyChildren :: {-# UNPACK #-} !(IORef Word) -- Number of children who still aren't fully rendered
182+ , _immediateDomBuilderEnv_commitAction :: !(JSM ()) -- Action to take when all children are ready --TODO: we should probably get rid of this once we invoke it
172183 }
173184
174185newtype ImmediateDomBuilderT t m a = ImmediateDomBuilderT { unImmediateDomBuilderT :: ReaderT (ImmediateDomBuilderEnv t) (RequesterT t JSM Identity (TriggerEventT t m)) a }
@@ -186,11 +197,13 @@ instance MonadTrans (ImmediateDomBuilderT t) where
186197 lift = ImmediateDomBuilderT . lift . lift . lift
187198
188199instance (Reflex t, PrimMonad m) => DomRenderHook t (ImmediateDomBuilderT t m) where
200+ {-
189201 withRenderHook hook (ImmediateDomBuilderT a) = do
190202 e <- ImmediateDomBuilderT ask
191203 ImmediateDomBuilderT $ lift $ withRequesting $ \rsp -> do
192204 (x, req) <- lift $ runRequesterT (runReaderT a e) $ runIdentity <$> rsp
193− return (ffor req $ \rm -> hook $ DMap.traverseWithKey (\_ r -> Identity <$> r) rm, x)
205+ return (ffor req $ \rm -> hook $ traverseRequesterData (\r -> Identity <$> r) rm, x)
206+-}
194207 requestDomAction = ImmediateDomBuilderT . lift . requestingIdentity
195208 requestDomAction_ = ImmediateDomBuilderT . lift . requesting_
196209
@@ -214,7 +227,7 @@ runImmediateDomBuilderT (ImmediateDomBuilderT a) env eventChan = do
214227 win <- DOM.currentWindowUnchecked
215228 rec (x, req) <- runRequesterT (runReaderT a env) rsp
216229 rsp <- performEventAsync $ ffor req $ \rm f -> liftJSM $ runInAnimationFrame handlersMVar win f $
217− DMap.traverseWithKey (\_ r -> Identity <$> r) rm
230+ traverseRequesterData (\r -> Identity <$> r) rm
218231 return x
219232 where
220233 runInAnimationFrame handlersMVar win f x = do
@@ -268,7 +281,7 @@ append n = do
268281
269282{-# INLINABLE textNodeInternal #-}
270283textNodeInternal :: (MonadJSM m, ToDOMString contents) => contents -> ImmediateDomBuilderT t m DOM.Text
271−textNodeInternal t = do
284+textNodeInternal !t = do
272285 doc <- askDocument
273286 n <- liftJSM $ createTextNode doc t
274287 append n
@@ -340,6 +353,7 @@ collectUpToGivenParent currentParent s e = do
340353
341354newtype EventFilterTriggerRef t er (en :: EventTag) = EventFilterTriggerRef (IORef (Maybe (EventTrigger t (er en))))
342355
356+{-# INLINABLE wrap #-}
343357wrap :: forall m er t. SupportsImmediateDomBuilder t m => RawElement GhcjsDomSpace -> RawElementConfig er t GhcjsDomSpace -> ImmediateDomBuilderT t m (Element er GhcjsDomSpace t)
344358wrap e cfg = do
345359 events <- askEvents
@@ -384,7 +398,7 @@ wrap e cfg = do
384398 }
385399
386400{-# INLINABLE makeElement #-}
387−makeElement :: forall er t m a. SupportsImmediateDomBuilder t m => Text -> ElementConfig er t GhcjsDomSpace -> ImmediateDomBuilderT t m a -> ImmediateDomBuilderT t m ((Element er GhcjsDomSpace t, a), DOM.Element)
401+makeElement :: forall er t m a. (Reflex t, MonadJSM m, MonadHold t m, MonadFix m, MonadReflexCreateTrigger t m, MonadRef m, Ref m ~ Ref JSM, MonadAdjust t m, PrimMonad m) => Text -> ElementConfig er t GhcjsDomSpace -> ImmediateDomBuilderT t m a -> ImmediateDomBuilderT t m ((Element er GhcjsDomSpace t, a), DOM.Element)
388402makeElement elementTag cfg child = do
389403 doc <- askDocument
390404 e <- liftJSM $ uncheckedCastTo DOM.Element <$> case cfg ^. namespace of
@@ -637,6 +651,7 @@ instance SupportsImmediateDomBuilder t m => MountableDomBuilder t (ImmediateDomB
637651 liftIO $ writeIORef (_immediateDomFragment_state fragment) $ FragmentState_Mounted (before, after)
638652
639653instance (Reflex t, MonadAdjust t m, MonadJSM m, MonadHold t m, MonadFix m, PrimMonad m) => MonadAdjust t (ImmediateDomBuilderT t m) where
654+ {-# INLINABLE runWithReplace #-}
640655 runWithReplace a0 a' = do
641656 initialEnv <- ImmediateDomBuilderT ask
642657 before <- textNodeInternal ("" :: Text)
@@ -692,31 +707,11 @@ instance (Reflex t, MonadAdjust t m, MonadJSM m, MonadHold t m, MonadFix m, Prim
692707 return (commitActionToRunNow, result)
693708 requestDomAction_ $ fmapMaybe fst child'
694709 return (result0, snd <$> child')
695− traverseDMapWithKeyWithAdjust = do
696− let updateChildUnreadiness (p :: PatchDMap k (Compose ((,,,) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v')) old = do
697− let new :: forall a. k a -> ComposeMaybe (Compose ((,,,) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v') a -> IO (ComposeMaybe (Constant (IORef (ChildReadyState k))) a)
698− new k (ComposeMaybe m) = ComposeMaybe <$> case m of
699− Nothing -> return Nothing
700− Just (Compose (_, _, sRef, _)) -> do
701− readIORef sRef >>= \case
702− ChildReadyState_Ready -> return Nothing -- Delete this child, since it's ready
703− ChildReadyState_Unready _ -> do
704− writeIORef sRef $ ChildReadyState_Unready $ Just $ Some.This k
705− return $ Just $ Constant sRef
706− delete _ (Constant sRef) = do
707− writeIORef sRef $ ChildReadyState_Unready Nothing
708− return $ Constant ()
709− p' <- fmap PatchDMap $ DMap.traverseWithKey new $ unPatchDMap p
710− _ <- DMap.traverseWithKey delete $ PatchDMap.getDeletions p old
711− return $ applyAlways p' old
712− hoistTraverseWithKeyWithAdjust traverseDMapWithKeyWithAdjust mapPatchDMap updateChildUnreadiness $ \placeholders lastPlaceholderRef (PatchDMap p) -> do
713− phs <- liftIO $ readIORef placeholders
714− forM_ (DMap.toList p) $ \(k :=> ComposeMaybe mv) -> do
715− lastPlaceholder <- liftIO $ readIORef lastPlaceholderRef
716− let nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phs
717− forM_ (Map.lookup (Some.This k) phs) $ \thisPlaceholder -> thisPlaceholder `deleteUpTo` nextPlaceholder
718− forM_ mv $ \(Compose (df, _, _, _)) -> df `insertBefore` nextPlaceholder
719− liftIO $ writeIORef placeholders $! fromMaybe phs $ apply (weakenPatchDMapWith (\(Compose (_, ph, _, _)) -> ph) $ PatchDMap p) phs
710+ {-# INLINABLE traverseIntMapWithKeyWithAdjust #-}
711+ traverseIntMapWithKeyWithAdjust = traverseIntMapWithKeyWithAdjust'
712+ {-# INLINABLE traverseDMapWithKeyWithAdjust #-}
713+ traverseDMapWithKeyWithAdjust = traverseDMapWithKeyWithAdjust'
714+ {-# INLINABLE traverseDMapWithKeyWithAdjustWithMove #-}
720715 traverseDMapWithKeyWithAdjustWithMove = do
721716 let updateChildUnreadiness (p :: PatchDMapWithMove k (Compose ((,,,) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v')) old = do
722717 let new :: forall a. k a -> PatchDMapWithMove.NodeInfo k (Compose ((,,,) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v') a -> IO (PatchDMapWithMove.NodeInfo k (Constant (IORef (ChildReadyState k))) a)
@@ -767,6 +762,62 @@ instance (Reflex t, MonadAdjust t m, MonadJSM m, MonadHold t m, MonadFix m, Prim
767762 mapM_ (\(k :=> v) -> void $ placeFragment k v) $ DMap.toDescList p -- We need to go in reverse order here, to make sure the placeholders are in the right spot at the right time
768763 liftIO $ writeIORef placeholders $! phsAfter
769764
765+{-# INLINABLE traverseDMapWithKeyWithAdjust' #-}
766+traverseDMapWithKeyWithAdjust' :: forall t m (k :: * -> *) v v'. (MonadAdjust t m, MonadHold t m, MonadFix m, MonadIO m, MonadJSM m, PrimMonad m, DMap.GCompare k) => (forall a. k a -> v a -> ImmediateDomBuilderT t m (v' a)) -> DMap k v -> Event t (PatchDMap k v) -> ImmediateDomBuilderT t m (DMap k v', Event t (PatchDMap k v'))
767+traverseDMapWithKeyWithAdjust' = do
768+ let updateChildUnreadiness (p :: PatchDMap k (Compose ((,,,) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v')) old = do
769+ let new :: forall a. k a -> ComposeMaybe (Compose ((,,,) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v') a -> IO (ComposeMaybe (Constant (IORef (ChildReadyState k))) a)
770+ new k (ComposeMaybe m) = ComposeMaybe <$> case m of
771+ Nothing -> return Nothing
772+ Just (Compose (_, _, sRef, _)) -> do
773+ readIORef sRef >>= \case
774+ ChildReadyState_Ready -> return Nothing -- Delete this child, since it's ready
775+ ChildReadyState_Unready _ -> do
776+ writeIORef sRef $ ChildReadyState_Unready $ Just $ Some.This k
777+ return $ Just $ Constant sRef
778+ delete _ (Constant sRef) = do
779+ writeIORef sRef $ ChildReadyState_Unready Nothing
780+ return $ Constant ()
781+ p' <- fmap PatchDMap $ DMap.traverseWithKey new $ unPatchDMap p
782+ _ <- DMap.traverseWithKey delete $ PatchDMap.getDeletions p old
783+ return $ applyAlways p' old
784+ hoistTraverseWithKeyWithAdjust traverseDMapWithKeyWithAdjust mapPatchDMap updateChildUnreadiness $ \placeholders lastPlaceholderRef (PatchDMap p) -> do
785+ phs <- liftIO $ readIORef placeholders
786+ forM_ (DMap.toList p) $ \(k :=> ComposeMaybe mv) -> do
787+ lastPlaceholder <- liftIO $ readIORef lastPlaceholderRef
788+ let nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phs
789+ forM_ (Map.lookup (Some.This k) phs) $ \thisPlaceholder -> thisPlaceholder `deleteUpTo` nextPlaceholder
790+ forM_ mv $ \(Compose (df, _, _, _)) -> df `insertBefore` nextPlaceholder
791+ liftIO $ writeIORef placeholders $! fromMaybe phs $ apply (weakenPatchDMapWith (\(Compose (_, ph, _, _)) -> ph) $ PatchDMap p) phs
792+
793+{-# INLINABLE traverseIntMapWithKeyWithAdjust' #-}
794+traverseIntMapWithKeyWithAdjust' :: forall t m v v'. (MonadAdjust t m, MonadHold t m, MonadFix m, MonadIO m, MonadJSM m, PrimMonad m) => (IntMap.Key -> v -> ImmediateDomBuilderT t m v') -> IntMap v -> Event t (PatchIntMap v) -> ImmediateDomBuilderT t m (IntMap v', Event t (PatchIntMap v'))
795+traverseIntMapWithKeyWithAdjust' = do
796+ let updateChildUnreadiness (p@(PatchIntMap pInner) :: PatchIntMap (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v')) old = do
797+ let new :: IntMap.Key -> Maybe (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v') -> IO (Maybe (IORef ChildReadyStateInt))
798+ new k m = case m of
799+ Nothing -> return Nothing
800+ Just (_, _, sRef, _) -> do
801+ readIORef sRef >>= \case
802+ ChildReadyStateInt_Ready -> return Nothing -- Delete this child, since it's ready
803+ ChildReadyStateInt_Unready _ -> do
804+ writeIORef sRef $ ChildReadyStateInt_Unready $ Just k
805+ return $ Just sRef
806+ delete _ sRef = do
807+ writeIORef sRef $ ChildReadyStateInt_Unready Nothing
808+ return ()
809+ p' <- fmap PatchIntMap $ IntMap.traverseWithKey new pInner
810+ _ <- IntMap.traverseWithKey delete $ FastMutableIntMap.getDeletions p old
811+ return $ applyAlways p' old
812+ hoistTraverseIntMapWithKeyWithAdjust traverseIntMapWithKeyWithAdjust updateChildUnreadiness $ \placeholders lastPlaceholderRef (PatchIntMap p) -> do
813+ phs <- liftIO $ readIORef placeholders
814+ forM_ (IntMap.toList p) $ \(k, mv) -> do
815+ lastPlaceholder <- liftIO $ readIORef lastPlaceholderRef
816+ let nextPlaceholder = maybe lastPlaceholder snd $ IntMap.lookupGT k phs
817+ forM_ (IntMap.lookup k phs) $ \thisPlaceholder -> thisPlaceholder `deleteUpTo` nextPlaceholder
818+ forM_ mv $ \(df, _, _, _) -> df `insertBefore` nextPlaceholder
819+ liftIO $ writeIORef placeholders $! fromMaybe phs $ apply (fmap (\(_, ph, _, _) -> ph) $ PatchIntMap p) phs
820+
770821#if MIN_VERSION_base(4,9,0)
771822data ChildReadyState k
772823#else
@@ -776,6 +827,95 @@ data ChildReadyState (k :: * -> *)
776827 | ChildReadyState_Unready !(Maybe (Some k))
777828 deriving (Show, Read, Eq, Ord)
778829
830+data ChildReadyStateInt
831+ = ChildReadyStateInt_Ready
832+ | ChildReadyStateInt_Unready !(Maybe Int)
833+ deriving (Show, Read, Eq, Ord)
834+
835+{-# INLINE hoistTraverseIntMapWithKeyWithAdjust #-}
836+hoistTraverseIntMapWithKeyWithAdjust :: forall v v' t m p.
837+ ( MonadAdjust t m
838+ , MonadIO m
839+ , MonadJSM m
840+ , PrimMonad m
841+ , Monoid (p (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v'))
842+ , Functor p
843+ )
844+ => ( (IntMap.Key -> v -> RequesterT t JSM Identity (TriggerEventT t m) (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v'))
845+ -> IntMap v
846+ -> Event t (p v)
847+ -> RequesterT t JSM Identity (TriggerEventT t m) (IntMap (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v'), Event t (p (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v')))
848+ ) -- ^ The base monad's traversal
849+ -> (p (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v') -> IntMap (IORef ChildReadyStateInt) -> IO (IntMap (IORef ChildReadyStateInt))) -- ^ Given a patch for the children DOM elements, produce a patch for the childrens' unreadiness state
850+ -> (IORef (IntMap DOM.Text) -> IORef DOM.Text -> p (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v') -> JSM ()) -- ^ Apply a patch to the DOM
851+ -> (IntMap.Key -> v -> ImmediateDomBuilderT t m v')
852+ -> IntMap v
853+ -> Event t (p v)
854+ -> ImmediateDomBuilderT t m (IntMap v', Event t (p v'))
855+hoistTraverseIntMapWithKeyWithAdjust base updateChildUnreadiness applyDomUpdate_ f dm0 dm' = do
856+ initialEnv <- ImmediateDomBuilderT ask
857+ let parentUnreadyChildren = _immediateDomBuilderEnv_unreadyChildren initialEnv
858+ pendingChange :: IORef (IntMap (IORef ChildReadyStateInt), p (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v')) <- liftIO $ newIORef mempty
859+ haveEverBeenReady <- liftIO $ newIORef False
860+ placeholders <- liftIO $ newIORef $ error "placeholders not yet initialized"
861+ lastPlaceholderRef <- liftIO $ newIORef $ error "lastPlaceholderRef not yet initialized"
862+ let applyDomUpdate p = do
863+ applyDomUpdate_ placeholders lastPlaceholderRef p
864+ markSelfReady
865+ liftIO $ writeIORef pendingChange $! mempty
866+ markSelfReady = do
867+ liftIO (readIORef haveEverBeenReady) >>= \case
868+ True -> return ()
869+ False -> do
870+ liftIO $ writeIORef haveEverBeenReady True
871+ old <- liftIO $ readIORef parentUnreadyChildren
872+ let new = pred old
873+ liftIO $ writeIORef parentUnreadyChildren $! new
874+ when (new == 0) $ _immediateDomBuilderEnv_commitAction initialEnv
875+ markChildReady :: IORef ChildReadyStateInt -> JSM ()
876+ markChildReady childReadyState = do
877+ liftIO (readIORef childReadyState) >>= \case
878+ ChildReadyStateInt_Ready -> return ()
879+ ChildReadyStateInt_Unready countedAt -> do
880+ liftIO $ writeIORef childReadyState ChildReadyStateInt_Ready
881+ case countedAt of
882+ Nothing -> return ()
883+ Just k -> do -- This child has been counted as unready, so we need to remove it from the unready set
884+ (oldUnready, p) <- liftIO $ readIORef pendingChange
885+ when (not $ IntMap.null oldUnready) $ do -- This shouldn't actually ever be null
886+ let newUnready = IntMap.delete k oldUnready
887+ liftIO $ writeIORef pendingChange (newUnready, p)
888+ when (IntMap.null newUnready) $ do
889+ applyDomUpdate p
890+ (children0, children') <- ImmediateDomBuilderT $ lift $ base (\k v -> drawChildUpdateInt initialEnv markChildReady $ f k v) dm0 dm'
891+ let processChild k (_, _, sRef, _) = do
892+ readIORef sRef >>= \case
893+ ChildReadyStateInt_Ready -> return Nothing
894+ ChildReadyStateInt_Unready _ -> do
895+ writeIORef sRef $ ChildReadyStateInt_Unready $ Just k
896+ return $ Just sRef
897+ initialUnready <- liftIO $ IntMap.mapMaybe id <$> IntMap.traverseWithKey processChild children0
898+ liftIO $ if IntMap.null initialUnready
899+ then writeIORef haveEverBeenReady True
900+ else do
901+ modifyIORef' parentUnreadyChildren succ
902+ writeIORef pendingChange (initialUnready, mempty) -- The patch is always empty because it got applied implicitly when we ran the children the first time
903+ let result0 = IntMap.map (\(_, _, _, v) -> v) children0
904+ placeholders0 = fmap (\(_, ph, _, _) -> ph) children0
905+ result' = ffor children' $ fmap $ \(_, _, _, r) -> r
906+ liftIO $ writeIORef placeholders $! placeholders0
907+ _ <- IntMap.traverseWithKey (\_ (df, _, _, _) -> void $ append df) children0
908+ liftIO . writeIORef lastPlaceholderRef =<< textNodeInternal ("" :: Text)
909+ requestDomAction_ $ ffor children' $ \p -> do
910+ (oldUnready, oldP) <- liftIO $ readIORef pendingChange
911+ newUnready <- liftIO $ updateChildUnreadiness p oldUnready
912+ let !newP = p <> oldP
913+ liftIO $ writeIORef pendingChange (newUnready, newP)
914+ when (IntMap.null newUnready) $ do
915+ applyDomUpdate newP
916+ return (result0, result')
917+
918+{-# INLINABLE hoistTraverseWithKeyWithAdjust #-}
779919hoistTraverseWithKeyWithAdjust :: forall (k :: * -> *) v v' t m p.
780920 ( MonadAdjust t m
781921 , MonadHold t m
@@ -865,6 +1005,7 @@ hoistTraverseWithKeyWithAdjust base mapPatch updateChildUnreadiness applyDomUpda
8651005 applyDomUpdate newP
8661006 return (result0, result')
8671007
1008+{-# INLINABLE drawChildUpdate #-}
8681009drawChildUpdate :: (MonadIO m, MonadJSM m)
8691010 => ImmediateDomBuilderEnv t
8701011 -> (IORef (ChildReadyState k) -> JSM ()) -- This will NOT be called if the child is ready at initialization time; instead, the ChildReadyState return value will be ChildReadyState_Ready
@@ -883,6 +1024,25 @@ drawChildUpdate initialEnv markReady child = do
8831024 when (u == 0) $ liftIO $ writeIORef childReadyState ChildReadyState_Ready
8841025 return $ Compose (df, placeholder, childReadyState, result)
8851026
1027+{-# INLINABLE drawChildUpdateInt #-}
1028+drawChildUpdateInt :: (MonadIO m, MonadJSM m)
1029+ => ImmediateDomBuilderEnv t
1030+ -> (IORef ChildReadyStateInt -> JSM ()) -- This will NOT be called if the child is ready at initialization time; instead, the ChildReadyState return value will be ChildReadyState_Ready
1031+ -> ImmediateDomBuilderT t m v'
1032+ -> RequesterT t JSM Identity (TriggerEventT t m) (DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v')
1033+drawChildUpdateInt initialEnv markReady child = do
1034+ childReadyState <- liftIO $ newIORef $ ChildReadyStateInt_Unready Nothing
1035+ unreadyChildren <- liftIO $ newIORef 0
1036+ df <- createDocumentFragment $ _immediateDomBuilderEnv_document initialEnv
1037+ (placeholder, result) <- runReaderT (unImmediateDomBuilderT $ (,) <$> textNodeInternal ("" :: Text) <*> child) $ initialEnv
1038+ { _immediateDomBuilderEnv_parent = toNode df
1039+ , _immediateDomBuilderEnv_unreadyChildren = unreadyChildren
1040+ , _immediateDomBuilderEnv_commitAction = markReady childReadyState
1041+ }
1042+ u <- liftIO $ readIORef unreadyChildren
1043+ when (u == 0) $ liftIO $ writeIORef childReadyState ChildReadyStateInt_Ready
1044+ return (df, placeholder, childReadyState, result)
1045+
8861046mkHasFocus :: (MonadHold t m, Reflex t) => Element er d t -> m (Dynamic t Bool)
8871047mkHasFocus e = do
8881048 let initialFocus = False --TODO: Actually get the initial focus of the element