@@ -12,7 +12,6 @@ module Reflex.Dom.WebSocket.Foreign
13import Prelude hiding (all, concat, concatMap, div, mapM, mapM_, sequence, span)
13import Prelude hiding (all, concat, concatMap, div, mapM, mapM_, sequence, span)
15−import Control.Monad.Reader
16import Data.Bifoldable
15import Data.Bifoldable
17import Data.ByteString (ByteString)
16import Data.ByteString (ByteString)
18import qualified Data.ByteString.Lazy as LBS
17import qualified Data.ByteString.Lazy as LBS
@@ -20,12 +19,11 @@ import Data.Text (Text)
20import Data.Text.Encoding
19import Data.Text.Encoding
21import Foreign.JavaScript.Utils (bsFromMutableArrayBuffer, bsToArrayBuffer)
20import Foreign.JavaScript.Utils (bsFromMutableArrayBuffer, bsToArrayBuffer)
22import GHCJS.DOM.CloseEvent
21import GHCJS.DOM.CloseEvent
23−import GHCJS.DOM.EventM (on)
24import GHCJS.DOM.MessageEvent
22import GHCJS.DOM.MessageEvent
25−import GHCJS.DOM.Types (JSM, JSVal, liftJSM, fromJSValUnchecked)
23+import GHCJS.DOM.Types (JSM, JSVal, liftJSM, fromJSValUnchecked, WebSocket(..))
26−import GHCJS.DOM.WebSocket (WebSocket)
27import qualified GHCJS.DOM.WebSocket as DOM
24import qualified GHCJS.DOM.WebSocket as DOM
28import GHCJS.Foreign (JSType(..), jsTypeOf)
25import GHCJS.Foreign (JSType(..), jsTypeOf)
26+import Language.Javascript.JSaddle (fun, eval, toJSVal, call)
29import Language.Javascript.JSaddle.Helper (mutableArrayBufferFromJSVal)
27import Language.Javascript.JSaddle.Helper (mutableArrayBufferFromJSVal)
30import Language.Javascript.JSaddle.Types (ghcjsPure)
28import Language.Javascript.JSaddle.Types (ghcjsPure)
@@ -64,25 +62,41 @@ newWebSocket
64 -> ((Bool, Word, Text) -> JSM ()) -- onclose
62 -> ((Bool, Word, Text) -> JSM ()) -- onclose
65 -> JSM JSWebSocket
63 -> JSM JSWebSocket
66newWebSocket _ url protocols onMessage onOpen onError onClose = do
64newWebSocket _ url protocols onMessage onOpen onError onClose = do
67− ws <- DOM.newWebSocket url protocols
65+ let onOpenWrapped = fun $ \_ _ _ -> onOpen
68− DOM.setBinaryType ws "arraybuffer"
66+ onErrorWrapped = fun $ \_ _ _ -> onError
69− _ <- on ws DOM.open $ liftJSM onOpen
67+ onCloseWrapped = fun $ \_ _ (e:_) -> do
70− _ <- on ws DOM.error $ liftJSM onError
68+ let e' = CloseEvent e
71− _ <- on ws DOM.closeEvent $ do
73− wasClean <- getWasClean e
69+ wasClean <- getWasClean e'
74− code <- getCode e
70+ code <- getCode e'
75− reason <- getReason e
71+ reason <- getReason e'
76− liftJSM $ onClose (wasClean, code, reason)
72+ liftJSM $ onClose (wasClean, code, reason)
77− _ <- on ws DOM.message $ do
73+ onMessageWrapped = fun $ \_ _ (e:_) -> do
78− e <- ask
74+ let e' = MessageEvent e
79− d <- getData e
75+ d <- getData e'
80− liftJSM $ ghcjsPure (jsTypeOf d) >>= \case
76+ liftJSM $ ghcjsPure (jsTypeOf d) >>= \case
81− String -> onMessage $ Right d
77+ String -> onMessage $ Right d
83− ab <- mutableArrayBufferFromJSVal d
79+ ab <- mutableArrayBufferFromJSVal d
84− bsFromMutableArrayBuffer ab >>= onMessage . Left
80+ bsFromMutableArrayBuffer ab >>= onMessage . Left
81+ newWS <- eval $ unlines
82+ [ "(function(url, protos, open, error, close, message) {"
83+ , " var ws = new window['WebSocket'](url, protos);"
84+ , " ws['binaryType'] = 'arraybuffer';"
85+ , " ws['addEventListener']('open', open);"
86+ , " ws['addEventListener']('error', error);"
87+ , " ws['addEventListener']('close', close);"
88+ , " ws['addEventListener']('message', message);"
93+ protocols' <- toJSVal protocols
94+ onOpen' <- toJSVal onOpenWrapped
95+ onError' <- toJSVal onErrorWrapped
96+ onClose' <- toJSVal onCloseWrapped
97+ onMessage' <- toJSVal onMessageWrapped
98+ ws <- call newWS newWS [url', protocols', onOpen', onError', onClose', onMessage']
85− return $ JSWebSocket ws
99+ return $ JSWebSocket $ WebSocket ws
87onBSMessage :: Either ByteString JSVal -> JSM ByteString
101onBSMessage :: Either ByteString JSVal -> JSM ByteString
88onBSMessage = either return $ fmap encodeUtf8 . fromJSValUnchecked
102onBSMessage = either return $ fmap encodeUtf8 . fromJSValUnchecked