@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE ConstraintKinds #-}
23{-# LANGUAGE DataKinds #-}
34{-# LANGUAGE EmptyDataDecls #-}
@@ -11,7 +12,9 @@
1112{-# LANGUAGE RankNTypes #-}
1213{-# LANGUAGE RecursiveDo #-}
1314{-# LANGUAGE ScopedTypeVariables #-}
15+#ifdef USE_TEMPLATE_HASKELL
1416{-# LANGUAGE TemplateHaskell #-}
17+#endif
1518{-# LANGUAGE TypeFamilies #-}
1619{-# LANGUAGE TypeOperators #-}
1720{-# LANGUAGE UndecidableInstances #-}
@@ -34,6 +37,9 @@ import Control.Monad.Primitive
3437import Control.Monad.Reader
3538import Control.Monad.Ref
3639import Control.Monad.Trans.Control
40+#ifndef USE_TEMPLATE_HASKELL
41+import Data.Functor.Contravariant (phantom)
42+#endif
3743import Data.Bitraversable
3844import Data.Default
3945import Data.Dependent.Map (DMap)
@@ -48,7 +54,7 @@ import Data.Monoid
4854import Data.Some (Some)
4955import qualified Data.Some as Some
5056import Data.Text (Text)
51−import GHCJS.DOM.Document (Document, createDocumentFragment, createElement, createElementNS, createTextNode)
57+import GHCJS.DOM.Document (Document, createDocumentFragmentUnchecked, createElementUnchecked, createElementNSUnchecked, createTextNodeUnchecked)
5258import GHCJS.DOM.Element (getScrollTop, removeAttribute, removeAttributeNS, setAttribute, setAttributeNS)
5359import qualified GHCJS.DOM.Element as Element
5460import qualified GHCJS.DOM.Event as Event
@@ -59,15 +65,17 @@ import qualified GHCJS.DOM.HTMLInputElement as Input
5965import qualified GHCJS.DOM.HTMLSelectElement as Select
6066import qualified GHCJS.DOM.HTMLTextAreaElement as TextArea
6167import GHCJS.DOM.MouseEvent
62−import GHCJS.DOM.Node (appendChild, getOwnerDocument, getParentNode, getPreviousSibling, removeChild,
68+import GHCJS.DOM.Node (appendChild_, getOwnerDocumentUnchecked, getParentNodeUnchecked,
6369 setNodeValue, toNode)
64−import qualified GHCJS.DOM.Node as DOM
65−import GHCJS.DOM.Types (FocusEvent, IsElement, IsEvent, IsNode, KeyboardEvent, Node, ToDOMString, TouchEvent,
66− WheelEvent, castToHTMLInputElement, castToHTMLSelectElement,
67− castToHTMLTextAreaElement)
70+import qualified GHCJS.DOM.Node as DOM (insertBefore_)
71+import GHCJS.DOM.Types
72+ (liftJSM, askJSM, runJSM, JSM, MonadJSM(..),
73+ FocusEvent, IsElement, IsEvent, IsNode, KeyboardEvent, Node,
74+ ToDOMString, TouchEvent, WheelEvent, uncheckedCastTo)
6875import qualified GHCJS.DOM.Types as DOM
6976import GHCJS.DOM.UIEvent
7077import qualified GHCJS.DOM.Window as Window
78+import Language.Javascript.JSaddle (call, eval)
7179
7280import Debug.Trace hiding (traceEvent)
7381
@@ -81,6 +89,11 @@ data ImmediateDomBuilderEnv t
8189
8290newtype ImmediateDomBuilderT t m a = ImmediateDomBuilderT { unImmediateDomBuilderT :: ReaderT (ImmediateDomBuilderEnv t) m a } deriving (Functor, Applicative, Monad, MonadFix, MonadIO, MonadException, MonadAsyncException)
8391
92+#ifndef __GHCJS__
93+instance MonadJSM m => MonadJSM (ImmediateDomBuilderT t m) where
94+ liftJSM' = ImmediateDomBuilderT . liftJSM'
95+#endif
96+
8497instance PrimMonad m => PrimMonad (ImmediateDomBuilderT x m) where
8598 type PrimState (ImmediateDomBuilderT x m) = PrimState m
8699 primitive = lift . primitive
@@ -110,64 +123,81 @@ askEvents :: Monad m => ImmediateDomBuilderT t m (Chan [DSum (TriggerRef t) Trig
110123askEvents = ImmediateDomBuilderT $ asks _immediateDomBuilderEnv_events
111124
112125{-# INLINABLE append #-}
113−append :: (IsNode n, MonadIO m) => n -> ImmediateDomBuilderT t m ()
126+append :: (IsNode n, MonadJSM m) => n -> ImmediateDomBuilderT t m ()
114127append n = do
115128 p <- askParent
116− _ <- liftIO $ appendChild p $ Just n
129+ liftJSM $ appendChild_ p $ Just n
117130 return ()
118131
119132{-# INLINABLE textNodeInternal #-}
120−textNodeInternal :: (MonadIO m, ToDOMString contents) => contents -> ImmediateDomBuilderT t m DOM.Text
133+textNodeInternal :: (MonadJSM m, ToDOMString contents) => contents -> ImmediateDomBuilderT t m DOM.Text
121134textNodeInternal t = do
122135 doc <- askDocument
123− Just n <- liftIO $ createTextNode doc t
136+ n <- liftJSM $ createTextNodeUnchecked doc t
124137 append n
125138 return n
126139
127−-- | s and e must both be children of the same node and s must precede e
140+-- | s and e must both be children of the same node and s must precede e;
141+-- s, e and all nodes between s and e will be removed
128142{-# INLINABLE deleteBetweenInclusive #-}
129−deleteBetweenInclusive :: (MonadIO m, IsNode start, IsNode end) => start -> end -> m ()
130−deleteBetweenInclusive s e = do
131− mCurrentParent <- getParentNode e -- May be different than it was at initial construction, e.g., because the parent may have dumped us in from a DocumentFragment
132− case mCurrentParent of
133− Nothing -> return () --TODO: Is this the right behavior?
134− Just currentParent -> do
135− deleteUpToGivenParent currentParent s e
136− _ <- removeChild currentParent $ Just e
137− return ()
138−
139−-- | s and e must both be children of the same node and s must precede e
140−deleteBetweenExclusive :: (MonadIO m, IsNode start, IsNode end) => start -> end -> m ()
141−deleteBetweenExclusive s e = do
142− mCurrentParent <- getParentNode e -- May be different than it was at initial construction, e.g., because the parent may have dumped us in from a DocumentFragment
143− case mCurrentParent of
144− Nothing -> return () --TODO: Is this the right behavior?
145− Just currentParent -> do
146− let go = do
147− Just x <- getPreviousSibling e -- This can't be Nothing because we should hit 's' first
148− when (toNode s /= toNode x) $ do
149− _ <- removeChild currentParent $ Just x
150− go
151− go
152−
153−-- | s and e must both be children of the same node and s must precede e; s and all nodes between s and e will be removed, but e will not be removed
143+deleteBetweenInclusive :: (MonadJSM m, IsNode start, IsNode end) => start -> end -> m ()
144+deleteBetweenInclusive s e = liftJSM $ do
145+ f <- eval ("(function(s,e){ \
146+ p = e.parentNode; \
147+ if(p !== null) { \
148+ for(;;){ \
149+ x = e.previousSibling; \
150+ p.removeChild(x); \
151+ if(s===x) break; \
152+ } \
153+ p.removeChild(e); \
154+ }})" :: Text)
155+ void $ call f f (s, e)
156+
157+-- | s and e must both be children of the same node and s must precede e;
158+-- all nodes between s and e will be removed, but s and e will not be removed
159+deleteBetweenExclusive :: (MonadJSM m, IsNode start, IsNode end) => start -> end -> m ()
160+deleteBetweenExclusive s e = liftJSM $ do
161+ f <- eval ("(function(s,e){ \
162+ p = e.parentNode; \
163+ if(p !== null) { \
164+ for(;;){ \
165+ x = e.previousSibling; \
166+ if(s===x) break; \
167+ p.removeChild(x); \
168+ } \
169+ }})" :: Text)
170+ void $ call f f (s, e)
171+
172+-- | s and e must both be children of the same node and s must precede e;
173+-- s and all nodes between s and e will be removed, but e will not be removed
154174{-# INLINABLE deleteUpTo #-}
155−deleteUpTo :: (MonadIO m, IsNode start, IsNode end) => start -> end -> m ()
156−deleteUpTo s e = do
157− mCurrentParent <- getParentNode e -- May be different than it was at initial construction, e.g., because the parent may have dumped us in from a DocumentFragment
158− case mCurrentParent of
159− Nothing -> return () --TODO: Is this the right behavior?
160− Just currentParent -> deleteUpToGivenParent currentParent s e
161−
175+deleteUpTo :: (MonadJSM m, IsNode start, IsNode end) => start -> end -> m ()
176+deleteUpTo s e = liftJSM $ do
177+ f <- eval ("(function(s,e){ \
178+ p = e.parentNode; \
179+ if(p !== null) { \
180+ for(;;) { \
181+ x = e.previousSibling; \
182+ p.removeChild(x); \
183+ if(s===x) break; \
184+ } \
185+ }})" :: Text)
186+ void $ call f f (s, e)
187+
188+-- | s and all nodes between s and e will be removed, but e will not be removed
162189{-# INLINABLE deleteUpToGivenParent #-}
163−deleteUpToGivenParent :: (MonadIO m, IsNode parent, IsNode start, IsNode end) => parent -> start -> end -> m ()
164−deleteUpToGivenParent currentParent s e = do
165− fix $ \loop -> do
166− Just x <- getPreviousSibling e -- This can't be Nothing because we should hit 's' first
167− _ <- removeChild currentParent $ Just x
168− when (toNode s /= toNode x) loop
169−
170−type SupportsImmediateDomBuilder t m = (Reflex t, MonadIO m, MonadIO (Performable m), MonadHold t m, MonadFix m, PerformEvent t m, MonadReflexCreateTrigger t m, MonadRef m, Ref m ~ Ref IO, MonadAdjust t m)
190+deleteUpToGivenParent :: (MonadJSM m, IsNode parent, IsNode start, IsNode end) => parent -> start -> end -> m ()
191+deleteUpToGivenParent currentParent s e = liftJSM $ do
192+ f <- eval ("(function(p,s,e){ \
193+ for(;;){ \
194+ x = e.previousSibling; \
195+ p.removeChild(x); \
196+ if(s===x) break; \
197+ }})" :: Text)
198+ void $ call f f (currentParent, s, e)
199+
200+type SupportsImmediateDomBuilder t m = (Reflex t, MonadJSM m, MonadJSM (Performable m), MonadHold t m, MonadFix m, PerformEvent t m, MonadReflexCreateTrigger t m, MonadRef m, Ref m ~ Ref JSM, MonadAdjust t m)
171201
172202newtype EventFilterTriggerRef t er (en :: EventTag) = EventFilterTriggerRef (IORef (Maybe (EventTrigger t (er en))))
173203
@@ -177,35 +207,37 @@ wrap e cfg = do
177207 lift $ performEvent_ $ ffor (cfg ^. modifyAttributes) $ imapM_ $ \(AttributeName mAttrNamespace n) mv -> case mAttrNamespace of
178208 Nothing -> maybe (removeAttribute e n) (setAttribute e n) mv
179209 Just ns -> maybe (removeAttributeNS e (Just ns) n) (setAttributeNS e (Just ns) n) mv
180− eventTriggerRefs :: DMap EventName (EventFilterTriggerRef t er) <- liftIO $ fmap DMap.fromList $ forM (DMap.toList $ _ghcjsEventSpec_filters $ _rawElementConfig_eventSpec cfg) $ \(en :=> GhcjsEventFilter f) -> do
181− triggerRef <- newIORef Nothing
210+ eventTriggerRefs :: DMap EventName (EventFilterTriggerRef t er) <- liftJSM $ fmap DMap.fromList $ forM (DMap.toList $ _ghcjsEventSpec_filters $ _rawElementConfig_eventSpec cfg) $ \(en :=> GhcjsEventFilter f) -> do
211+ triggerRef <- liftIO $ newIORef Nothing
182212 _ <- elementOnEventName en e $ do
183213 evt <- DOM.event
184− (flags, k) <- liftIO $ f $ GhcjsDomEvent evt
214+ (flags, k) <- liftJSM $ f $ GhcjsDomEvent evt
185215 when (_eventFlags_preventDefault flags) $ withIsEvent en DOM.preventDefault
186216 case _eventFlags_propagation flags of
187217 Propagation_Continue -> return ()
188218 Propagation_Stop -> withIsEvent en DOM.stopPropagation
189219 Propagation_StopImmediate -> withIsEvent en DOM.stopImmediatePropagation
190− mv <- liftIO k --TODO: Only do this when the event is subscribed
220+ mv <- liftJSM k --TODO: Only do this when the event is subscribed
191221 liftIO $ forM_ mv $ \v -> writeChan events [TriggerRef triggerRef :=> TriggerInvocation v (return ())]
192222 return $ en :=> EventFilterTriggerRef triggerRef
193− es <- newFanEventWithTrigger $ \(WrapArg en) t -> do
194− case DMap.lookup en eventTriggerRefs of
195− Just (EventFilterTriggerRef r) -> do
196− writeIORef r $ Just t
197− return $ do
198− writeIORef r Nothing
199− Nothing -> elementOnEventName en e $ do
200− evt <- DOM.event
201− let h = _ghcjsEventSpec_handler $ _rawElementConfig_eventSpec cfg
202− mv <- liftIO $ h (en, GhcjsDomEvent evt)
203− case mv of
204− Nothing -> return ()
205− Just v -> liftIO $ do
206− --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
207− ref <- newIORef $ Just t
208− writeChan events [TriggerRef ref :=> TriggerInvocation v (return ())]
223+ es <- do
224+ ctx <- askJSM
225+ newFanEventWithTrigger $ \(WrapArg en) t ->
226+ case DMap.lookup en eventTriggerRefs of
227+ Just (EventFilterTriggerRef r) -> do
228+ writeIORef r $ Just t
229+ return $ do
230+ writeIORef r Nothing
231+ Nothing -> (`runJSM` ctx) <$> (`runJSM` ctx) (elementOnEventName en e $ do
232+ evt <- DOM.event
233+ let h = _ghcjsEventSpec_handler $ _rawElementConfig_eventSpec cfg
234+ mv <- lift $ h (en, GhcjsDomEvent evt)
235+ case mv of
236+ Nothing -> return ()
237+ Just v -> liftIO $ do
238+ --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
239+ ref <- newIORef $ Just t
240+ writeChan events [TriggerRef ref :=> TriggerInvocation v (return ())])
209241 return $ Element es e
210242
211243{-# INLINABLE makeElement #-}
@@ -213,12 +245,12 @@ makeElement :: forall er t m a. SupportsImmediateDomBuilder t m => Text -> Eleme
213245makeElement elementTag cfg child = do
214246 doc <- askDocument
215247 events <- askEvents
216− Just e <- ImmediateDomBuilderT $ fmap DOM.castToElement <$> case cfg ^. namespace of
217− Nothing -> createElement doc (Just elementTag)
218− Just ens -> createElementNS doc (Just ens) (Just elementTag)
248+ e <- liftJSM $ case cfg ^. namespace of
249+ Nothing -> createElementUnchecked doc (Just elementTag)
250+ Just ens -> createElementNSUnchecked doc (Just ens) (Just elementTag)
219251 ImmediateDomBuilderT $ iforM_ (cfg ^. initialAttributes) $ \(AttributeName mAttrNamespace n) v -> case mAttrNamespace of
220− Nothing -> setAttribute e n v
221− Just ans -> setAttributeNS e (Just ans) n v
252+ Nothing -> lift $ setAttribute e n v
253+ Just ans -> lift $ setAttributeNS e (Just ans) n v
222254 result <- lift $ runImmediateDomBuilderT child $ ImmediateDomBuilderEnv
223255 { _immediateDomBuilderEnv_parent = toNode e
224256 , _immediateDomBuilderEnv_document = doc
@@ -228,9 +260,9 @@ makeElement elementTag cfg child = do
228260 wrapped <- wrap e $ extractRawElementConfig cfg
229261 return ((wrapped, result), e)
230262
231−newtype GhcjsDomHandler a b = GhcjsDomHandler { unGhcjsDomHandler :: a -> IO b }
263+newtype GhcjsDomHandler a b = GhcjsDomHandler { unGhcjsDomHandler :: a -> JSM b }
232264
233−newtype GhcjsDomHandler1 a b = GhcjsDomHandler1 { unGhcjsDomHandler1 :: forall (x :: EventTag). a x -> IO (b x) }
265+newtype GhcjsDomHandler1 a b = GhcjsDomHandler1 { unGhcjsDomHandler1 :: forall (x :: EventTag). a x -> JSM (b x) }
234266
235267newtype GhcjsDomEvent en = GhcjsDomEvent { unGhcjsDomEvent :: EventType en }
236268
@@ -258,7 +290,7 @@ instance DomSpace GhcjsDomSpace where
258290 in DMap.alter f' en $ _ghcjsEventSpec_filters es
259291 }
260292
261−newtype GhcjsEventFilter er en = GhcjsEventFilter (GhcjsDomEvent en -> IO (EventFlags, IO (Maybe (er en))))
293+newtype GhcjsEventFilter er en = GhcjsEventFilter (GhcjsDomEvent en -> JSM (EventFlags, JSM (Maybe (er en))))
262294
263295data Pair1 (f :: k -> *) (g :: k -> *) (a :: k) = Pair1 (f a) (g a)
264296
@@ -266,15 +298,29 @@ data Maybe1 f a = Nothing1 | Just1 (f a)
266298
267299data GhcjsEventSpec er = GhcjsEventSpec
268300 { _ghcjsEventSpec_filters :: DMap EventName (GhcjsEventFilter er)
269− , _ghcjsEventSpec_handler :: forall en. (EventName en, GhcjsDomEvent en) -> IO (Maybe (er en))
301+ , _ghcjsEventSpec_handler :: forall en. (EventName en, GhcjsDomEvent en) -> JSM (Maybe (er en))
270302 }
271303
304+#ifndef USE_TEMPLATE_HASKELL
305+phantom2 :: (Functor f, Contravariant f) => f a -> f b
306+phantom2 = phantom
307+{-# INLINE phantom2 #-}
308+
309+ghcjsEventSpec_filters :: forall er . Lens' (GhcjsEventSpec er) (DMap EventName (GhcjsEventFilter er))
310+ghcjsEventSpec_filters f (GhcjsEventSpec a b) = (\a' -> GhcjsEventSpec a' b) <$> f a
311+{-# INLINE ghcjsEventSpec_filters #-}
312+ghcjsEventSpec_handler :: forall er en . Getter (GhcjsEventSpec er) ((EventName en, GhcjsDomEvent en) -> JSM (Maybe (er en)))
313+ghcjsEventSpec_handler f (GhcjsEventSpec _ b) = phantom2 (f b)
314+{-# INLINE ghcjsEventSpec_handler #-}
315+#endif
316+
272317instance er ~ EventResult => Default (GhcjsEventSpec er) where
273318 def = GhcjsEventSpec
274319 { _ghcjsEventSpec_filters = mempty
275320 , _ghcjsEventSpec_handler = \(en, GhcjsDomEvent evt) -> do
276− Just t <- withIsEvent en $ Event.getTarget evt --TODO: Rework this; defaultDomEventHandler shouldn't need to take this as an argument
277− runReaderT (defaultDomEventHandler (Element.castToElement t) en) evt
321+ t :: DOM.EventTarget <- withIsEvent en $ Event.getTargetUnchecked evt --TODO: Rework this; defaultDomEventHandler shouldn't need to take this as an argument
322+ let e = uncheckedCastTo DOM.Element t
323+ runReaderT (defaultDomEventHandler e en) evt
278324 }
279325
280326instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t m) where
@@ -300,9 +346,9 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
300346 {-# INLINABLE inputElement #-}
301347 inputElement cfg = do
302348 ((e, _), domElement) <- makeElement "input" (cfg ^. inputElementConfig_elementConfig) $ return ()
303− let domInputElement = castToHTMLInputElement domElement
349+ let domInputElement = uncheckedCastTo DOM.HTMLInputElement domElement
304350 Input.setValue domInputElement $ Just (cfg ^. inputElementConfig_initialValue)
305− Just v0 <- Input.getValue domInputElement
351+ v0 <- Input.getValueUnchecked domInputElement
306352 let getMyValue = fromMaybe "" <$> Input.getValue domInputElement
307353 valueChangedByUI <- performEvent $ getMyValue <$ Reflex.select (_element_events e) (WrapArg Input)
308354 valueChangedBySetValue <- performEvent $ ffor (cfg ^. inputElementConfig_setValue) $ \v' -> do
@@ -317,10 +363,10 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
317363 Input.getChecked domInputElement
318364 checkedChangedBySetChecked <- performEvent $ ffor (_inputElementConfig_setChecked cfg) $ \newChecked -> do
319365 oldChecked <- Input.getChecked domInputElement
320− if newChecked /= oldChecked
321− then do Input.setChecked domInputElement newChecked
322− return $ Just newChecked
323− else return Nothing
366+ Input.setChecked domInputElement newChecked
367+ return $ if newChecked /= oldChecked
368+ then Just newChecked
369+ else Nothing
324370 c <- holdDyn (_inputElementConfig_initialChecked cfg) $ leftmost
325371 [ fmapMaybe id checkedChangedBySetChecked
326372 , checkedChangedByUI
@@ -347,9 +393,9 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
347393 {-# INLINABLE textAreaElement #-}
348394 textAreaElement cfg = do --TODO
349395 ((e, _), domElement) <- makeElement "textarea" (cfg ^. textAreaElementConfig_elementConfig) $ return ()
350− let domTextAreaElement = castToHTMLTextAreaElement domElement
396+ let domTextAreaElement = uncheckedCastTo DOM.HTMLTextAreaElement domElement
351397 TextArea.setValue domTextAreaElement $ Just (cfg ^. textAreaElementConfig_initialValue)
352− Just v0 <- TextArea.getValue domTextAreaElement
398+ v0 <- TextArea.getValueUnchecked domTextAreaElement
353399 let getMyValue = fromMaybe "" <$> TextArea.getValue domTextAreaElement
354400 valueChangedByUI <- performEvent $ getMyValue <$ Reflex.select (_element_events e) (WrapArg Input)
355401 valueChangedBySetValue <- performEvent $ ffor (cfg ^. textAreaElementConfig_setValue) $ \v' -> do
@@ -370,7 +416,7 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
370416 {-# INLINABLE selectElement #-}
371417 selectElement cfg child = do
372418 ((e, result), domElement) <- makeElement "select" (cfg ^. selectElementConfig_elementConfig) child
373− let domSelectElement = castToHTMLSelectElement domElement
419+ let domSelectElement = uncheckedCastTo DOM.HTMLSelectElement domElement
374420 Select.setValue domSelectElement $ Just (cfg ^. selectElementConfig_initialValue)
375421 Just v0 <- Select.getValue domSelectElement
376422 let getMyValue = fromMaybe "" <$> Select.getValue domSelectElement
@@ -394,18 +440,18 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
394440 placeRawElement = append
395441 wrapRawElement = wrap
396442
397−instance (Reflex t, MonadAdjust t m, MonadIO m, MonadHold t m, PerformEvent t m, MonadIO (Performable m)) => MonadAdjust t (ImmediateDomBuilderT t m) where
443+instance (Reflex t, MonadAdjust t m, MonadJSM m, MonadHold t m, PerformEvent t m, MonadJSM (Performable m)) => MonadAdjust t (ImmediateDomBuilderT t m) where
398444 runWithReplace a0 a' = do
399445 initialEnv <- ImmediateDomBuilderT ask
400446 before <- textNodeInternal ("" :: Text)
401447 -- We draw 'after' in this roundabout way to avoid using MonadFix
402− Just after <- createTextNode (_immediateDomBuilderEnv_document initialEnv) ("" :: Text)
448+ after <- createTextNodeUnchecked (_immediateDomBuilderEnv_document initialEnv) ("" :: Text)
403449 let drawInitialChild = do
404450 result <- a0
405451 append after
406452 return result
407453 (result0, result') <- lift $ runWithReplace (runImmediateDomBuilderT drawInitialChild initialEnv) $ ffor a' $ \child -> do
408− Just df <- createDocumentFragment $ _immediateDomBuilderEnv_document initialEnv
454+ df <- createDocumentFragmentUnchecked $ _immediateDomBuilderEnv_document initialEnv
409455 result <- runImmediateDomBuilderT child $ initialEnv
410456 { _immediateDomBuilderEnv_parent = toNode df
411457 }
@@ -419,7 +465,7 @@ instance (Reflex t, MonadAdjust t m, MonadIO m, MonadHold t m, PerformEvent t m,
419465 drawChildInitial child = runImmediateDomBuilderT ((,,) <$> pure (error "sequenceDMapWithAdjust{ImmediateDomBuilderT}: drawChildInitial: DocumentFragment evaluated") <*> textNodeInternal ("" :: Text) <*> child) initialEnv --TODO: Don't return a DocumentFragment at all here; this will require that sequenceDMapWithAdjust accept differently-typed values for the constant and Event arguments.
420466 drawChildUpdate :: ImmediateDomBuilderT t m a -> m (DOM.DocumentFragment, DOM.Text, a)
421467 drawChildUpdate child = do
422− Just df <- createDocumentFragment $ _immediateDomBuilderEnv_document initialEnv
468+ df <- createDocumentFragmentUnchecked $ _immediateDomBuilderEnv_document initialEnv
423469 runImmediateDomBuilderT ((,,) <$> pure df <*> textNodeInternal ("" :: Text) <*> child) $ initialEnv
424470 { _immediateDomBuilderEnv_parent = toNode df
425471 }
@@ -454,12 +500,12 @@ mkHasFocus e = do
454500 ]
455501
456502{-# INLINABLE insertImmediateAbove #-}
457−insertImmediateAbove :: (IsNode placeholder, PerformEvent t m, MonadIO (Performable m)) => placeholder -> Event t (ImmediateDomBuilderT t (Performable m) a) -> ImmediateDomBuilderT t m (Event t a)
503+insertImmediateAbove :: (IsNode placeholder, PerformEvent t m, MonadJSM (Performable m)) => placeholder -> Event t (ImmediateDomBuilderT t (Performable m) a) -> ImmediateDomBuilderT t m (Event t a)
458504insertImmediateAbove n toInsertAbove = do
459505 events <- askEvents
460506 lift $ performEvent $ ffor toInsertAbove $ \new -> do
461− Just doc <- getOwnerDocument n
462− Just df <- createDocumentFragment doc
507+ doc <- getOwnerDocumentUnchecked n
508+ df <- createDocumentFragmentUnchecked doc
463509 result <- runImmediateDomBuilderT new $ ImmediateDomBuilderEnv
464510 { _immediateDomBuilderEnv_parent = toNode df
465511 , _immediateDomBuilderEnv_document = doc
@@ -468,12 +514,10 @@ insertImmediateAbove n toInsertAbove = do
468514 df `insertBefore` n
469515 return result
470516
471−insertBefore :: (MonadIO m, IsNode new, IsNode existing) => new -> existing -> m ()
517+insertBefore :: (MonadJSM m, IsNode new, IsNode existing) => new -> existing -> m ()
472518insertBefore new existing = do
473− mp <- getParentNode existing
474− case mp of
475− Nothing -> trace "ImmediateDomBuilderT: placeholder: Warning: (getParentNode n) returned Nothing" $ return ()
476− Just p -> void $ DOM.insertBefore p (Just new) (Just existing) -- If there's no parent, that means we've been removed from the DOM; this should not happen if the we're removing ourselves from the performEvent properly
519+ p <- getParentNodeUnchecked existing
520+ DOM.insertBefore_ p (Just new) (Just existing) -- If there's no parent, that means we've been removed from the DOM; this should not happen if the we're removing ourselves from the performEvent properly
477521
478522instance PerformEvent t m => PerformEvent t (ImmediateDomBuilderT t m) where
479523 type Performable (ImmediateDomBuilderT t m) = Performable m
@@ -501,17 +545,17 @@ instance (Monad m, MonadRef m, Ref m ~ Ref IO, MonadReflexCreateTrigger t m) =>
501545 newTriggerEventWithOnComplete = do
502546 events <- askEvents
503547 (eResult, reResultTrigger) <- lift newEventWithTriggerRef
504− return $ (,) eResult $ \a cb -> writeChan events [TriggerRef reResultTrigger :=> TriggerInvocation a cb]
548+ return $ (,) eResult $ \a cb -> writeChan events [TriggerRef reResultTrigger :=> TriggerInvocation a (liftIO cb)]
505549 {-# INLINABLE newEventWithLazyTriggerWithOnComplete #-}
506550 newEventWithLazyTriggerWithOnComplete f = do
507551 events <- askEvents
508552 lift $ newEventWithTrigger $ \t -> f $ \a cb -> do
509553 reResultTrigger <- newIORef $ Just t
510− writeChan events [TriggerRef reResultTrigger :=> TriggerInvocation a cb]
554+ writeChan events [TriggerRef reResultTrigger :=> TriggerInvocation a (liftIO cb)]
511555
512−instance HasWebView m => HasWebView (ImmediateDomBuilderT t m) where
513− type WebViewPhantom (ImmediateDomBuilderT t m) = WebViewPhantom m
514− askWebView = lift askWebView
556+instance HasJSContext m => HasJSContext (ImmediateDomBuilderT t m) where
557+ type JSContextPhantom (ImmediateDomBuilderT t m) = JSContextPhantom m
558+ askJSContext = lift askJSContext
515559
516560instance MonadRef m => MonadRef (ImmediateDomBuilderT t m) where
517561 type Ref (ImmediateDomBuilderT t m) = Ref m
@@ -527,7 +571,7 @@ instance MonadAtomicRef m => MonadAtomicRef (ImmediateDomBuilderT t m) where
527571 atomicModifyRef r = lift . atomicModifyRef r
528572
529573instance (HasJS x m, ReflexHost t) => HasJS x (ImmediateDomBuilderT t m) where
530− type JSM (ImmediateDomBuilderT t m) = JSM m
574+ type JSX (ImmediateDomBuilderT t m) = JSX m
531575 liftJS = lift . liftJS
532576
533577type family EventType en where
@@ -728,8 +772,57 @@ withIsEvent en r = case en of
728772 Mousewheel -> r
729773 Wheel -> r
730774
775+showEventName :: EventName en -> String
776+showEventName en = case en of
777+ Abort -> "Abort"
778+ Blur -> "Blur"
779+ Change -> "Change"
780+ Click -> "Click"
781+ Contextmenu -> "Contextmenu"
782+ Dblclick -> "Dblclick"
783+ Drag -> "Drag"
784+ Dragend -> "Dragend"
785+ Dragenter -> "Dragenter"
786+ Dragleave -> "Dragleave"
787+ Dragover -> "Dragover"
788+ Dragstart -> "Dragstart"
789+ Drop -> "Drop"
790+ Error -> "Error"
791+ Focus -> "Focus"
792+ Input -> "Input"
793+ Invalid -> "Invalid"
794+ Keydown -> "Keydown"
795+ Keypress -> "Keypress"
796+ Keyup -> "Keyup"
797+ Load -> "Load"
798+ Mousedown -> "Mousedown"
799+ Mouseenter -> "Mouseenter"
800+ Mouseleave -> "Mouseleave"
801+ Mousemove -> "Mousemove"
802+ Mouseout -> "Mouseout"
803+ Mouseover -> "Mouseover"
804+ Mouseup -> "Mouseup"
805+ Mousewheel -> "Mousewheel"
806+ Scroll -> "Scroll"
807+ Select -> "Select"
808+ Submit -> "Submit"
809+ Wheel -> "Wheel"
810+ Beforecut -> "Beforecut"
811+ Cut -> "Cut"
812+ Beforecopy -> "Beforecopy"
813+ Copy -> "Copy"
814+ Beforepaste -> "Beforepaste"
815+ Paste -> "Paste"
816+ Reset -> "Reset"
817+ Search -> "Search"
818+ Selectstart -> "Selectstart"
819+ Touchstart -> "Touchstart"
820+ Touchmove -> "Touchmove"
821+ Touchend -> "Touchend"
822+ Touchcancel -> "Touchcancel"
823+
731824{-# INLINABLE elementOnEventName #-}
732−elementOnEventName :: IsElement e => EventName en -> e -> EventM e (EventType en) () -> IO (IO ())
825+elementOnEventName :: IsElement e => EventName en -> e -> EventM e (EventType en) () -> JSM (JSM ())
733826elementOnEventName en e = case en of
734827 Abort -> on e Element.abort
735828 Blur -> on e Element.blurEvent
@@ -779,7 +872,7 @@ elementOnEventName en e = case en of
779872 Touchcancel -> on e Element.touchCancel
780873
781874{-# INLINABLE windowOnEventName #-}
782−windowOnEventName :: EventName en -> DOM.Window -> EventM DOM.Window (EventType en) () -> IO (IO ())
875+windowOnEventName :: EventName en -> DOM.Window -> EventM DOM.Window (EventType en) () -> JSM (JSM ())
783876windowOnEventName en e = case en of
784877 Abort -> on e Window.abort
785878 Blur -> on e Window.blurEvent
@@ -829,15 +922,15 @@ windowOnEventName en e = case en of
829922 Touchcancel -> on e Window.touchCancel
830923
831924{-# INLINABLE wrapDomEvent #-}
832−wrapDomEvent :: TriggerEvent t m => e -> (e -> EventM e event () -> IO (IO ())) -> EventM e event a -> m (Event t a)
925+wrapDomEvent :: (TriggerEvent t m, MonadJSM m) => e -> (e -> EventM e event () -> JSM (JSM ())) -> EventM e event a -> m (Event t a)
833926wrapDomEvent el elementOnevent getValue = wrapDomEventMaybe el elementOnevent $ fmap Just getValue
834927
835928{-# INLINABLE subscribeDomEvent #-}
836−subscribeDomEvent :: (EventM e event () -> IO (IO ()))
929+subscribeDomEvent :: (EventM e event () -> JSM (JSM ()))
837930 -> EventM e event (Maybe a)
838931 -> Chan [DSum (TriggerRef t) TriggerInvocation]
839932 -> EventTrigger t a
840− -> IO (IO ())
933+ -> JSM (JSM ())
841934subscribeDomEvent elementOnevent getValue eventChan et = elementOnevent $ do
842935 mv <- getValue
843936 forM_ mv $ \v -> liftIO $ do
@@ -846,25 +939,28 @@ subscribeDomEvent elementOnevent getValue eventChan et = elementOnevent $ do
846939 writeChan eventChan [TriggerRef etr :=> TriggerInvocation v (return ())]
847940
848941{-# INLINABLE wrapDomEventMaybe #-}
849−wrapDomEventMaybe :: TriggerEvent t m
942+wrapDomEventMaybe :: (TriggerEvent t m, MonadJSM m)
850943 => e
851− -> (e -> EventM e event () -> IO (IO ()))
944+ -> (e -> EventM e event () -> JSM (JSM ()))
852945 -> EventM e event (Maybe a)
853946 -> m (Event t a)
854947wrapDomEventMaybe el elementOnevent getValue = do
855− newEventWithLazyTriggerWithOnComplete $ \trigger -> elementOnevent el $ do
948+ ctx <- askJSM
949+ newEventWithLazyTriggerWithOnComplete $ \trigger -> (`runJSM` ctx) <$> (`runJSM` ctx) (elementOnevent el $ do
856950 mv <- getValue
857− forM_ mv $ \v -> liftIO $ trigger v $ return ()
951+ forM_ mv $ \v -> liftIO $ trigger v $ return ())
858952
859953{-# INLINABLE wrapDomEventsMaybe #-}
860−wrapDomEventsMaybe :: (MonadIO m, MonadReflexCreateTrigger t m)
954+wrapDomEventsMaybe :: (MonadJSM m, MonadReflexCreateTrigger t m)
861955 => e
862956 -> (forall en. IsEvent (EventType en) => EventName en -> EventM e (EventType en) (Maybe (f en)))
863− -> (forall en. EventName en -> e -> EventM e (EventType en) () -> IO (IO ()))
957+ -> (forall en. EventName en -> e -> EventM e (EventType en) () -> JSM (JSM ()))
864958 -> ImmediateDomBuilderT t m (EventSelector t (WrapArg f EventName))
865959wrapDomEventsMaybe target handlers onEventName = do
960+ ctx <- askJSM
866961 eventChan <- askEvents
867− e <- lift $ newFanEventWithTrigger $ \(WrapArg en) -> withIsEvent en $ subscribeDomEvent (onEventName en target) (handlers en) eventChan
962+ e <- lift $ newFanEventWithTrigger $ \(WrapArg en) -> withIsEvent en
963+ (((`runJSM` ctx) <$>) . (`runJSM` ctx) . subscribeDomEvent (onEventName en target) (handlers en) eventChan)
868964 return $! e
869965
870966{-# INLINABLE getKeyEvent #-}
@@ -905,7 +1001,7 @@ data Window t = Window
9051001 , _window_raw :: DOM.Window
9061002 }
9071003
908−wrapWindow :: (MonadIO m, MonadReflexCreateTrigger t m) => DOM.Window -> WindowConfig t -> ImmediateDomBuilderT t m (Window t)
1004+wrapWindow :: (MonadJSM m, MonadReflexCreateTrigger t m) => DOM.Window -> WindowConfig t -> ImmediateDomBuilderT t m (Window t)
9091005wrapWindow wv _ = do
9101006 events <- wrapDomEventsMaybe wv (defaultDomWindowEventHandler wv) windowOnEventName
9111007 return $ Window
@@ -913,4 +1009,6 @@ wrapWindow wv _ = do
9131009 , _window_raw = wv
9141010 }
9151011
1012+#ifdef USE_TEMPLATE_HASKELL
9161013makeLenses ''GhcjsEventSpec
1014+#endif