Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DomHasCallStack for ghcjs-dom debug feature #217

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion reflex-dom-core/reflex-dom-core.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ library
dependent-sum-template >= 0.1 && < 0.2,
directory >= 1.2 && < 1.4,
exception-transformers == 0.4.*,
ghcjs-dom >= 0.9.1.0 && < 0.10,
ghcjs-dom >= 0.9.4.0 && < 0.10,
jsaddle >= 0.9.0.0 && < 0.10,
-- keycode-0.2 has a bug on firefox
keycode >= 0.2.1 && < 0.3,
Expand Down
29 changes: 19 additions & 10 deletions reflex-dom-core/src/Reflex/Dom/Builder/Class.hs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import Data.Semigroup
import Data.String
import Data.Text (Text)
import Data.Type.Coercion
import GHCJS.DOM.Debug (DomHasCallStack)
import GHCJS.DOM.Types (JSM)
import qualified GHCJS.DOM.Types as DOM

Expand All @@ -78,77 +79,85 @@ class Default (EventSpec d EventResult) => DomSpace d where
-- dynamic DOM in the 'Reflex' timeline @t@
class (Monad m, Reflex t, DomSpace (DomBuilderSpace m), NotReady t m, Adjustable t m) => DomBuilder t m | m -> t where
type DomBuilderSpace m :: *
textNode :: TextNodeConfig t -> m (TextNode (DomBuilderSpace m) t)
textNode :: DomHasCallStack => TextNodeConfig t -> m (TextNode (DomBuilderSpace m) t)
default textNode :: ( MonadTrans f
, m ~ f m'
, DomBuilderSpace m' ~ DomBuilderSpace m
, DomBuilder t m'
, DomHasCallStack
)
=> TextNodeConfig t -> m (TextNode (DomBuilderSpace m) t)
textNode = lift . textNode
{-# INLINABLE textNode #-}
commentNode :: CommentNodeConfig t -> m (CommentNode (DomBuilderSpace m) t)
commentNode :: DomHasCallStack => CommentNodeConfig t -> m (CommentNode (DomBuilderSpace m) t)
default commentNode :: ( MonadTrans f
, m ~ f m'
, DomBuilderSpace m' ~ DomBuilderSpace m
, DomBuilder t m'
, DomHasCallStack
)
=> CommentNodeConfig t -> m (CommentNode (DomBuilderSpace m) t)
commentNode = lift . commentNode
{-# INLINABLE commentNode #-}
element :: Text -> ElementConfig er t (DomBuilderSpace m) -> m a -> m (Element er (DomBuilderSpace m) t, a)
element :: DomHasCallStack => Text -> ElementConfig er t (DomBuilderSpace m) -> m a -> m (Element er (DomBuilderSpace m) t, a)
default element :: ( MonadTransControl f
, StT f a ~ a
, m ~ f m'
, DomBuilderSpace m' ~ DomBuilderSpace m
, DomBuilder t m'
, DomHasCallStack
)
=> Text -> ElementConfig er t (DomBuilderSpace m) -> m a -> m (Element er (DomBuilderSpace m) t, a)
element t cfg child = liftWith $ \run -> element t cfg $ run child
{-# INLINABLE element #-}
inputElement :: InputElementConfig er t (DomBuilderSpace m) -> m (InputElement er (DomBuilderSpace m) t)
inputElement :: DomHasCallStack => InputElementConfig er t (DomBuilderSpace m) -> m (InputElement er (DomBuilderSpace m) t)
default inputElement :: ( MonadTransControl f
, m ~ f m'
, DomBuilderSpace m' ~ DomBuilderSpace m
, DomBuilder t m'
, DomHasCallStack
)
=> InputElementConfig er t (DomBuilderSpace m) -> m (InputElement er (DomBuilderSpace m) t)
inputElement = lift . inputElement
{-# INLINABLE inputElement #-}
textAreaElement :: TextAreaElementConfig er t (DomBuilderSpace m) -> m (TextAreaElement er (DomBuilderSpace m) t)
textAreaElement :: DomHasCallStack => TextAreaElementConfig er t (DomBuilderSpace m) -> m (TextAreaElement er (DomBuilderSpace m) t)
default textAreaElement :: ( MonadTransControl f
, m ~ f m'
, DomBuilderSpace m' ~ DomBuilderSpace m
, DomBuilder t m'
, DomHasCallStack
)
=> TextAreaElementConfig er t (DomBuilderSpace m) -> m (TextAreaElement er (DomBuilderSpace m) t)
textAreaElement = lift . textAreaElement
{-# INLINABLE textAreaElement #-}
selectElement :: SelectElementConfig er t (DomBuilderSpace m) -> m a -> m (SelectElement er (DomBuilderSpace m) t, a)
selectElement :: DomHasCallStack => SelectElementConfig er t (DomBuilderSpace m) -> m a -> m (SelectElement er (DomBuilderSpace m) t, a)
default selectElement :: ( MonadTransControl f
, StT f a ~ a
, m ~ f m'
, DomBuilderSpace m' ~ DomBuilderSpace m
, DomBuilder t m'
, DomHasCallStack
)
=> SelectElementConfig er t (DomBuilderSpace m) -> m a -> m (SelectElement er (DomBuilderSpace m) t, a)
selectElement cfg child = do
liftWith $ \run -> selectElement cfg $ run child
{-# INLINABLE selectElement #-}
placeRawElement :: RawElement (DomBuilderSpace m) -> m ()
placeRawElement :: DomHasCallStack => RawElement (DomBuilderSpace m) -> m ()
default placeRawElement :: ( MonadTrans f
, m ~ f m'
, DomBuilderSpace m' ~ DomBuilderSpace m
, DomBuilder t m'
, DomHasCallStack
)
=> RawElement (DomBuilderSpace m) -> m ()
placeRawElement = lift . placeRawElement
{-# INLINABLE placeRawElement #-}
wrapRawElement :: RawElement (DomBuilderSpace m) -> RawElementConfig er t (DomBuilderSpace m) -> m (Element er (DomBuilderSpace m) t)
wrapRawElement :: DomHasCallStack => RawElement (DomBuilderSpace m) -> RawElementConfig er t (DomBuilderSpace m) -> m (Element er (DomBuilderSpace m) t)
default wrapRawElement :: ( MonadTrans f
, m ~ f m'
, DomBuilderSpace m' ~ DomBuilderSpace m
, DomBuilder t m'
, DomHasCallStack
)
=> RawElement (DomBuilderSpace m) -> RawElementConfig er t (DomBuilderSpace m) -> m (Element er (DomBuilderSpace m) t)
wrapRawElement e cfg = lift $ wrapRawElement e $ cfg
Expand All @@ -158,8 +167,8 @@ class (Monad m, Reflex t, DomSpace (DomBuilderSpace m), NotReady t m, Adjustable

class DomBuilder t m => MountableDomBuilder t m where
type DomFragment m :: *
buildDomFragment :: m a -> m (DomFragment m, a)
mountDomFragment :: DomFragment m -> Event t (DomFragment m) -> m ()
buildDomFragment :: DomHasCallStack => m a -> m (DomFragment m, a)
mountDomFragment :: DomHasCallStack => DomFragment m -> Event t (DomFragment m) -> m ()

type Namespace = Text

Expand Down
6 changes: 4 additions & 2 deletions reflex-dom-core/src/Reflex/Dom/Builder/Immediate.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
Expand Down Expand Up @@ -140,7 +141,8 @@ import Data.Some (Some(..))
import Data.Text (Text)
import Foreign.JavaScript.Internal.Utils
import Foreign.JavaScript.TH
import GHCJS.DOM.Document (Document, createDocumentFragment, createElement, createElementNS, createTextNode, createComment)
import GHCJS.DOM.Debug (DomHasCallStack)
import "ghcjs-dom" GHCJS.DOM.Document (Document, createDocumentFragment, createElement, createElementNS, createTextNode, createComment)
import GHCJS.DOM.Element (getScrollTop, removeAttribute, removeAttributeNS, setAttribute, setAttributeNS, hasAttribute, hasAttributeNS)
import GHCJS.DOM.EventM (EventM, event, on)
import GHCJS.DOM.KeyboardEvent as KeyboardEvent
Expand Down Expand Up @@ -658,7 +660,7 @@ instance er ~ EventResult => Default (GhcjsEventSpec er) where
}

{-# INLINE makeElement #-}
makeElement :: MonadJSM m => Document -> Text -> ElementConfig er t s -> m DOM.Element
makeElement :: (MonadJSM m, DomHasCallStack) => Document -> Text -> ElementConfig er t s -> m DOM.Element
makeElement doc elementTag cfg = do
e <- uncheckedCastTo DOM.Element <$> case cfg ^. namespace of
Nothing -> createElement doc elementTag
Expand Down
3 changes: 2 additions & 1 deletion reflex-dom-core/src/Reflex/Dom/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecursiveDo #-}
Expand Down Expand Up @@ -46,7 +47,7 @@ import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding
import GHCJS.DOM
import GHCJS.DOM.Document
import "ghcjs-dom" GHCJS.DOM.Document
import GHCJS.DOM.Element
import GHCJS.DOM.Node
import GHCJS.DOM.NonElementParentNode
Expand Down
3 changes: 2 additions & 1 deletion reflex-dom-core/src/Reflex/Dom/Prerender.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE ScopedTypeVariables #-}
Expand Down Expand Up @@ -41,7 +42,7 @@ import Reflex.Host.Class
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as IntMap

import qualified GHCJS.DOM.Document as Document
import qualified "ghcjs-dom" GHCJS.DOM.Document as Document
import qualified GHCJS.DOM.Node as Node
import qualified GHCJS.DOM.Types as DOM

Expand Down
45 changes: 23 additions & 22 deletions reflex-dom-core/src/Reflex/Dom/Widget/Basic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import Reflex.Dynamic
import Reflex.Network
import Reflex.PostBuild.Class
import Reflex.Workflow
import GHCJS.DOM.Debug (DomHasCallStack)

import Control.Arrow
import Control.Lens hiding (children, element)
Expand Down Expand Up @@ -109,11 +110,11 @@ partitionMapBySetLT s m0 = Map.fromDistinctAscList $ go (Set.toAscList s) m0
else (Left h, lt) : go t geq

{-# INLINABLE text #-}
text :: DomBuilder t m => Text -> m ()
text :: (DomBuilder t m, DomHasCallStack) => Text -> m ()
text t = void $ textNode $ def & textNodeConfig_initialContents .~ t

{-# INLINABLE dynText #-}
dynText :: forall t m. (PostBuild t m, DomBuilder t m) => Dynamic t Text -> m ()
dynText :: forall t m. (PostBuild t m, DomBuilder t m, DomHasCallStack) => Dynamic t Text -> m ()
dynText t = do
postBuild <- getPostBuild
void $ textNode $ (def :: TextNodeConfig t) & textNodeConfig_setContents .~ leftmost
Expand All @@ -135,11 +136,11 @@ dynComment t = do
]
notReadyUntil postBuild

display :: (PostBuild t m, DomBuilder t m, Show a) => Dynamic t a -> m ()
display :: (PostBuild t m, DomBuilder t m, Show a, DomHasCallStack) => Dynamic t a -> m ()
display = dynText . fmap (T.pack . show)

{-# DEPRECATED button "Use 'elAttr'' in combination with 'domEvent' instead" #-}
button :: DomBuilder t m => Text -> m (Event t ())
button :: (DomBuilder t m, DomHasCallStack) => Text -> m (Event t ())
button t = do
(e, _) <- element "button" def $ text t
return $ domEvent Click e
Expand Down Expand Up @@ -172,39 +173,39 @@ widgetHold_ z = void . widgetHold z
-- >>> el "div" (text "Hello World")
-- <div>Hello World</div>
{-# INLINABLE el #-}
el :: forall t m a. DomBuilder t m => Text -> m a -> m a
el :: forall t m a. (DomBuilder t m, DomHasCallStack) => Text -> m a -> m a
el elementTag child = snd <$> el' elementTag child

-- | Create a DOM element with attributes
--
-- >>> elAttr "a" ("href" =: "https://reflex-frp.org") (text "Reflex-FRP!")
-- <a href="https://reflex-frp.org">Reflex-FRP!</a>
{-# INLINABLE elAttr #-}
elAttr :: forall t m a. DomBuilder t m => Text -> Map Text Text -> m a -> m a
elAttr :: forall t m a. (DomBuilder t m, DomHasCallStack) => Text -> Map Text Text -> m a -> m a
elAttr elementTag attrs child = snd <$> elAttr' elementTag attrs child

-- | Create a DOM element with classes
--
-- >>> elClass "div" "row" (return ())
-- <div class="row"></div>
{-# INLINABLE elClass #-}
elClass :: forall t m a. DomBuilder t m => Text -> Text -> m a -> m a
elClass :: forall t m a. (DomBuilder t m, DomHasCallStack) => Text -> Text -> m a -> m a
elClass elementTag c child = snd <$> elClass' elementTag c child

-- | Create a DOM element with Dynamic Attributes
--
-- >>> elClass "div" (constDyn ("class" =: "row")) (return ())
-- <div class="row"></div>
{-# INLINABLE elDynAttr #-}
elDynAttr :: forall t m a. (DomBuilder t m, PostBuild t m) => Text -> Dynamic t (Map Text Text) -> m a -> m a
elDynAttr :: forall t m a. (DomBuilder t m, PostBuild t m, DomHasCallStack) => Text -> Dynamic t (Map Text Text) -> m a -> m a
elDynAttr elementTag attrs child = snd <$> elDynAttr' elementTag attrs child

-- | Create a DOM element with a Dynamic Class
--
-- >>> elDynClass "div" (constDyn "row") (return ())
-- <div class="row"></div>
{-# INLINABLE elDynClass #-}
elDynClass :: forall t m a. (DomBuilder t m, PostBuild t m) => Text -> Dynamic t Text -> m a -> m a
elDynClass :: forall t m a. (DomBuilder t m, PostBuild t m, DomHasCallStack) => Text -> Dynamic t Text -> m a -> m a
elDynClass elementTag c child = snd <$> elDynClass' elementTag c child

-- | Create a DOM element and return the element
Expand All @@ -214,32 +215,32 @@ elDynClass elementTag c child = snd <$> elDynClass' elementTag c child
-- return $ domEvent Click e
-- @
{-# INLINABLE el' #-}
el' :: forall t m a. DomBuilder t m => Text -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
el' :: forall t m a. (DomBuilder t m, DomHasCallStack) => Text -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
el' elementTag = element elementTag def

-- | Create a DOM element with attributes and return the element
{-# INLINABLE elAttr' #-}
elAttr' :: forall t m a. DomBuilder t m => Text -> Map Text Text -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elAttr' :: forall t m a. (DomBuilder t m, DomHasCallStack) => Text -> Map Text Text -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elAttr' elementTag attrs = element elementTag $ def
& initialAttributes .~ Map.mapKeys (AttributeName Nothing) attrs

-- | Create a DOM element with a class and return the element
{-# INLINABLE elClass' #-}
elClass' :: forall t m a. DomBuilder t m => Text -> Text -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elClass' :: forall t m a. (DomBuilder t m, DomHasCallStack) => Text -> Text -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elClass' elementTag c = elAttr' elementTag ("class" =: c)

-- | Create a DOM element with Dynamic Attributes and return the element
{-# INLINABLE elDynAttr' #-}
elDynAttr' :: forall t m a. (DomBuilder t m, PostBuild t m) => Text -> Dynamic t (Map Text Text) -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elDynAttr' :: forall t m a. (DomBuilder t m, PostBuild t m, DomHasCallStack) => Text -> Dynamic t (Map Text Text) -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elDynAttr' = elDynAttrNS' Nothing

-- | Create a DOM element with a Dynamic class and return the element
{-# INLINABLE elDynClass' #-}
elDynClass' :: forall t m a. (DomBuilder t m, PostBuild t m) => Text -> Dynamic t Text -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elDynClass' :: forall t m a. (DomBuilder t m, PostBuild t m, DomHasCallStack) => Text -> Dynamic t Text -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elDynClass' elementTag c = elDynAttr' elementTag (fmap ("class" =:) c)

{-# INLINABLE elDynAttrNS' #-}
elDynAttrNS' :: forall t m a. (DomBuilder t m, PostBuild t m) => Maybe Text -> Text -> Dynamic t (Map Text Text) -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elDynAttrNS' :: forall t m a. (DomBuilder t m, PostBuild t m, DomHasCallStack) => Maybe Text -> Text -> Dynamic t (Map Text Text) -> m a -> m (Element EventResult (DomBuilderSpace m) t, a)
elDynAttrNS' mns elementTag attrs child = do
modifyAttrs <- dynamicAttributesToModifyAttributes attrs
let cfg = def
Expand All @@ -251,7 +252,7 @@ elDynAttrNS' mns elementTag attrs child = do
return result

{-# INLINABLE elDynAttrNS #-}
elDynAttrNS :: forall t m a. (DomBuilder t m, PostBuild t m) => Maybe Text -> Text -> Dynamic t (Map Text Text) -> m a -> m a
elDynAttrNS :: forall t m a. (DomBuilder t m, PostBuild t m, DomHasCallStack) => Maybe Text -> Text -> Dynamic t (Map Text Text) -> m a -> m a
elDynAttrNS mns elementTag attrs child = fmap snd $ elDynAttrNS' mns elementTag attrs child

dynamicAttributesToModifyAttributes :: (Ord k, PostBuild t m) => Dynamic t (Map k Text) -> m (Event t (Map k (Maybe Text)))
Expand All @@ -278,20 +279,20 @@ newtype Link t
}

{-# DEPRECATED linkClass "Use 'elAttr'' in combination with 'domEvent' for just clicks. Use 'routeLink' for Obelisk navigation" #-}
linkClass :: DomBuilder t m => Text -> Text -> m (Link t)
linkClass :: (DomBuilder t m, DomHasCallStack) => Text -> Text -> m (Link t)
linkClass s c = do
(l,_) <- elAttr' "a" ("class" =: c) $ text s
return $ Link $ domEvent Click l

{-# DEPRECATED link "Use 'elAttr'' in combination with 'domEvent' for just clicks. Use 'routeLink' for Obelisk navigation" #-}
link :: DomBuilder t m => Text -> m (Link t)
link :: (DomBuilder t m, DomHasCallStack) => Text -> m (Link t)
link s = linkClass s ""

divClass :: forall t m a. DomBuilder t m => Text -> m a -> m a
divClass :: forall t m a. (DomBuilder t m, DomHasCallStack) => Text -> m a -> m a
divClass = elClass "div"

{-# DEPRECATED dtdd "Use an application specific widget generating function" #-}
dtdd :: forall t m a. DomBuilder t m => Text -> m a -> m a
dtdd :: forall t m a. (DomBuilder t m, DomHasCallStack) => Text -> m a -> m a
dtdd h w = do
el "dt" $ text h
el "dd" w
Expand All @@ -302,7 +303,7 @@ blank = return ()
-- TODO: Move to an example project.
-- | A widget to display a table with static columns and dynamic rows.
{-# DEPRECATED tableDynAttr "Use an application specific widget generating function" #-}
tableDynAttr :: forall t m r k v. (Ord k, DomBuilder t m, MonadHold t m, PostBuild t m, MonadFix m)
tableDynAttr :: forall t m r k v. (Ord k, DomBuilder t m, MonadHold t m, PostBuild t m, MonadFix m, DomHasCallStack)
=> Text -- ^ Class applied to <table> element
-> [(Text, k -> Dynamic t r -> m v)] -- ^ Columns of (header, row key -> row value -> child widget)
-> Dynamic t (Map k r) -- ^ Map from row key to row value
Expand All @@ -322,7 +323,7 @@ tableDynAttr klass cols dRows rowAttrs = elAttr "div" (Map.singleton "style" "zo
-- Creates a header bar containing a <ul> with one <li> per child; clicking a <li> displays
-- the corresponding child and hides all others.
{-# DEPRECATED tabDisplay "Use an application specific widget generating function" #-}
tabDisplay :: forall t m k. (MonadFix m, DomBuilder t m, MonadHold t m, PostBuild t m, Ord k)
tabDisplay :: forall t m k. (MonadFix m, DomBuilder t m, MonadHold t m, PostBuild t m, Ord k, DomHasCallStack)
=> Text -- ^ Class applied to <ul> element
-> Text -- ^ Class applied to currently active <li> element
-> Map k (Text, m ()) -- ^ Map from (arbitrary) key to (tab label, child widget)
Expand Down
Loading