{-# LANGUAGE CPP #-} {-# LANGUAGE PatternSynonyms #-} #ifdef ghcjs_HOST_OS {-# OPTIONS_GHC -Wno-dodgy-exports -Wno-dodgy-imports #-} #endif ----------------------------------------------------------------------------- -- -- Module : Language.Javascript.JSaddle.Monad -- Copyright : (c) Hamish Mackenzie -- License : MIT -- -- Maintainer : Hamish Mackenzie -- -- | JSM monad keeps track of the JavaScript context -- ----------------------------------------------------------------------------- module Language.Javascript.JSaddle.Monad ( -- * Types JSM(..) , JSContextRef , MonadJSM , liftJSM -- * Running JavaScript in a JavaScript context , askJSM , runJSM , runJSaddle -- * Syncronizing with the JavaScript context , syncPoint , syncAfter , waitForAnimationFrame , nextAnimationFrame -- * Exception Handling , catch , bracket ) where import Prelude hiding (read) #ifndef ghcjs_HOST_OS import Control.Monad.Trans.Reader (runReaderT, ask, ReaderT(..)) #endif import Control.Monad.IO.Class (MonadIO(..)) import qualified Control.Exception as E (Exception, catch, bracket) import Language.Javascript.JSaddle.Types (JSM(..), MonadJSM, liftJSM, JSContextRef(..)) import Language.Javascript.JSaddle.Run (syncPoint, syncAfter, waitForAnimationFrame, nextAnimationFrame) -- | Gets the JavaScript context from the monad askJSM :: MonadJSM m => m JSContextRef #ifdef ghcjs_HOST_OS askJSM = return () #else askJSM = liftJSM $ JSM ask #endif -- | Runs a 'JSM' JavaScript function in a given JavaScript context. runJSM :: MonadIO m => JSM a -> JSContextRef -> m a #ifdef ghcjs_HOST_OS runJSM f = liftIO . const f #else runJSM f = liftIO . runReaderT (unJSM f) #endif -- | Alternative version of 'runJSM' runJSaddle :: MonadIO m => JSContextRef -> JSM a -> m a runJSaddle = flip runJSM -- | Wrapped version of 'E.catch' that runs in a MonadIO that works -- a bit better with 'JSM' catch :: E.Exception e => JSM b -> (e -> JSM b) -> JSM b t `catch` c = do r <- askJSM liftIO (runJSM (syncAfter t) r `E.catch` \e -> runJSM (c e) r) -- | Wrapped version of 'E.bracket' that runs in a MonadIO that works -- a bit better with 'JSM' bracket :: JSM a -> (a -> JSM b) -> (a -> JSM c) -> JSM c bracket aquire release f = do r <- askJSM liftIO $ E.bracket (runJSM (syncAfter aquire) r) (\x -> runJSM (syncAfter $ release x) r) (\x -> runJSM (syncAfter $ f x) r)