@@ -747,6 +747,7 @@ instance GEq SpiderTimelineEnv where
747747data EventEnv x
748748 = EventEnv { eventEnvAssignments :: !(IORef [SomeAssignment x]) -- Needed for Subscribe
749749 , eventEnvHoldInits :: !(IORef [SomeHoldInit x]) -- Needed for Subscribe
750+ , eventEnvDynInits :: !(IORef [SomeDynInit x])
750751 , eventEnvMergeUpdates :: !(IORef [SomeMergeUpdate x])
751752 , eventEnvMergeInits :: !(IORef [SomeMergeInit x]) -- Needed for Subscribe
752753 , eventEnvClears :: !(IORef [SomeClear]) -- Needed for Subscribe
@@ -780,6 +781,10 @@ instance HasSpiderTimeline x => Defer (SomeHoldInit x) (EventM x) where
780781 {-# INLINE getDeferralQueue #-}
781782 getDeferralQueue = asksEventEnv eventEnvHoldInits
782783
784+instance HasSpiderTimeline x => Defer (SomeDynInit x) (EventM x) where
785+ {-# INLINE getDeferralQueue #-}
786+ getDeferralQueue = asksEventEnv eventEnvDynInits
787+
783788instance Defer (SomeHoldInit x) (BehaviorM x) where
784789 {-# INLINE getDeferralQueue #-}
785790 getDeferralQueue = BehaviorM $ asks snd
@@ -952,6 +957,8 @@ data Root x (k :: * -> *)
952957
953958data SomeHoldInit x = forall p. Patch p => SomeHoldInit !(Hold x p)
954959
960+data SomeDynInit x = forall p. Patch p => SomeDynInit !(Dyn x p)
961+
955962data SomeMergeUpdate x = SomeMergeUpdate
956963 { _someMergeUpdate_update :: !(EventM x [EventSubscription x])
957964 , _someMergeUpdate_invalidateHeight :: !(IO ())
@@ -963,14 +970,20 @@ newtype SomeMergeInit x = SomeMergeInit { unSomeMergeInit :: EventM x () }
963970-- EventM can do everything BehaviorM can, plus create holds
964971newtype EventM x a = EventM { unEventM :: IO a } deriving (Functor, Applicative, Monad, MonadIO, MonadFix, MonadException, MonadAsyncException) -- The environment should be Nothing if we are not in a frame, and Just if we are - in which case it is a list of assignments to be done after the frame is over
965972
966−newtype ComputeM x a = ComputeM (ReaderT (IORef [SomeHoldInit x]) IO a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
973+newtype ComputeM x a = ComputeM (ReaderT (IORef [SomeHoldInit x], IORef [SomeDynInit x]) IO a) deriving (Functor, Applicative, Monad, MonadIO, MonadFix)
967974
968975instance Defer (SomeHoldInit x) (ComputeM x) where
969− getDeferralQueue = ComputeM ask
976+ getDeferralQueue = ComputeM $ asks fst
977+
978+instance Defer (SomeDynInit x) (ComputeM x) where
979+ getDeferralQueue = ComputeM $ asks snd
970980
971981{-# INLINABLE runComputeM #-}
972−runComputeM :: Defer (SomeHoldInit x) m => ComputeM x a -> m a
973−runComputeM (ComputeM a) = liftIO . runReaderT a =<< getDeferralQueue
982+runComputeM :: (Defer (SomeHoldInit x) m, Defer (SomeDynInit x) m) => ComputeM x a -> m a
983+runComputeM (ComputeM a) = do
984+ holds <- getDeferralQueue
985+ dyns <- getDeferralQueue
986+ liftIO $ runReaderT a (holds, dyns)
974987
975988newtype MergeSubscribedParent x a = MergeSubscribedParent { unMergeSubscribedParent :: EventSubscription x }
976989
@@ -1103,7 +1116,7 @@ instance HasSpiderTimeline x => Align (Event x) where
11031116newtype Dyn x p = Dyn { unDyn :: IORef (Either (BehaviorM x (PatchTarget p), Event x p) (Hold x p)) }
11041117
11051118newMapDyn :: HasSpiderTimeline x => (a -> b) -> Dynamic x (Identity a) -> Dynamic x (Identity b)
1106−newMapDyn f d = dynamicDynIdentity $ unsafeDyn (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
1119+newMapDyn f d = dynamicDynIdentity $ unsafeBuildDynamic (fmap f $ readBehaviorTracked $ dynamicCurrent d) (Identity . f . runIdentity <$> dynamicUpdated d)
11071120
11081121--TODO: Avoid the duplication between this and R.zipDynWith
11091122zipDynWith :: HasSpiderTimeline x => (a -> b -> c) -> Dynamic x (Identity a) -> Dynamic x (Identity b) -> Dynamic x (Identity c)
@@ -1119,10 +1132,17 @@ zipDynWith f da db =
11191132 return (a, b)
11201133 These (Identity a) (Identity b) -> return (a, b)
11211134 return $ Just $ Identity $ f a b
1122− in dynamicDynIdentity $ unsafeDyn (f <$> readBehaviorUntracked (dynamicCurrent da) <*> readBehaviorUntracked (dynamicCurrent db)) ec
1135+ in dynamicDynIdentity $ unsafeBuildDynamic (f <$> readBehaviorUntracked (dynamicCurrent da) <*> readBehaviorUntracked (dynamicCurrent db)) ec
1136+
1137+buildDynamic :: (Defer (SomeDynInit x) m, Patch p) => BehaviorM x (PatchTarget p) -> Event x p -> m (Dyn x p)
1138+buildDynamic readV0 v' = do
1139+ result <- liftIO $ newIORef $ Left (readV0, v')
1140+ let !d = Dyn result
1141+ defer $ SomeDynInit d
1142+ return d
11231143
1124−unsafeDyn :: BehaviorM x (PatchTarget p) -> Event x p -> Dyn x p
1125−unsafeDyn readV0 v' = Dyn $ unsafeNewIORef x $ Left x
1144+unsafeBuildDynamic :: BehaviorM x (PatchTarget p) -> Event x p -> Dyn x p
1145+unsafeBuildDynamic readV0 v' = Dyn $ unsafeNewIORef x $ Left x
11261146 where x = (readV0, v')
11271147
11281148-- ResultM can read behaviors and events
@@ -1796,24 +1816,31 @@ fan e =
17961816 }
17971817 in EventSelector $ \k -> eventFan k f
17981818
1799−runHoldInits :: HasSpiderTimeline x => IORef [SomeHoldInit x] -> IORef [SomeMergeInit x] -> EventM x ()
1800−runHoldInits holdInitRef mergeInitRef = do
1819+runHoldInits :: HasSpiderTimeline x => IORef [SomeHoldInit x] -> IORef [SomeDynInit x] -> IORef [SomeMergeInit x] -> EventM x ()
1820+runHoldInits holdInitRef dynInitRef mergeInitRef = do
18011821 holdInits <- liftIO $ readIORef holdInitRef
1822+ dynInits <- liftIO $ readIORef dynInitRef
18021823 mergeInits <- liftIO $ readIORef mergeInitRef
1803− unless (null holdInits && null mergeInits) $ do
1824+ unless (null holdInits && null dynInits && null mergeInits) $ do
18041825 liftIO $ writeIORef holdInitRef []
1826+ liftIO $ writeIORef dynInitRef []
18051827 liftIO $ writeIORef mergeInitRef []
18061828 mapM_ initHold holdInits
1829+ mapM_ initDyn dynInits
18071830 mapM_ unSomeMergeInit mergeInits
1808− runHoldInits holdInitRef mergeInitRef
1831+ runHoldInits holdInitRef dynInitRef mergeInitRef
18091832
18101833initHold :: HasSpiderTimeline x => SomeHoldInit x -> EventM x ()
18111834initHold (SomeHoldInit h) = void $ getHoldEventSubscription h
18121835
1836+initDyn :: HasSpiderTimeline x => SomeDynInit x -> EventM x ()
1837+initDyn (SomeDynInit d) = void $ getDynHold d
1838+
18131839newEventEnv :: IO (EventEnv x)
18141840newEventEnv = do
18151841 toAssignRef <- newIORef [] -- This should only actually get used when events are firing
18161842 holdInitRef <- newIORef []
1843+ dynInitRef <- newIORef []
18171844 mergeUpdateRef <- newIORef []
18181845 mergeInitRef <- newIORef []
18191846 heightRef <- newIORef zeroHeight
@@ -1821,12 +1848,13 @@ newEventEnv = do
18211848 toClearRootRef <- newIORef []
18221849 coincidenceInfosRef <- newIORef []
18231850 delayedRef <- newIORef IntMap.empty
1824− return $ EventEnv toAssignRef holdInitRef mergeUpdateRef mergeInitRef toClearRef toClearRootRef heightRef coincidenceInfosRef delayedRef
1851+ return $ EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeInitRef toClearRef toClearRootRef heightRef coincidenceInfosRef delayedRef
18251852
18261853clearEventEnv :: EventEnv x -> IO ()
1827−clearEventEnv (EventEnv toAssignRef holdInitRef mergeUpdateRef mergeInitRef toClearRef toClearRootRef heightRef coincidenceInfosRef delayedRef) = do
1854+clearEventEnv (EventEnv toAssignRef holdInitRef dynInitRef mergeUpdateRef mergeInitRef toClearRef toClearRootRef heightRef coincidenceInfosRef delayedRef) = do
18281855 writeIORef toAssignRef []
18291856 writeIORef holdInitRef []
1857+ writeIORef dynInitRef []
18301858 writeIORef mergeUpdateRef []
18311859 writeIORef mergeInitRef []
18321860 writeIORef heightRef zeroHeight
@@ -1841,7 +1869,7 @@ runFrame a = SpiderHost $ ask >>= \_ -> lift $ do
18411869 let env = _spiderTimeline_eventEnv (spiderTimeline :: SpiderTimelineEnv x)
18421870 let go = do
18431871 result <- a
1844− runHoldInits (eventEnvHoldInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events
1872+ runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) -- This must happen before doing the assignments, in case subscribing a Hold causes existing Holds to be read by the newly-propagated events
18451873 return result
18461874 result <- runEventM go
18471875 toClear <- readIORef $ eventEnvClears env
@@ -1873,7 +1901,7 @@ runFrame a = SpiderHost $ ask >>= \_ -> lift $ do
18731901 writeIORef (switchSubscribedBehaviorParents subscribed) []
18741902 writeIORef (eventEnvHoldInits env) [] --TODO: Should we reuse this?
18751903 e <- runBehaviorM (readBehaviorTracked (switchSubscribedParent subscribed)) (Just (wi', switchSubscribedBehaviorParents subscribed)) $ eventEnvHoldInits env
1876− runEventM $ runHoldInits (eventEnvHoldInits env) (eventEnvMergeInits env) --TODO: Is this actually OK? It seems like it should be, since we know that no events are firing at this point, but it still seems inelegant
1904+ runEventM $ runHoldInits (eventEnvHoldInits env) (eventEnvDynInits env) (eventEnvMergeInits env) --TODO: Is this actually OK? It seems like it should be, since we know that no events are firing at this point, but it still seems inelegant
18771905 --TODO: Make sure we touch the pieces of the SwitchSubscribed at the appropriate times
18781906 sub <- newSubscriberSwitch subscribed
18791907 subscription <- runReaderT (unSpiderHost (runFrame ({-# SCC "subscribeSwitch" #-} subscribe e sub))) spiderTimeline --TODO: Assert that the event isn't firing --TODO: This should not loop because none of the events should be firing, but still, it is inefficient
@@ -2074,9 +2102,9 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
20742102 {-# INLINABLE updated #-}
20752103 updated = coerce $ SpiderEvent . dynamicUpdated . unSpiderDynamic
20762104 {-# INLINABLE unsafeBuildDynamic #-}
2077− unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeDyn (coerce readV0) $ coerce $ unSpiderEvent v'
2105+ unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
20782106 {-# INLINABLE unsafeBuildIncremental #-}
2079− unsafeBuildIncremental readV0 dv = SpiderIncremental $ dynamicDyn $ unsafeDyn (coerce readV0) $ unSpiderEvent dv
2107+ unsafeBuildIncremental readV0 dv = SpiderIncremental $ dynamicDyn $ unsafeBuildDynamic (coerce readV0) $ unSpiderEvent dv
20802108 {-# INLINABLE mergeIncremental #-}
20812109 mergeIncremental = SpiderEvent . merge . (unsafeCoerce :: Dynamic x (PatchDMap k (R.Event (SpiderTimeline x))) -> Dynamic x (PatchDMap k (Event x))) . unSpiderIncremental
20822110 {-# INLINABLE mergeIncrementalWithMove #-}
@@ -2086,7 +2114,7 @@ instance HasSpiderTimeline x => R.Reflex (SpiderTimeline x) where
20862114 {-# INLINABLE updatedIncremental #-}
20872115 updatedIncremental = SpiderEvent . dynamicUpdated . unSpiderIncremental
20882116 {-# INLINABLE incrementalToDynamic #-}
2089− incrementalToDynamic (SpiderIncremental i) = SpiderDynamic $ dynamicDynIdentity $ unsafeDyn (readBehaviorUntracked $ dynamicCurrent i) $ flip push (dynamicUpdated i) $ \p -> do
2117+ incrementalToDynamic (SpiderIncremental i) = SpiderDynamic $ dynamicDynIdentity $ unsafeBuildDynamic (readBehaviorUntracked $ dynamicCurrent i) $ flip push (dynamicUpdated i) $ \p -> do
20902118 c <- readBehaviorUntracked $ dynamicCurrent i
20912119 return $ Identity <$> apply p c --TODO: Avoid the redundant 'apply'
20922120 eventCoercion Coercion = Coercion