{-# LANGUAGE DeriveDataTypeable #-}
module JSDOM.Custom.XMLHttpRequest (
module Generated
, XHRError(..)
, send
, sendString
, sendArrayBuffer
, sendBlob
, sendDocument
, sendFormData
) where
import Prelude ()
import Prelude.Compat
import Data.Typeable (Typeable)
import Control.Concurrent.MVar (takeMVar, newEmptyMVar, putMVar)
import Control.Monad (void)
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.Catch (onException, bracket, throwM)
import Control.Exception (Exception(..))
import Control.Lens.Operators ((^.))
import Language.Javascript.JSaddle
(js0, js1, ToJSString, ToJSVal(..), JSVal)
import JSDOM.Types
(DOM, MonadDOM, liftDOM, FormData(..), IsDocument, IsBlob, IsArrayBufferView)
import JSDOM.EventM (onAsync)
import JSDOM.Generated.XMLHttpRequest as Generated hiding (send)
import JSDOM.Generated.XMLHttpRequestEventTarget as Generated
data XHRError = XHRError
| XHRAborted
deriving (Show, Eq, Typeable)
instance Exception XHRError
throwXHRError :: MonadDOM m => Maybe XHRError -> m ()
throwXHRError = maybe (return ()) (liftDOM . throwM)
withEvent :: DOM (DOM ()) -> DOM a -> DOM a
withEvent aquire = bracket aquire id . const
send' :: (MonadDOM m) => XMLHttpRequest -> Maybe JSVal -> m ()
send' self mbVal = liftDOM $ (`onException` abort self) $ do
result <- liftIO newEmptyMVar
r <- withEvent (onAsync self Generated.error . liftIO $ putMVar result (Just XHRError)) $
withEvent (onAsync self abortEvent . liftIO $ putMVar result (Just XHRAborted)) $
withEvent (onAsync self load . liftIO $ putMVar result Nothing) $ do
void $
case mbVal of
Nothing -> self ^. js0 "send"
Just val -> self ^. js1 "send" val
liftIO $ takeMVar result
throwXHRError r
send :: (MonadDOM m) => XMLHttpRequest -> m ()
send self = send' self Nothing
sendString :: (MonadDOM m, ToJSString str) => XMLHttpRequest -> str -> m ()
sendString self str = liftDOM $ toJSVal str >>= send' self . Just
sendArrayBuffer :: (MonadDOM m, IsArrayBufferView view) => XMLHttpRequest -> view -> m ()
sendArrayBuffer self view = liftDOM $ toJSVal view >>= send' self . Just
sendBlob :: (MonadDOM m, IsBlob blob) => XMLHttpRequest -> blob -> m ()
sendBlob self blob = liftDOM $ toJSVal blob >>= send' self . Just
sendDocument :: (MonadDOM m, IsDocument doc) => XMLHttpRequest -> doc -> m ()
sendDocument self doc = liftDOM $ toJSVal doc >>= send' self . Just
sendFormData :: (MonadDOM m) => XMLHttpRequest -> FormData -> m ()
sendFormData self formData = liftDOM $ toJSVal formData >>= send' self . Just