@@ -59,6 +59,7 @@ import Control.Monad.Primitive
59import Control.Monad.Reader
59import Control.Monad.Reader
60import Control.Monad.Ref
60import Control.Monad.Ref
61import Control.Monad.State.Strict
61import Control.Monad.State.Strict
62import Data.Dependent.Map (DMap)
63import Data.Dependent.Map (DMap)
63import Data.Dependent.Sum
64import Data.Dependent.Sum
64import Data.FastMutableIntMap (PatchIntMap (..))
65import Data.FastMutableIntMap (PatchIntMap (..))
@@ -188,11 +189,11 @@ addHydrationStepWithSetup setup f = getHydrationMode >>= \case
188 HydrationDomBuilderT $ modify' (>> f s)
189 HydrationDomBuilderT $ modify' (>> f s)
190-- | Add a hydration step
191-- | Add a hydration step
191−addHydrationStep :: (MonadIO m, Ref m ~ IORef, MonadRef m, PerformEvent t m, MonadFix m, MonadReflexCreateTrigger t m, MonadJSM m, MonadJSM (Performable m)) => HydrationRunnerT t m () -> HydrationDomBuilderT t m ()
193+ :: (MonadIO m, Ref m ~ IORef, MonadRef m, PerformEvent t m, MonadFix m, MonadReflexCreateTrigger t m, MonadJSM m, MonadJSM (Performable m))
194+ => HydrationRunnerT t m () -> HydrationDomBuilderT t m ()
192addHydrationStep m = getHydrationMode >>= \case
195addHydrationStep m = getHydrationMode >>= \case
193− HydrationMode_Immediate -> do
195− lift $ runHydrationRunnerT m Nothing undefined events
196+ HydrationMode_Immediate -> lift . runHydrationRunnerT m Nothing undefined =<< askEvents
196 HydrationMode_Hydrating -> HydrationDomBuilderT $ modify' (>> m)
197 HydrationMode_Hydrating -> HydrationDomBuilderT $ modify' (>> m)
198-- | A monad for DomBuilder which just gets the results of children and pushes
199-- | A monad for DomBuilder which just gets the results of children and pushes
@@ -387,6 +388,35 @@ wrap events e cfg = do
387 return $ en :=> EventFilterTriggerRef triggerRef
388 return $ en :=> EventFilterTriggerRef triggerRef
388 return eventTriggerRefs
389 return eventTriggerRefs
392+ :: forall er t x. DOM.JSContextRef
393+ -> ElementConfig er t GhcjsDomSpace
394+ -> Chan [DSum (EventTriggerRef t) TriggerInvocation]
395+ -> DMap EventName (EventFilterTriggerRef t er)
397+ -> WrapArg er EventName x
400+triggerBody ctx cfg events eventTriggerRefs e (WrapArg en) t = case DMap.lookup en eventTriggerRefs of
401+ Just (EventFilterTriggerRef r) -> do
402+ writeIORef r $ Just t
404+ writeIORef r Nothing
405+ Nothing -> (`runJSM` ctx) <$> (`runJSM` ctx) (elementOnEventName en e $ do
407+ mv <- lift $ unGhcjsEventHandler handler (en, GhcjsDomEvent evt)
409+ Nothing -> return ()
410+ Just v -> liftIO $ do
411+ --TODO: I don't think this is quite right: if a new trigger is created between when this is enqueued and when it fires, this may not work quite right
412+ ref <- newIORef $ Just t
413+ writeChan events [EventTriggerRef ref :=> TriggerInvocation v (return ())])
415+ -- Note: this needs to be done strictly and outside of the newFanEventWithTrigger, so that the newFanEventWithTrigger doesn't
416+ -- retain the entire cfg, which can cause a cyclic dependency that the GC won't be able to clean up
417+ handler :: GhcjsEventHandler er
418+ !handler = _ghcjsEventSpec_handler $ _rawElementConfig_eventSpec $ extractRawElementConfig cfg
390{-# INLINABLE makeElement #-}
420{-# INLINABLE makeElement #-}
391makeElement
421makeElement
392 :: forall er t m a. (MonadJSM m, MonadHold t m, MonadFix m, MonadReflexCreateTrigger t m, Adjustable t m, Ref m ~ IORef, PerformEvent t m, MonadJSM (Performable m), MonadRef m)
422 :: forall er t m a. (MonadJSM m, MonadHold t m, MonadFix m, MonadReflexCreateTrigger t m, Adjustable t m, Ref m ~ IORef, PerformEvent t m, MonadJSM (Performable m), MonadRef m)
@@ -413,25 +443,6 @@ makeElement elementTag cfg child = do
413 hasSSRAttribute e = case cfg ^. namespace of
443 hasSSRAttribute e = case cfg ^. namespace of
414 Nothing -> hasAttribute e ssrAttr -- TODO: disabled for debugging <* removeAttribute e ssrAttr
444 Nothing -> hasAttribute e ssrAttr -- TODO: disabled for debugging <* removeAttribute e ssrAttr
415 Just ns -> hasAttributeNS e (Just ns) ssrAttr -- TODO: disabled for debugging <* removeAttributeNS e (Just ns) ssrAttr
445 Just ns -> hasAttributeNS e (Just ns) ssrAttr -- TODO: disabled for debugging <* removeAttributeNS e (Just ns) ssrAttr
416− -- Note: this needs to be done strictly and outside of the newFanEventWithTrigger, so that the newFanEventWithTrigger doesn't
417− -- retain the entire cfg, which can cause a cyclic dependency that the GC won't be able to clean up
418− handler :: GhcjsEventHandler er
419− !handler = _ghcjsEventSpec_handler $ _rawElementConfig_eventSpec $ extractRawElementConfig cfg
420− triggerBody :: DMap EventName (EventFilterTriggerRef t er) -> DOM.Element -> WrapArg er EventName x -> EventTrigger t x -> IO (IO ())
421− triggerBody eventTriggerRefs e (WrapArg en) t = case DMap.lookup en eventTriggerRefs of
422− Just (EventFilterTriggerRef r) -> do
423− writeIORef r $ Just t
425− writeIORef r Nothing
426− Nothing -> (`runJSM` ctx) <$> (`runJSM` ctx) (elementOnEventName en e $ do
428− mv <- lift $ unGhcjsEventHandler handler (en, GhcjsDomEvent evt)
430− Nothing -> return ()
431− Just v -> liftIO $ do
432− --TODO: I don't think this is quite right: if a new trigger is created between when this is enqueued and when it fires, this may not work quite right
433− ref <- newIORef $ Just t
434− writeChan events [EventTriggerRef ref :=> TriggerInvocation v (return ())])
435 getHydrationMode >>= \case
446 getHydrationMode >>= \case
436 HydrationMode_Immediate -> do
447 HydrationMode_Immediate -> do
437 e <- makeNodeInternal buildElement
448 e <- makeNodeInternal buildElement
@@ -439,7 +450,7 @@ makeElement elementTag cfg child = do
439 -- Run the child builder with updated parent and previous sibling references
450 -- Run the child builder with updated parent and previous sibling references
440 result <- localEnv (\env -> env { _hydrationDomBuilderEnv_parent = p }) child
451 result <- localEnv (\env -> env { _hydrationDomBuilderEnv_parent = p }) child
441 eventTriggerRefs <- wrap events e $ extractRawElementConfig cfg
452 eventTriggerRefs <- wrap events e $ extractRawElementConfig cfg
442− es <- newFanEventWithTrigger $ triggerBody eventTriggerRefs e
453+ es <- newFanEventWithTrigger $ triggerBody ctx cfg events eventTriggerRefs e
443 e' <- liftIO $ newIORef e
454 e' <- liftIO $ newIORef e
444 return ((Element es e, result), e')
455 return ((Element es e, result), e')
445 HydrationMode_Hydrating -> do
456 HydrationMode_Hydrating -> do
@@ -469,7 +480,7 @@ makeElement elementTag cfg child = do
469 (e, eventTriggerRefs) <- readMVar wrapResult
480 (e, eventTriggerRefs) <- readMVar wrapResult
470 bracketOnError
481 bracketOnError
471 -- Run the setup, acquiring the cleanup action
482 -- Run the setup, acquiring the cleanup action
472− (triggerBody eventTriggerRefs e (WrapArg en) t)
483+ (triggerBody ctx cfg events eventTriggerRefs e (WrapArg en) t)
473 -- Run the cleanup, if we have it - but only when an exception is
484 -- Run the cleanup, if we have it - but only when an exception is
474 -- raised (we might get killed between acquiring the cleanup action
485 -- raised (we might get killed between acquiring the cleanup action
475 -- from 'triggerBody' and putting it in the MVar)
486 -- from 'triggerBody' and putting it in the MVar)
@@ -768,33 +779,73 @@ instance (SupportsHydrationDomBuilder t m) => DomBuilder t (HydrationDomBuilderT
769 {-# INLINABLE selectElement #-}
780 {-# INLINABLE selectElement #-}
770 selectElement cfg child = do
781 selectElement cfg child = do
771− ((e, result), _domElement') <- makeElement "select" (cfg ^. selectElementConfig_elementConfig) child
782+ ((e, result), domElementRef) <- makeElement "select" (cfg ^. selectElementConfig_elementConfig) child
772− let domElement = undefined :: DOM.HTMLSelectElement
783+
773− let domSelectElement = uncheckedCastTo DOM.HTMLSelectElement domElement
784+ (valueChangedByUI, triggerChangeByUI) <- newTriggerEvent
774− Select.setValue domSelectElement $ cfg ^. selectElementConfig_initialValue
785+ (valueChangedBySetValue, triggerChangeBySetValue) <- newTriggerEvent
775− v0 <- Select.getValue domSelectElement
786+
776− let getMyValue = Select.getValue domSelectElement
787+ (focusChange, triggerFocusChange) <- newTriggerEvent
777− valueChangedByUI <- requestDomAction $ liftJSM getMyValue <$ Reflex.select (_element_events e) (WrapArg Change)
788+
791+ -- Expected initial value from config
792+ let v0 = _selectElementConfig_initialValue cfg
794+ addHydrationStep $ do
795+ domElement <- liftIO $ readIORef domElementRef
796+ let domSelectElement = uncheckedCastTo DOM.HTMLSelectElement domElement
797+ getValue = Select.getValue domSelectElement
799+ -- The browser might have messed with the value, or the user could have
800+ -- altered it before activation, so we set it if it isn't what we expect
801+ liftJSM getValue >>= \v0' -> do
802+ when (v0' /= v0) $ liftIO $ triggerChangeByUI v0'
804+ -- Watch for user interaction and trigger event accordingly
805+ requestDomAction_ $ (liftJSM getValue >>= liftIO . triggerChangeByUI) <$ Reflex.select (_element_events e) (WrapArg Change)
778− valueChangedBySetValue <- case _selectElementConfig_setValue cfg of
807+ for_ (_selectElementConfig_setValue cfg) $ \eSetValue ->
779− Nothing -> return never
780− Just eSetValue -> requestDomAction $ ffor eSetValue $ \v' -> do
808+ requestDomAction_ $ ffor eSetValue $ \v' -> do
781− Select.setValue domSelectElement v'
809+ Select.setValue domSelectElement v'
782− getMyValue -- We get the value after setting it in case the browser has mucked with it somehow
810+ v <- getValue -- We get the value after setting it in case the browser has mucked with it somehow
811+ liftIO $ triggerChangeBySetValue v
813+ let focusChange' = leftmost
814+ [ False <$ Reflex.select (_element_events e) (WrapArg Blur)
815+ , True <$ Reflex.select (_element_events e) (WrapArg Focus)
817+ liftIO . triggerFocusChange =<< Node.isSameNode (toNode domElement) . fmap toNode =<< Document.getActiveElement doc
818+ requestDomAction_ $ liftIO . triggerFocusChange <$> focusChange'
820+ let initialFocus = False -- Assume it isn't focused, but we update the actual focus state at switchover
821+ hasFocus <- holdUniqDyn =<< holdDyn initialFocus focusChange
783 v <- holdDyn v0 $ leftmost
823 v <- holdDyn v0 $ leftmost
784 [ valueChangedBySetValue
824 [ valueChangedBySetValue
785 , valueChangedByUI
825 , valueChangedByUI
787− hasFocus <- mkHasFocus e
827+
788− let wrapped = SelectElement
828+ return $ flip (,) result $ SelectElement
789− { _selectElement_value = v
829+ { _selectElement_value = v
790− , _selectElement_change = valueChangedByUI
830+ , _selectElement_change = valueChangedByUI
791− , _selectElement_hasFocus = hasFocus
831+ , _selectElement_hasFocus = hasFocus
792− , _selectElement_element = e
832+ , _selectElement_element = e
793− , _selectElement_raw = domSelectElement
833+ , _selectElement_raw = undefined -- TODO domSelectElement
836+ placeRawElement e = getHydrationMode >>= \case
837+ HydrationMode_Immediate -> append $ toNode e
838+ HydrationMode_Hydrating -> addHydrationStep $ insertAfterPreviousNode e
839+ wrapRawElement e rawCfg = do
842+ let cfg = (def :: ElementConfig EventResult t GhcjsDomSpace)
843+ { _elementConfig_modifyAttributes = _rawElementConfig_modifyAttributes rawCfg
844+ , _elementConfig_eventSpec = _rawElementConfig_eventSpec rawCfg
795− return (wrapped, result)
846+ eventTriggerRefs <- wrap events e rawCfg
796− placeRawElement _ = return () -- append . toNode
847+ es <- newFanEventWithTrigger $ triggerBody ctx cfg events eventTriggerRefs e
797− wrapRawElement e _ = return $ Element (EventSelector $ const never) e -- TODO
848+ return $ Element es e
799data FragmentState
850data FragmentState
800 = FragmentState_Unmounted
851 = FragmentState_Unmounted
@@ -842,7 +893,7 @@ instance (Reflex t, Monad m, Adjustable t m, MonadHold t m, MonadFix m) => Adjus
842 traverseDMapWithKeyWithAdjust f m = DomRenderHookT . traverseDMapWithKeyWithAdjust (\k -> unDomRenderHookT . f k) m
893 traverseDMapWithKeyWithAdjust f m = DomRenderHookT . traverseDMapWithKeyWithAdjust (\k -> unDomRenderHookT . f k) m
843 traverseDMapWithKeyWithAdjustWithMove f m = DomRenderHookT . traverseDMapWithKeyWithAdjustWithMove (\k -> unDomRenderHookT . f k) m
894 traverseDMapWithKeyWithAdjustWithMove f m = DomRenderHookT . traverseDMapWithKeyWithAdjustWithMove (\k -> unDomRenderHookT . f k) m
845−instance (Reflex t, Adjustable t m, MonadJSM m, MonadHold t m, MonadFix m, PrimMonad m, Ref m ~ IORef, MonadReflexCreateTrigger t m, MonadJSM (Performable m), MonadRef m) => Adjustable t (HydrationDomBuilderT t m) where
896+instance (Adjustable t m, MonadJSM m, MonadHold t m, MonadFix m, PrimMonad m) => Adjustable t (HydrationDomBuilderT t m) where
846 {-# INLINABLE runWithReplace #-}
897 {-# INLINABLE runWithReplace #-}
847 runWithReplace a0 a' = do
898 runWithReplace a0 a' = do
848 initialEnv <- HydrationDomBuilderT ask
899 initialEnv <- HydrationDomBuilderT ask
@@ -932,15 +983,15 @@ instance (Reflex t, Adjustable t m, MonadJSM m, MonadHold t m, MonadFix m, PrimM
932 traverseDMapWithKeyWithAdjust = traverseDMapWithKeyWithAdjust'
983 traverseDMapWithKeyWithAdjust = traverseDMapWithKeyWithAdjust'
933 {-# INLINABLE traverseDMapWithKeyWithAdjustWithMove #-}
984 {-# INLINABLE traverseDMapWithKeyWithAdjustWithMove #-}
934 traverseDMapWithKeyWithAdjustWithMove = do
985 traverseDMapWithKeyWithAdjustWithMove = do
935− let updateChildUnreadiness (p :: PatchDMapWithMove k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v')) old = do
986+ let updateChildUnreadiness (p :: PatchDMapWithMove k (Compose (TraverseDMapChild t m k) v')) old = do
936− let new :: forall a. k a -> PatchDMapWithMove.NodeInfo k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v') a -> IO (PatchDMapWithMove.NodeInfo k (Constant (IORef (ChildReadyState k))) a)
987+ let new :: forall a. k a -> PatchDMapWithMove.NodeInfo k (Compose (TraverseDMapChild t m k) v') a -> IO (PatchDMapWithMove.NodeInfo k (Constant (IORef (ChildReadyState k))) a)
937 new k = PatchDMapWithMove.nodeInfoMapFromM $ \case
988 new k = PatchDMapWithMove.nodeInfoMapFromM $ \case
938− PatchDMapWithMove.From_Insert (Compose (_, _, _, sRef, _)) -> do
989+ PatchDMapWithMove.From_Insert (Compose (TraverseDMapChild (Right myTypeImmediate) _)) -> do
939− readIORef sRef >>= \case
990+ readIORef (_traverseDMapChildImmediate_childReadyState myTypeImmediate) >>= \case
940 ChildReadyState_Ready -> return PatchDMapWithMove.From_Delete
991 ChildReadyState_Ready -> return PatchDMapWithMove.From_Delete
941 ChildReadyState_Unready _ -> do
992 ChildReadyState_Unready _ -> do
942− writeIORef sRef $ ChildReadyState_Unready $ Just $ Some.This k
993+ writeIORef (_traverseDMapChildImmediate_childReadyState myTypeImmediate) $ ChildReadyState_Unready $ Just $ Some.This k
943− return $ PatchDMapWithMove.From_Insert $ Constant sRef
994+ return $ PatchDMapWithMove.From_Insert $ Constant (_traverseDMapChildImmediate_childReadyState myTypeImmediate)
944 PatchDMapWithMove.From_Delete -> return PatchDMapWithMove.From_Delete
995 PatchDMapWithMove.From_Delete -> return PatchDMapWithMove.From_Delete
945 PatchDMapWithMove.From_Move fromKey -> return $ PatchDMapWithMove.From_Move fromKey
996 PatchDMapWithMove.From_Move fromKey -> return $ PatchDMapWithMove.From_Move fromKey
946 deleteOrMove :: forall a. k a -> Product (Constant (IORef (ChildReadyState k))) (ComposeMaybe k) a -> IO (Constant () a)
997 deleteOrMove :: forall a. k a -> Product (Constant (IORef (ChildReadyState k))) (ComposeMaybe k) a -> IO (Constant () a)
@@ -950,11 +1001,10 @@ instance (Reflex t, Adjustable t m, MonadJSM m, MonadHold t m, MonadFix m, PrimM
950 p' <- fmap unsafePatchDMapWithMove $ DMap.traverseWithKey new $ unPatchDMapWithMove p
1001 p' <- fmap unsafePatchDMapWithMove $ DMap.traverseWithKey new $ unPatchDMapWithMove p
951 _ <- DMap.traverseWithKey deleteOrMove $ PatchDMapWithMove.getDeletionsAndMoves p old
1002 _ <- DMap.traverseWithKey deleteOrMove $ PatchDMapWithMove.getDeletionsAndMoves p old
952 return $ applyAlways p' old
1003 return $ applyAlways p' old
953− hoistTraverseWithKeyWithAdjust traverseDMapWithKeyWithAdjustWithMove mapPatchDMapWithMove updateChildUnreadiness $ \placeholders lastPlaceholderRef (p_ :: PatchDMapWithMove k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v')) -> do
1004+ hoistTraverseWithKeyWithAdjust traverseDMapWithKeyWithAdjustWithMove mapPatchDMapWithMove updateChildUnreadiness $ \placeholders lastPlaceholder (p_ :: PatchDMapWithMove k (Compose (TraverseDMapChild t m k) v')) -> do
954 let p = unPatchDMapWithMove p_
1005 let p = unPatchDMapWithMove p_
955 phsBefore <- liftIO $ readIORef placeholders
1006 phsBefore <- liftIO $ readIORef placeholders
956− lastPlaceholder <- liftIO $ readIORef lastPlaceholderRef
957− let collectIfMoved :: forall a. k a -> PatchDMapWithMove.NodeInfo k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v') a -> JSM (Constant (Maybe DOM.DocumentFragment) a)
1007+ let collectIfMoved :: forall a. k a -> PatchDMapWithMove.NodeInfo k (Compose (TraverseDMapChild t m k) v') a -> JSM (Constant (Maybe DOM.DocumentFragment) a)
958 collectIfMoved k e = do
1008 collectIfMoved k e = do
959 let mThisPlaceholder = Map.lookup (Some.This k) phsBefore -- Will be Nothing if this element wasn't present before
1009 let mThisPlaceholder = Map.lookup (Some.This k) phsBefore -- Will be Nothing if this element wasn't present before
960 nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phsBefore
1010 nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phsBefore
@@ -965,13 +1015,14 @@ instance (Reflex t, Adjustable t m, MonadJSM m, MonadHold t m, MonadFix m, PrimM
965 True -> do
1015 True -> do
966 Constant <$> mapM (`collectUpTo` nextPlaceholder) mThisPlaceholder
1016 Constant <$> mapM (`collectUpTo` nextPlaceholder) mThisPlaceholder
967 collected <- DMap.traverseWithKey collectIfMoved p
1017 collected <- DMap.traverseWithKey collectIfMoved p
968− let !phsAfter = fromMaybe phsBefore $ apply (weakenPatchDMapWithMoveWith (\(Compose (_, _, ph, _, _)) -> ph) p_) phsBefore --TODO: Don't recompute this
1018+ let !phsAfter = fromMaybe phsBefore $ apply (weakenPatchDMapWithMoveWith (_traverseDMapChildImmediate_placeholder . error "FIXME" . _traverseDMapChild_mode . getCompose) p_) phsBefore --TODO: Don't recompute this
969− let placeFragment :: forall a. k a -> PatchDMapWithMove.NodeInfo k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v') a -> JSM (Constant () a)
1019+ let placeFragment :: forall a. k a -> PatchDMapWithMove.NodeInfo k (Compose (TraverseDMapChild t m k) v') a -> JSM (Constant () a)
970 placeFragment k e = do
1020 placeFragment k e = do
971 let nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phsAfter
1021 let nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phsAfter
972 case PatchDMapWithMove._nodeInfo_from e of
1022 case PatchDMapWithMove._nodeInfo_from e of
973− PatchDMapWithMove.From_Insert (Compose (_, df, _, _, _)) -> do
1023+ PatchDMapWithMove.From_Insert (Compose (TraverseDMapChild x _)) -> case x of
974− df `insertBefore` nextPlaceholder
1025+ Right immediate -> _traverseDMapChildImmediate_fragment immediate `insertBefore` nextPlaceholder
975 PatchDMapWithMove.From_Delete -> do
1026 PatchDMapWithMove.From_Delete -> do
976 return ()
1027 return ()
977 PatchDMapWithMove.From_Move fromKey -> do
1028 PatchDMapWithMove.From_Move fromKey -> do
@@ -983,40 +1034,54 @@ instance (Reflex t, Adjustable t m, MonadJSM m, MonadHold t m, MonadFix m, PrimM
984{-# INLINABLE traverseDMapWithKeyWithAdjust' #-}
1035{-# INLINABLE traverseDMapWithKeyWithAdjust' #-}
985traverseDMapWithKeyWithAdjust'
1036traverseDMapWithKeyWithAdjust'
986− :: forall t m (k :: * -> *) v v'. (Adjustable t m, MonadHold t m, MonadFix m, MonadIO m, MonadJSM m, PrimMonad m, DMap.GCompare k)
1037+ :: forall t m (k :: * -> *) v v'. (Adjustable t m, MonadHold t m, MonadFix m, MonadJSM m, PrimMonad m, DMap.GCompare k)
987 => (forall a. k a -> v a -> HydrationDomBuilderT t m (v' a))
1038 => (forall a. k a -> v a -> HydrationDomBuilderT t m (v' a))
988 -> DMap k v
1039 -> DMap k v
989 -> Event t (PatchDMap k v)
1040 -> Event t (PatchDMap k v)
990 -> HydrationDomBuilderT t m (DMap k v', Event t (PatchDMap k v'))
1041 -> HydrationDomBuilderT t m (DMap k v', Event t (PatchDMap k v'))
991traverseDMapWithKeyWithAdjust' = do
1042traverseDMapWithKeyWithAdjust' = do
992− let updateChildUnreadiness (p :: PatchDMap k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v')) old = do
1043+ let updateChildUnreadiness (p :: PatchDMap k (Compose (TraverseDMapChild t m k) v')) old = do
993− let new :: forall a. k a -> ComposeMaybe (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v') a -> IO (ComposeMaybe (Constant (IORef (ChildReadyState k))) a)
1044+ let new :: forall a. k a -> ComposeMaybe (Compose (TraverseDMapChild t m k) v') a -> IO (ComposeMaybe (Constant (IORef (ChildReadyState k))) a)
994 new k (ComposeMaybe m) = ComposeMaybe <$> case m of
1045 new k (ComposeMaybe m) = ComposeMaybe <$> case m of
995 Nothing -> return Nothing
1046 Nothing -> return Nothing
996− Just (Compose (_, _, _, sRef, _)) -> do
1047+ Just (Compose (TraverseDMapChild (Left hydration) _)) -> pure Nothing
997− readIORef sRef >>= \case
1048+ Just (Compose (TraverseDMapChild (Right immediate) _)) -> do
1049+ readIORef (_traverseDMapChildImmediate_childReadyState immediate) >>= \case
998 ChildReadyState_Ready -> return Nothing -- Delete this child, since it's ready
1050 ChildReadyState_Ready -> return Nothing -- Delete this child, since it's ready
999 ChildReadyState_Unready _ -> do
1051 ChildReadyState_Unready _ -> do
1000− writeIORef sRef $ ChildReadyState_Unready $ Just $ Some.This k
1052+ writeIORef (_traverseDMapChildImmediate_childReadyState immediate) $ ChildReadyState_Unready $ Just $ Some.This k
1001− return $ Just $ Constant sRef
1053+ return $ Just $ Constant (_traverseDMapChildImmediate_childReadyState immediate)
1002 delete _ (Constant sRef) = do
1054 delete _ (Constant sRef) = do
1003 writeIORef sRef $ ChildReadyState_Unready Nothing
1055 writeIORef sRef $ ChildReadyState_Unready Nothing
1004 return $ Constant ()
1056 return $ Constant ()
1005 p' <- fmap PatchDMap $ DMap.traverseWithKey new $ unPatchDMap p
1057 p' <- fmap PatchDMap $ DMap.traverseWithKey new $ unPatchDMap p
1006 _ <- DMap.traverseWithKey delete $ PatchDMap.getDeletions p old
1058 _ <- DMap.traverseWithKey delete $ PatchDMap.getDeletions p old
1007 return $ applyAlways p' old
1059 return $ applyAlways p' old
1008− hoistTraverseWithKeyWithAdjust traverseDMapWithKeyWithAdjust mapPatchDMap updateChildUnreadiness $ \placeholders lastPlaceholderRef (PatchDMap p) -> do
1060+ hoistTraverseWithKeyWithAdjust traverseDMapWithKeyWithAdjust mapPatchDMap updateChildUnreadiness $ \placeholders lastPlaceholder (PatchDMap patch) -> do
1009 phs <- liftIO $ readIORef placeholders
1061 phs <- liftIO $ readIORef placeholders
1010− forM_ (DMap.toList p) $ \(k :=> ComposeMaybe mv) -> do
1062+ forM_ (DMap.toList patch) $ \(k :=> ComposeMaybe mv) -> do
1011− lastPlaceholder <- liftIO $ readIORef lastPlaceholderRef
1012 let nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phs
1063 let nextPlaceholder = maybe lastPlaceholder snd $ Map.lookupGT (Some.This k) phs
1013− forM_ (Map.lookup (Some.This k) phs) $ \thisPlaceholder -> thisPlaceholder `deleteUpTo` nextPlaceholder
1065+ forM_ (Map.lookup (Some.This k) phs) $ \thisPlaceholder -> do
1066+ thisPlaceholder `deleteUpTo` nextPlaceholder
1068+ forM_ mv $ \(Compose (TraverseDMapChild e _)) -> case e of
1069+ Left _hydration -> pure ()
1070+ Right immediate -> do
1014− forM_ mv $ \(Compose (_, df, _, _, _)) -> df `insertBefore` nextPlaceholder
1071+ _traverseDMapChildImmediate_fragment immediate `insertBefore` nextPlaceholder
1072+ let weakened :: PatchMap (Some.Some k) (Either (TraverseDMapChildHydration t m) (TraverseDMapChildImmediate k))
1073+ weakened = weakenPatchDMapWith (_traverseDMapChild_mode . getCompose) $ PatchDMap patch
1074+ filtered :: PatchMap (Some.Some k) DOM.Text
1075+ filtered = PatchMap $ flip Map.mapMaybe (unPatchMap weakened) $ \case
1076+ Nothing -> Just Nothing -- deletion
1077+ Just (Left _) -> Nothing
1078+ Just (Right immediate) -> Just $ Just $ _traverseDMapChildImmediate_placeholder immediate
1079+ a = apply filtered phs
1015− liftIO $ writeIORef placeholders $! fromMaybe phs $ apply (weakenPatchDMapWith (\(Compose (_, _, ph, _, _)) -> ph) $ PatchDMap p) phs
1080+ liftIO $ writeIORef placeholders $! fromMaybe phs a
1017{-# INLINABLE traverseIntMapWithKeyWithAdjust' #-}
1082{-# INLINABLE traverseIntMapWithKeyWithAdjust' #-}
1018traverseIntMapWithKeyWithAdjust'
1083traverseIntMapWithKeyWithAdjust'
1019− :: forall t m v v'. (Adjustable t m, MonadHold t m, MonadFix m, MonadIO m, MonadJSM m, PrimMonad m)
1084+ :: forall t m v v'. (Adjustable t m, MonadJSM m, MonadFix m, PrimMonad m, MonadHold t m)
1020 => (IntMap.Key -> v -> HydrationDomBuilderT t m v')
1085 => (IntMap.Key -> v -> HydrationDomBuilderT t m v')
1021 -> IntMap v
1086 -> IntMap v
1022 -> Event t (PatchIntMap v)
1087 -> Event t (PatchIntMap v)
@@ -1050,14 +1115,13 @@ traverseIntMapWithKeyWithAdjust' = do
1050{-# INLINE hoistTraverseIntMapWithKeyWithAdjust #-}
1115{-# INLINE hoistTraverseIntMapWithKeyWithAdjust #-}
1051hoistTraverseIntMapWithKeyWithAdjust :: forall v v' t m p.
1116hoistTraverseIntMapWithKeyWithAdjust :: forall v v' t m p.
1052 ( Adjustable t m
1117 ( Adjustable t m
1053− , MonadIO m
1118+ , MonadHold t m
1054 , MonadJSM m
1119 , MonadJSM m
1055 , MonadFix m
1120 , MonadFix m
1056 , PrimMonad m
1121 , PrimMonad m
1057 , Monoid (p (HydrationRunnerT t m (), DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v'))
1122 , Monoid (p (HydrationRunnerT t m (), DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v'))
1058 , Functor p
1123 , Functor p
1059 , PatchTarget (p (HydrationRunnerT t m ())) ~ IntMap (HydrationRunnerT t m ())
1124 , PatchTarget (p (HydrationRunnerT t m ())) ~ IntMap (HydrationRunnerT t m ())
1061 , Patch (p (HydrationRunnerT t m ()))
1125 , Patch (p (HydrationRunnerT t m ()))
1063 => ( (IntMap.Key -> v -> DomRenderHookT t m (HydrationRunnerT t m (), DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v'))
1127 => ( (IntMap.Key -> v -> DomRenderHookT t m (HydrationRunnerT t m (), DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v'))
@@ -1072,7 +1136,6 @@ hoistTraverseIntMapWithKeyWithAdjust :: forall v v' t m p.
1072 -> Event t (p v)
1136 -> Event t (p v)
1073 -> HydrationDomBuilderT t m (IntMap v', Event t (p v'))
1137 -> HydrationDomBuilderT t m (IntMap v', Event t (p v'))
1074hoistTraverseIntMapWithKeyWithAdjust base updateChildUnreadiness applyDomUpdate_ f dm0 dm' = do
1138hoistTraverseIntMapWithKeyWithAdjust base updateChildUnreadiness applyDomUpdate_ f dm0 dm' = do
1075− (_hydrateStart, _, key) <- skipToReplaceStart
1076 initialEnv <- HydrationDomBuilderT ask
1139 initialEnv <- HydrationDomBuilderT ask
1077 let parentUnreadyChildren = _hydrationDomBuilderEnv_unreadyChildren initialEnv
1140 let parentUnreadyChildren = _hydrationDomBuilderEnv_unreadyChildren initialEnv
1078 pendingChange :: IORef (IntMap (IORef ChildReadyStateInt), p (HydrationRunnerT t m (), DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v')) <- liftIO $ newIORef mempty
1141 pendingChange :: IORef (IntMap (IORef ChildReadyStateInt), p (HydrationRunnerT t m (), DOM.DocumentFragment, DOM.Text, IORef ChildReadyStateInt, v')) <- liftIO $ newIORef mempty
@@ -1139,7 +1202,6 @@ hoistTraverseIntMapWithKeyWithAdjust base updateChildUnreadiness applyDomUpdate_
1139 getHydrationMode >>= \case
1202 getHydrationMode >>= \case
1140 HydrationMode_Immediate -> void $ IntMap.traverseWithKey (\_ (_, df, _, _, _) -> void $ append $ toNode df) children0
1203 HydrationMode_Immediate -> void $ IntMap.traverseWithKey (\_ (_, df, _, _, _) -> void $ append $ toNode df) children0
1141 _ -> pure ()
1204 _ -> pure ()
1142− (_hydrateEnd, _lastPlaceholderRef) <- skipToReplaceEnd key
1143 requestDomAction_ $ ffor children' $ \p -> do
1205 requestDomAction_ $ ffor children' $ \p -> do
1144 (oldUnready, oldP) <- liftIO $ readIORef pendingChange
1206 (oldUnready, oldP) <- liftIO $ readIORef pendingChange
1145 newUnready <- liftIO $ updateChildUnreadiness p oldUnready
1207 newUnready <- liftIO $ updateChildUnreadiness p oldUnready
@@ -1156,6 +1218,24 @@ insertAfterPreviousNode node = do
1156 Node.insertBefore_ parent node nextNode
1218 Node.insertBefore_ parent node nextNode
1157 setPreviousNode $ Just $ toNode node
1219 setPreviousNode $ Just $ toNode node
1221+data TraverseDMapChildImmediate k = TraverseDMapChildImmediate
1222+ { _traverseDMapChildImmediate_fragment :: DOM.DocumentFragment
1223+ -- ^ Child is appended to this fragment
1224+ , _traverseDMapChildImmediate_placeholder :: DOM.Text
1225+ -- ^ Placeholder reference
1226+ , _traverseDMapChildImmediate_childReadyState :: IORef (ChildReadyState k)
1229+newtype TraverseDMapChildHydration t m = TraverseDMapChildHydration
1230+ { _traverseDMapChildHydration_delayed :: HydrationRunnerT t m DOM.Text
1231+ -- ^ Action to run at switchover, returns the placeholder
1234+data TraverseDMapChild t m k a = TraverseDMapChild
1235+ { _traverseDMapChild_mode :: Either (TraverseDMapChildHydration t m) (TraverseDMapChildImmediate k)
1236+ , _traverseDMapChild_result :: a
1159{-# INLINABLE hoistTraverseWithKeyWithAdjust #-}
1239{-# INLINABLE hoistTraverseWithKeyWithAdjust #-}
1160hoistTraverseWithKeyWithAdjust :: forall (k :: * -> *) v v' t m p.
1240hoistTraverseWithKeyWithAdjust :: forall (k :: * -> *) v v' t m p.
1161 ( Adjustable t m
1241 ( Adjustable t m
@@ -1166,35 +1246,39 @@ hoistTraverseWithKeyWithAdjust :: forall (k :: * -> *) v v' t m p.
1166 , PrimMonad m
1246 , PrimMonad m
1167 , MonadFix m
1247 , MonadFix m
1168 , Patch (p k v)
1248 , Patch (p k v)
1169− , PatchTarget (p k (Constant Int)) ~ DMap k (Constant Int)
1170− , Patch (p k (Const (HydrationRunnerT t m ())))
1171− , PatchTarget (p k (Const (HydrationRunnerT t m ()))) ~ DMap k (Const (HydrationRunnerT t m ()))
1172− , Monoid (p k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v'))
1173 , Patch (p k (Constant Int))
1249 , Patch (p k (Constant Int))
1250+ , PatchTarget (p k (Constant Int)) ~ DMap k (Constant Int)
1251+ , Patch (p k (Compose (TraverseDMapChild t m k) v'))
1252+ , PatchTarget (p k (Compose (TraverseDMapChild t m k) v')) ~ DMap k (Compose (TraverseDMapChild t m k) v')
1253+ , Monoid (p k (Compose (TraverseDMapChild t m k) v'))
1175 => (forall vv vv'.
1255 => (forall vv vv'.
1176 (forall a. k a -> vv a -> DomRenderHookT t m (vv' a))
1256 (forall a. k a -> vv a -> DomRenderHookT t m (vv' a))
1177 -> DMap k vv
1257 -> DMap k vv
1178 -> Event t (p k vv)
1258 -> Event t (p k vv)
1179 -> DomRenderHookT t m (DMap k vv', Event t (p k vv'))
1259 -> DomRenderHookT t m (DMap k vv', Event t (p k vv'))
1180− ) -- ^ The base monad's traversal
1261+ -- ^ The base monad's traversal
1181− -> (forall vv vv'. (forall a. vv a -> vv' a) -> p k vv -> p k vv') -- ^ A way of mapping over the patch type
1262+ -> (forall vv vv'. (forall a. vv a -> vv' a) -> p k vv -> p k vv')
1263+ -- ^ A way of mapping over the patch type
1264+ -> (p k (Compose (TraverseDMapChild t m k) v') -> DMap k (Constant (IORef (ChildReadyState k))) -> IO (DMap k (Constant (IORef (ChildReadyState k)))))
1182− -> (p k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v') -> DMap k (Constant (IORef (ChildReadyState k))) -> IO (DMap k (Constant (IORef (ChildReadyState k))))) -- ^ Given a patch for the children DOM elements, produce a patch for the childrens' unreadiness state
1265+ -- ^ Given a patch for the children DOM elements, produce a patch for the childrens' unreadiness state
1183− -> (IORef (Map.Map (Some.Some k) DOM.Text) -> IORef DOM.Text -> p k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v') -> JSM ()) -- ^ Apply a patch to the DOM
1266+ -> (IORef (Map.Map (Some.Some k) DOM.Text) -> DOM.Text -> p k (Compose (TraverseDMapChild t m k) v') -> JSM ())
1267+ -- ^ Apply a patch to the DOM
1184 -> (forall a. k a -> v a -> HydrationDomBuilderT t m (v' a))
1268 -> (forall a. k a -> v a -> HydrationDomBuilderT t m (v' a))
1185 -> DMap k v
1269 -> DMap k v
1186 -> Event t (p k v)
1270 -> Event t (p k v)
1187 -> HydrationDomBuilderT t m (DMap k v', Event t (p k v'))
1271 -> HydrationDomBuilderT t m (DMap k v', Event t (p k v'))
1188hoistTraverseWithKeyWithAdjust base mapPatch updateChildUnreadiness applyDomUpdate_ (f :: forall a. k a -> v a -> HydrationDomBuilderT t m (v' a)) (dm0 :: DMap k v) dm' = do
1272hoistTraverseWithKeyWithAdjust base mapPatch updateChildUnreadiness applyDomUpdate_ (f :: forall a. k a -> v a -> HydrationDomBuilderT t m (v' a)) (dm0 :: DMap k v) dm' = do
1189−-- (hydrateStart, _, key) <- skipToReplaceStart -- TODO
1273+ doc <- askDocument
1190 initialEnv <- HydrationDomBuilderT ask
1274 initialEnv <- HydrationDomBuilderT ask
1191 let parentUnreadyChildren = _hydrationDomBuilderEnv_unreadyChildren initialEnv
1275 let parentUnreadyChildren = _hydrationDomBuilderEnv_unreadyChildren initialEnv
1192− pendingChange :: IORef (DMap k (Constant (IORef (ChildReadyState k))), p k (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v')) <- liftIO $ newIORef mempty
1276+ pendingChange :: IORef (DMap k (Constant (IORef (ChildReadyState k))), p k (Compose (TraverseDMapChild t m k) v')) <- liftIO $ newIORef mempty
1193 haveEverBeenReady <- liftIO $ newIORef False
1277 haveEverBeenReady <- liftIO $ newIORef False
1194− placeholders <- liftIO $ newIORef $ error "placeholders not yet initialized"
1278+ placeholders <- liftIO $ newIORef Map.empty
1195− lastPlaceholderRef <- liftIO $ newIORef $ error "lastPlaceholderRef not yet initialized"
1279+ lastPlaceholder <- createTextNode doc ("" :: Text)
1196 let applyDomUpdate p = do
1280 let applyDomUpdate p = do
1197− applyDomUpdate_ placeholders lastPlaceholderRef p
1281+ applyDomUpdate_ placeholders lastPlaceholder p
1198 markSelfReady
1282 markSelfReady
1199 liftIO $ writeIORef pendingChange $! mempty
1283 liftIO $ writeIORef pendingChange $! mempty
1200 markSelfReady = do
1284 markSelfReady = do
@@ -1221,38 +1305,36 @@ hoistTraverseWithKeyWithAdjust base mapPatch updateChildUnreadiness applyDomUpda
1221 liftIO $ writeIORef pendingChange (newUnready, p)
1305 liftIO $ writeIORef pendingChange (newUnready, p)
1222 when (DMap.null newUnready) $ do
1306 when (DMap.null newUnready) $ do
1223 applyDomUpdate p
1307 applyDomUpdate p
1308+ (children0 :: DMap k (Compose (TraverseDMapChild t m k) v'), children' :: Event t (p k (Compose (TraverseDMapChild t m k) v')))
1224− (children0, children') <- HydrationDomBuilderT $ lift $ lift $ base (\k v -> drawChildUpdate initialEnv markChildReady $ f k v) dm0 dm'
1309+ <- HydrationDomBuilderT $ lift $ lift $ base (\k v -> drawChildUpdate initialEnv markChildReady $ f k v) dm0 dm'
1225− let processChild k (Compose (_, _, _, sRef, _)) = ComposeMaybe <$> do
1310+ let processChild k (Compose (TraverseDMapChild e _)) = case e of
1226− readIORef sRef >>= \case
1311+ Left _ -> pure $ ComposeMaybe Nothing
1312+ Right immediate -> ComposeMaybe <$> do
1313+ readIORef (_traverseDMapChildImmediate_childReadyState immediate) >>= \case
1227− ChildReadyState_Ready -> return Nothing
1314+ ChildReadyState_Ready -> return Nothing
1228− ChildReadyState_Unready _ -> do
1315+ ChildReadyState_Unready _ -> do
1229− writeIORef sRef $ ChildReadyState_Unready $ Just $ Some.This k
1316+ writeIORef (_traverseDMapChildImmediate_childReadyState immediate) $ ChildReadyState_Unready $ Just $ Some.This k
1230− return $ Just $ Constant sRef
1317+ return $ Just $ Constant (_traverseDMapChildImmediate_childReadyState immediate)
1231 initialUnready <- liftIO $ DMap.mapMaybeWithKey (\_ -> getComposeMaybe) <$> DMap.traverseWithKey processChild children0
1318 initialUnready <- liftIO $ DMap.mapMaybeWithKey (\_ -> getComposeMaybe) <$> DMap.traverseWithKey processChild children0
1232 liftIO $ if DMap.null initialUnready
1319 liftIO $ if DMap.null initialUnready
1233 then writeIORef haveEverBeenReady True
1320 then writeIORef haveEverBeenReady True
1235 modifyIORef' parentUnreadyChildren succ
1322 modifyIORef' parentUnreadyChildren succ
1236 writeIORef pendingChange (initialUnready, mempty) -- The patch is always empty because it got applied implicitly when we ran the children the first time
1323 writeIORef pendingChange (initialUnready, mempty) -- The patch is always empty because it got applied implicitly when we ran the children the first time
1237− let result0 = DMap.map (\(Compose (_, _, _, _, v)) -> v) children0
1238− placeholders0 = weakenDMapWith (\(Compose (_, _, ph, _, _)) -> ph) children0
1239− delayed0 :: DMap k (Const (HydrationRunnerT t m ()))
1240− delayed0 = DMap.map (\(Compose (delayed, _, _, _, _)) -> Const delayed) children0
1241− delayed' :: Event t (p k (Const (HydrationRunnerT t m ())))
1242− delayed' = ffor children' $ mapPatch $ \(Compose (d, _, _, _, _)) -> Const d
1243− result' = ffor children' $ mapPatch $ \(Compose (_, _, _, _, r)) -> r
1245− let setFinalPlaceholder = do
1246− ph <- createTextNode doc ("" :: Text)
1247− insertAfterPreviousNode ph
1248− liftIO $ writeIORef lastPlaceholderRef ph
1249− addHydrationStepWithSetup (accumMaybeB (flip apply) delayed0 delayed') $ \delayed -> do
1250− _ <- join $ sample (traverse (\(_ :=> Const d) -> d) . DMap.toList <$> delayed)
1251− setFinalPlaceholder
1252− liftIO $ writeIORef placeholders $! placeholders0
1253 getHydrationMode >>= \case
1324 getHydrationMode >>= \case
1254− HydrationMode_Immediate -> void $ DMap.traverseWithKey (\_ (Compose (_, df, _, _, _)) -> Constant () <$ append (toNode df)) children0
1325+ HydrationMode_Hydrating -> addHydrationStepWithSetup (holdIncremental children0 children') $ \children -> do
1255− _ -> pure ()
1326+ dm :: DMap k (Compose (TraverseDMapChild t m k) v') <- sample $ currentIncremental children
1327+ phs <- traverse id $ weakenDMapWith (either _traverseDMapChildHydration_delayed (pure . _traverseDMapChildImmediate_placeholder) . _traverseDMapChild_mode . getCompose) dm
1328+ liftIO $ writeIORef placeholders $! phs
1329+ insertAfterPreviousNode lastPlaceholder
1330+ HydrationMode_Immediate -> do
1331+ let activate i = do
1332+ append $ toNode $ _traverseDMapChildImmediate_fragment i
1333+ pure $ _traverseDMapChildImmediate_placeholder i
1334+ phs <- traverse id $ weakenDMapWith ((either (error "delayed") activate) . _traverseDMapChild_mode . getCompose) children0
1335+ liftIO $ writeIORef placeholders $! phs
1336+ append $ toNode lastPlaceholder
1256 requestDomAction_ $ ffor children' $ \p -> do
1338 requestDomAction_ $ ffor children' $ \p -> do
1257 (oldUnready, oldP) <- liftIO $ readIORef pendingChange
1339 (oldUnready, oldP) <- liftIO $ readIORef pendingChange
1258 newUnready <- liftIO $ updateChildUnreadiness p oldUnready
1340 newUnready <- liftIO $ updateChildUnreadiness p oldUnready
@@ -1260,6 +1342,8 @@ hoistTraverseWithKeyWithAdjust base mapPatch updateChildUnreadiness applyDomUpda
1260 liftIO $ writeIORef pendingChange (newUnready, newP)
1342 liftIO $ writeIORef pendingChange (newUnready, newP)
1261 when (DMap.null newUnready) $ do
1343 when (DMap.null newUnready) $ do
1262 applyDomUpdate newP
1344 applyDomUpdate newP
1345+ let result0 = DMap.map (_traverseDMapChild_result . getCompose) children0
1346+ result' = ffor children' $ mapPatch $ _traverseDMapChild_result . getCompose
1263 return (result0, result')
1347 return (result0, result')
1265{-# INLINABLE drawChildUpdate #-}
1349{-# INLINABLE drawChildUpdate #-}
@@ -1267,35 +1351,47 @@ drawChildUpdate :: (MonadIO m, MonadJSM m, Reflex t)
1267 => HydrationDomBuilderEnv t
1351 => HydrationDomBuilderEnv t
1268 -> (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
1352 -> (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
1269 -> HydrationDomBuilderT t m (v' a)
1353 -> HydrationDomBuilderT t m (v' a)
1270− -> DomRenderHookT t m (Compose ((,,,,) (HydrationRunnerT t m ()) DOM.DocumentFragment DOM.Text (IORef (ChildReadyState k))) v' a)
1354+ -> DomRenderHookT t m (Compose (TraverseDMapChild t m k) v' a)
1271−drawChildUpdate initialEnv markReady child = do
1272− childReadyState <- liftIO $ newIORef $ ChildReadyState_Unready Nothing
1273− let doc = _hydrationDomBuilderEnv_document initialEnv
1274− unreadyChildren <- liftIO $ newIORef 0
1275− hydrationMode <- liftIO $ readIORef $ _hydrationDomBuilderEnv_hydrationMode initialEnv
1355+drawChildUpdate initialEnv markReady child = liftIO (readIORef $ _hydrationDomBuilderEnv_hydrationMode initialEnv) >>= \case
1276− placeholder <- createTextNode doc ("" :: Text)
1277− (p, delayed) <- case hydrationMode of
1278− HydrationMode_Hydrating -> pure
1356+ HydrationMode_Hydrating -> do
1279− ( Left $ _hydrationDomBuilderEnv_parent initialEnv
1357+ let doc = _hydrationDomBuilderEnv_document initialEnv
1280− , insertAfterPreviousNode placeholder
1282− HydrationMode_Immediate -> do
1283− df <- createDocumentFragment doc
1284− Node.appendChild_ df placeholder
1285− pure (Right df, pure ())
1286− p' <- either pure (liftIO . newIORef . toNode) p
1358+ unreadyChildren <- liftIO $ newIORef 0
1287− (result, finalState) <- flip runStateT (pure ()) $ runReaderT (unHydrationDomBuilderT child) initialEnv
1359+ (result, childDelayed) <- flip runStateT (pure ()) $ runReaderT (unHydrationDomBuilderT child) initialEnv
1288− { _hydrationDomBuilderEnv_parent = p'
1289− , _hydrationDomBuilderEnv_unreadyChildren = unreadyChildren
1360+ { _hydrationDomBuilderEnv_unreadyChildren = unreadyChildren
1290− , _hydrationDomBuilderEnv_commitAction = markReady childReadyState
1361+ }
1363+ placeholder <- createTextNode doc ("" :: Text)
1364+ insertAfterPreviousNode placeholder
1366+ return $ Compose $ TraverseDMapChild
1367+ { _traverseDMapChild_result = result
1368+ , _traverseDMapChild_mode = Left TraverseDMapChildHydration
1369+ { _traverseDMapChildHydration_delayed = delayed <* childDelayed
1372+ HydrationMode_Immediate -> do
1373+ childReadyState <- liftIO $ newIORef $ ChildReadyState_Unready Nothing
1374+ let doc = _hydrationDomBuilderEnv_document initialEnv
1375+ unreadyChildren <- liftIO $ newIORef 0
1376+ df <- createDocumentFragment doc
1377+ placeholder <- createTextNode doc ("" :: Text)
1378+ Node.appendChild_ df placeholder
1379+ parentRef <- liftIO . newIORef $ toNode df
1380+ (result, _s) <- flip runStateT (pure ()) $ runReaderT (unHydrationDomBuilderT child) initialEnv
1381+ { _hydrationDomBuilderEnv_parent = parentRef
1382+ , _hydrationDomBuilderEnv_unreadyChildren = unreadyChildren
1383+ , _hydrationDomBuilderEnv_commitAction = markReady childReadyState
1292− u <- liftIO $ readIORef unreadyChildren
1385+ u <- liftIO $ readIORef unreadyChildren
1293− when (u == 0) $ liftIO $ writeIORef childReadyState ChildReadyState_Ready
1386+ when (u == 0) $ liftIO $ writeIORef childReadyState ChildReadyState_Ready
1294− return $ Compose
1387+ return $ Compose $ TraverseDMapChild
1295− ( delayed >> finalState
1388+ { _traverseDMapChild_result = result
1296− , either (const $ error "drawChildUpdate: Tried to use document fragment in hydration mode") id p
1389+ , _traverseDMapChild_mode = Right TraverseDMapChildImmediate
1297− , placeholder, childReadyState, result
1390+ { _traverseDMapChildImmediate_fragment = df
1298− )
1391+ , _traverseDMapChildImmediate_placeholder = placeholder
1392+ , _traverseDMapChildImmediate_childReadyState = childReadyState
1300{-# INLINABLE drawChildUpdateInt #-}
1396{-# INLINABLE drawChildUpdateInt #-}
1301drawChildUpdateInt :: (MonadIO m, MonadJSM m, Reflex t)
1397drawChildUpdateInt :: (MonadIO m, MonadJSM m, Reflex t)