on develop help sign in
Avoid CPP
commita0284873a1a66085c8fa1167fd52000f1cc54d8b authorLuigy Leon <luigy@outlook.com> dateTue 6 Jun 2017, 19:57 (9 years ago) parent67d217e
5 files changed+56−41
reflex-dom-core/reflex-dom-core.cabal+3 reflex-dom-core/src-ghc/Reflex/Dom/WebSocket/Internal.hs+10 reflex-dom-core/src-ghcjs/Reflex/Dom/WebSocket/Internal.hs+30 reflex-dom-core/src/Foreign/JavaScript/Utils.hs+13−1 reflex-dom-core/src/Reflex/Dom/WebSocket.hs−40
reflex-dom-core/reflex-dom-core.cabal+3
@@ -13,6 +13,8 @@ Cabal-version: >=1.9.2
1313-- Deal with https://github.com/haskell/cabal/issues/2544 / https://github.com/haskell/cabal/issues/367
1414extra-source-files: src-ghc/Foreign/JavaScript/Internal/Utils.hs
1515 src-ghcjs/Foreign/JavaScript/Internal/Utils.hs
16+ src-ghc/Reflex/Dom/WebSocket/Internal.hs
17+ src-ghcjs/Reflex/Dom/WebSocket/Internal.hs
1618 src/Reflex/Dom/Xhr/Foreign.hs
1719 src/Reflex/Dom/WebSocket/Foreign.hs
1820 src/Reflex/Dom/Xhr/ResponseType.hs
@@ -122,6 +124,7 @@ library
122124 other-modules:
123125 Foreign.JavaScript.Internal.Utils
124126 Reflex.Dom.WebSocket.Foreign
127+ Reflex.Dom.WebSocket.Internal
125128 Reflex.Dom.Xhr.Foreign
126129 Reflex.Dom.Xhr.ResponseType
127130 Reflex.Dom.Xhr.Exception
reflex-dom-core/src-ghc/Reflex/Dom/WebSocket/Internal.hsnew file+10
@@ -0,0 +1,10 @@
1+module Reflex.Dom.WebSocket.Internal where
2+
3+import Data.Aeson
4+import qualified Data.ByteString.Lazy as LBS
5+import Data.JSString (JSString)
6+import Data.JSString.Text
7+import Data.Text.Encoding
8+
9+jsonDecode :: FromJSON a => JSString -> Maybe a
10+jsonDecode = decode . LBS.fromStrict . encodeUtf8 . textFromJSString
reflex-dom-core/src-ghcjs/Reflex/Dom/WebSocket/Internal.hsnew file+30
@@ -0,0 +1,30 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE LambdaCase #-}
3+{-# LANGUAGE ScopedTypeVariables #-}
4+module Reflex.Dom.WebSocket.Internal where
5+
6+import Control.Exception
7+import Data.Aeson
8+import Data.JSString (JSString)
9+import Foreign.JavaScript.Utils
10+import Language.Javascript.JSaddle
11+import System.IO.Unsafe
12+-- When on ghcjs and using packages with jsstring patches it removes the FromJSVal
13+-- instance for Value from ghcjs-base. This makes it so that if the patches
14+-- are used then the instance comes from ghcjs-json
15+#if defined(ghcjs_HOST_OS) && defined(USE_TEXT_JSSTRING)
16+import JavaScript.JSON.Types.FromJSVal ()
17+#endif
18+#if defined(ghcjs_HOST_OS) && !defined(USE_TEXT_JSSTRING)
19+import GHCJS.Marshal ()
20+#endif
21+
22+jsonDecode :: FromJSON a => JSString -> Maybe a
23+jsonDecode t = do
24+ result <- unsafePerformIO $ handle (\(_ :: SomeException) -> pure Nothing) $ do
25+ safeJsonParse t >>= \case
26+ Nothing -> pure Nothing
27+ Just a -> fromJSVal a
28+ case fromJSON result of
29+ Success a -> pure a
30+ Error _ -> Nothing
reflex-dom-core/src/Foreign/JavaScript/Utils.hs+13−1
@@ -1,15 +1,21 @@
1+{-# LANGUAGE ScopedTypeVariables #-}
12module Foreign.JavaScript.Utils
23 ( bsFromMutableArrayBuffer
34 , bsToArrayBuffer
5+ , jsonParse
6+ , safeJsonParse
47 ) where
58
9+import Control.Exception
10+import Control.Lens
611import Data.ByteString (ByteString)
712import qualified Data.ByteString as BS
813import Foreign.JavaScript.Internal.Utils (js_dataView)
914import qualified GHCJS.Buffer as JS
1015import GHCJS.DOM.Types (ArrayBuffer (..))
16+import qualified Language.Javascript.JSaddle as JS (catch, jsg, js1)
1117import qualified JavaScript.TypedArray.ArrayBuffer as JS
12−import Language.Javascript.JSaddle.Types (MonadJSM, ghcjsPure, jsval, liftJSM)
18+import Language.Javascript.JSaddle.Types (JSString, JSM, JSVal, MonadJSM, ghcjsPure, jsval, liftJSM)
1319
1420{-# INLINABLE bsFromMutableArrayBuffer #-}
1521bsFromMutableArrayBuffer :: MonadJSM m => JS.MutableArrayBuffer -> m ByteString
@@ -25,3 +31,9 @@ bsToArrayBuffer bs = liftJSM $ do
2531 else do
2632 ref <- ghcjsPure (JS.getArrayBuffer b) >>= ghcjsPure . jsval
2733 js_dataView off len ref
34+
35+safeJsonParse :: JSString -> JSM (Maybe JSVal)
36+safeJsonParse a = (Just <$> jsonParse a) `JS.catch` \(_ :: SomeException) -> return Nothing
37+
38+jsonParse :: JSString -> JSM JSVal
39+jsonParse a = JS.jsg "JSON" ^. JS.js1 "parse" a
reflex-dom-core/src/Reflex/Dom/WebSocket.hs−40
@@ -41,33 +41,16 @@ import Control.Lens
4141import Control.Monad hiding (forM, forM_, mapM, mapM_, sequence)
4242import Control.Monad.IO.Class
4343import Control.Monad.State
44−import Data.Aeson hiding (json)
4544import Data.ByteString (ByteString)
4645import Data.Default
4746import Data.IORef
48−import Data.JSString (JSString)
4947import Data.Maybe (isJust)
5048import Data.Text
5149import Data.Text.Encoding
5250import GHCJS.DOM.Types (runJSM, askJSM, MonadJSM, liftJSM, JSM)
5351import GHCJS.Marshal
54−import qualified Language.Javascript.JSaddle as JS (jsg, js1)
5552import qualified Language.Javascript.JSaddle.Monad as JS (catch)
5653
57−#ifdef ghcjs_HOST_OS
58−import GHCJS.DOM.Types ()
59−import System.IO.Unsafe
60−#else
61−import Data.JSString.Text
62−import qualified Data.ByteString.Lazy as LBS
63−#endif
64−-- When on ghcjs and using packages with jsstring patches it removes the FromJSVal
65−-- instance for Value from ghcjs-base. This makes it so that if the patches
66−-- are used then the instance comes from ghcjs-json
67−#if defined(ghcjs_HOST_OS) && defined(USE_TEXT_JSSTRING)
68−import JavaScript.JSON.Types.FromJSVal ()
69−#endif
70−
7154data WebSocketConfig t a
7255 = WebSocketConfig { _webSocketConfig_send :: Event t [a]
7356 , _webSocketConfig_close :: Event t (Word, Text)
@@ -145,29 +128,6 @@ webSocket' url config onRawMessage = do
145128textWebSocket :: (MonadJSM m, MonadJSM (Performable m), HasJSContext m, PostBuild t m, TriggerEvent t m, PerformEvent t m, MonadHold t m, Reflex t) => Text -> WebSocketConfig t Text -> m (RawWebSocket t Text)
146129textWebSocket url cfg = webSocket' url cfg (either (return . decodeUtf8) fromJSValUnchecked)
147130
148−-- | Deserialize a JSON value from a JSString.
149−-- When on ghcjs it uses JSON.parse which is usually faster than using aeson's decode to get a Value
150−-- When on ghc the JSString is converted to Text and then to ByteString in order to use aeson's decode
151−jsonDecode :: FromJSON a => JSString -> Maybe a
152−jsonDecode t = do
153−#ifdef ghcjs_HOST_OS
154− result <- unsafePerformIO $ handle (\(_ :: SomeException) -> pure Nothing) $ do
155− safeJsonParse t >>= \case
156− Nothing -> pure Nothing
157− Just a -> fromJSVal a
158− case fromJSON result of
159− Success a -> pure a
160− Error _ -> Nothing
161−#else
162− decode $ LBS.fromStrict $ encodeUtf8 $ textFromJSString t
163−#endif
164−
165−safeJsonParse :: JSString -> JSM (Maybe JSVal)
166−safeJsonParse a = (Just <$> jsonParse a) `JS.catch` \(_ :: SomeException) -> return Nothing
167−
168−jsonParse :: JSString -> JSM JSVal
169−jsonParse a = JS.jsg "JSON" ^. JS.js1 "parse" a
170−
171131#ifdef USE_TEMPLATE_HASKELL
172132makeLensesWith (lensRules & simpleLenses .~ True) ''WebSocketConfig
173133makeLensesWith (lensRules & simpleLenses .~ True) ''RawWebSocket