ghcjs-dom-0.9.4.0: src/GHCJS/DOM/Debug/Internal.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE KindSignatures #-}
module GHCJS.DOM.Debug.Internal (
DomHasCallStack
, debugEnabled
, cachedStacks
, cacheStack
, lookupStack
, getElementStack
) where
import Control.Monad (void)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Map (Map)
import qualified Data.Map as M (insert, size, lookup)
import Data.IORef (atomicModifyIORef', IORef, newIORef, readIORef)
import GHC.Stack
(SrcLoc, CallStack, callStack, getCallStack, HasCallStack)
import GHC.Exts (Constraint)
import System.IO.Unsafe (unsafePerformIO)
import Text.Read (readMaybe)
import GHCJS.DOM.Types (Element(..), MonadDOM, ToJSString, JSString)
import GHCJS.DOM.Element (setAttribute, getAttribute)
#ifdef GHCJS_DOM_DEBUG
type DomHasCallStack = (HasCallStack :: Constraint)
debugEnabled :: Bool
debugEnabled = True
#else
type DomHasCallStack = (() :: Constraint)
debugEnabled :: Bool
debugEnabled = False
#endif
cachedStacks :: IORef (Map String Int, Map Int [(String, SrcLoc)])
cachedStacks = unsafePerformIO $ newIORef (mempty, mempty)
{-# NOINLINE cachedStacks #-}
lookupStack :: MonadIO m => Int -> m (Maybe [(String, SrcLoc)])
lookupStack n = do
(_, intToStack) <- liftIO $ readIORef cachedStacks
return $ M.lookup n intToStack
getElementStack :: MonadDOM m => Element -> m (Maybe [(String, SrcLoc)])
getElementStack e =
getAttribute e ("hs-creator" :: JSString) >>= \case
Just a -> case readMaybe a of
Just n -> lookupStack n
Nothing -> return Nothing
Nothing -> return Nothing
cacheStack :: MonadIO m => [(String, SrcLoc)] -> m Int
cacheStack cs = do
let csString = show cs
liftIO $ atomicModifyIORef' cachedStacks $ \(stackToInt, intToStack) ->
case M.lookup csString stackToInt of
Just n -> ((stackToInt, intToStack), n)
Nothing ->
let n = M.size stackToInt in
((M.insert csString n stackToInt, M.insert n cs intToStack), n)