on master help sign in
Include ghcjs-base compatible modules

Adds GHC implementations of GHCJS.Marshal, JavaScript.Array.Internal and JavaScript.Object.Internal. Most of the default PFromJSVal and PToJSVal instances cannot be implemented (because we need to know the JS context), but there are many instances in ghcjs-dom that are. Also adds modules like Language.Javascript.JSaddle.Array and .Foreign. These are not quite the same as the ghcjs-base any ghcjs-base modules because they have some IO versions instead of pure ones.

commit9ea9b917bfeaca71e3d0b914d0bcce28f241aff6 authorHamish Mackenzie <Hamish.K.Mackenzie@googlemail.com> dateThu 24 Nov 2016, 02:13 (10 years ago) parentbfb639e
27 files changed+1276−282
.gitignore+1 jsaddle-warp/jsaddle-warp.cabal+2−2 jsaddle-wkwebview/jsaddle-wkwebview.cabal+2−2 jsaddle-wkwebview/src/Language/Javascript/JSaddle/WKWebView.hs+2−2 jsaddle/jsaddle.cabal+22−4 jsaddle/src-ghc/GHCJS/Marshal.hs+168 jsaddle/src-ghc/GHCJS/Marshal/Internal.hs+248 jsaddle/src-ghc/GHCJS/Marshal/Pure.hs+20 jsaddle/src-ghc/JavaScript/Array/Internal.hs+46 jsaddle/src-ghc/JavaScript/Object/Internal.hs+49 jsaddle/src/Language/Javascript/JSaddle.hs+3−1 jsaddle/src/Language/Javascript/JSaddle/Arguments.hs+3−13 jsaddle/src/Language/Javascript/JSaddle/Array.hs+121 jsaddle/src/Language/Javascript/JSaddle/Classes.hs+15−23 jsaddle/src/Language/Javascript/JSaddle/Classes/Internal.hs+41 jsaddle/src/Language/Javascript/JSaddle/Evaluate.hs+2−3 jsaddle/src/Language/Javascript/JSaddle/Foreign.hs+99 jsaddle/src/Language/Javascript/JSaddle/Marshal/String.hs+32 jsaddle/src/Language/Javascript/JSaddle/Native.hs+3−47 jsaddle/src/Language/Javascript/JSaddle/Native/Internal.hs+64 jsaddle/src/Language/Javascript/JSaddle/Object.hs+25−64 jsaddle/src/Language/Javascript/JSaddle/Properties.hs+11−29 jsaddle/src/Language/Javascript/JSaddle/Run.hs+1−1 jsaddle/src/Language/Javascript/JSaddle/Run/Files.hs+75 jsaddle/src/Language/Javascript/JSaddle/String.hs+10−11 jsaddle/src/Language/Javascript/JSaddle/Types.hs+51−4 jsaddle/src/Language/Javascript/JSaddle/Value.hs+160−76
.gitignore+1
@@ -8,3 +8,4 @@ cabal-dev
88*.lkshf
99/dist-newstyle/
1010/.stack-work/
11+*.project.local
jsaddle-warp/jsaddle-warp.cabal+2−2
@@ -1,5 +1,5 @@
11name: jsaddle-warp
2−version: 0.6.0.1
2+version: 0.7.0.0
33cabal-version: >=1.10
44build-type: Simple
55license: MIT
@@ -27,7 +27,7 @@ library
2727 aeson >=0.8.0.2 && <1.1,
2828 containers >=0.5.6.2 && <0.6,
2929 http-types >=0.8.6 && <0.10,
30− jsaddle >=0.6.0.0 && <0.7,
30+ jsaddle >=0.7.0.0 && <0.8,
3131 stm >=2.4.4 && <2.5,
3232 text >=1.2.1.3 && <1.3,
3333 time >=1.5.0.1 && <1.7,
jsaddle-wkwebview/jsaddle-wkwebview.cabal+2−2
@@ -1,5 +1,5 @@
11name: jsaddle-wkwebview
2−version: 0.6.0.0
2+version: 0.7.0.0
33cabal-version: >=1.10
44build-type: Simple
55license: MIT
@@ -25,7 +25,7 @@ library
2525 aeson >=0.8.0.2 && <1.1,
2626 base <5,
2727 bytestring >=0.10.6.0 && <0.11,
28− jsaddle >= 0.6.0.0 && <0.7
28+ jsaddle >= 0.7.0.0 && <0.8
2929 default-language: Haskell2010
3030 hs-source-dirs: src
3131 ghc-options: -ferror-spans -Wall
jsaddle-wkwebview/src/Language/Javascript/JSaddle/WKWebView.hs+2−2
@@ -18,7 +18,7 @@ import Foreign.StablePtr (StablePtr, newStablePtr, deRefStablePtr)
1818
1919import Language.Javascript.JSaddle (Result, JSM)
2020import Language.Javascript.JSaddle.Run (runJavaScript)
21−import Language.Javascript.JSaddle.Run.Files (initState, runBatch)
21+import Language.Javascript.JSaddle.Run.Files (initState, runBatch, ghcjsHelpers)
2222
2323newtype WKWebView = WKWebView (Ptr WKWebView)
2424
@@ -54,7 +54,7 @@ jsaddleResult ptrHandler s = do
5454 Just r -> processResult r
5555
5656jsaddleJs :: ByteString
57−jsaddleJs = "\
57+jsaddleJs = ghcjsHelpers <> "\
5858 \runJSaddleBatch = (function() {\n\
5959 \ " <> initState <> "\n\
6060 \ return function(batch) {\n\
jsaddle/jsaddle.cabal+22−4
@@ -1,5 +1,5 @@
11name: jsaddle
2−version: 0.6.0.1
2+version: 0.7.0.0
33cabal-version: >=1.10
44build-type: Simple
55license: MIT
@@ -26,22 +26,39 @@ library
2626 ghcjs-prim -any
2727 else
2828 build-depends:
29− aeson >=0.8.0.2 && <1.1,
29+ attoparsec >=0.11 && <0.14,
3030 containers >=0.5.6.2 && <0.6,
31+ deepseq >=1.3 && < 1.5,
3132 filepath >=1.4.0.0 && <1.5,
33+ ghc-prim,
3234 http-types >=0.8.6 && <0.10,
3335 process >=1.2.3.0 && <1.5,
3436 ref-tf >=0.4.0.1 && <0.5,
37+ scientific >=0.3 && <0.4,
3538 stm >=2.4.4 && <2.5,
36− time >=1.5.0.1 && <1.7
39+ time >=1.5.0.1 && <1.7,
40+ unordered-containers >=0.2 && <0.3,
41+ vector >=0.10 && <0.12
42+ exposed-modules:
43+ GHCJS.Marshal
44+ GHCJS.Marshal.Internal
45+ GHCJS.Marshal.Pure
46+ JavaScript.Array.Internal
47+ JavaScript.Object.Internal
48+ Language.Javascript.JSaddle.Native
49+ Language.Javascript.JSaddle.Native.Internal
50+ hs-source-dirs: src-ghc
3751 exposed-modules:
3852 Language.Javascript.JSaddle
53+ Language.Javascript.JSaddle.Array
3954 Language.Javascript.JSaddle.Arguments
4055 Language.Javascript.JSaddle.Classes
56+ Language.Javascript.JSaddle.Classes.Internal
4157 Language.Javascript.JSaddle.Evaluate
4258 Language.Javascript.JSaddle.Exception
59+ Language.Javascript.JSaddle.Foreign
60+ Language.Javascript.JSaddle.Marshal.String
4361 Language.Javascript.JSaddle.Monad
44− Language.Javascript.JSaddle.Native
4562 Language.Javascript.JSaddle.Object
4663 Language.Javascript.JSaddle.Properties
4764 Language.Javascript.JSaddle.Run
@@ -50,6 +67,7 @@ library
5067 Language.Javascript.JSaddle.Value
5168 Language.Javascript.JSaddle.Types
5269 build-depends:
70+ aeson >=0.8.0.2 && <1.1,
5371 base <5,
5472 bytestring >=0.10.6.0 && <0.11,
5573 lens >=3.8.5 && <4.16,
jsaddle/src-ghc/GHCJS/Marshal.hsnew file+168
@@ -0,0 +1,168 @@
1+{-# LANGUAGE ScopedTypeVariables,
2+ FlexibleContexts,
3+ FlexibleInstances,
4+ OverloadedStrings,
5+ TupleSections,
6+ LambdaCase #-}
7+{-# OPTIONS_GHC -fno-warn-orphans #-}
8+
9+module GHCJS.Marshal ( FromJSVal(..)
10+ , ToJSVal(..)
11+ , toJSVal_aeson
12+ , toJSVal_pure
13+ ) where
14+
15+import Control.Monad (join)
16+import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
17+
18+import qualified Data.Aeson as AE
19+import Data.Int (Int8, Int16, Int32)
20+import Data.Word (Word8, Word16, Word32, Word)
21+
22+import GHC.Prim
23+
24+import Language.Javascript.JSaddle.Types (JSM, JSVal, SomeJSArray(..), Command(ValueToJSONValue), Result(ValueToJSONValueResult))
25+import Language.Javascript.JSaddle.Native (withToJSVal)
26+import Language.Javascript.JSaddle.Run(sendCommand)
27+import GHCJS.Marshal.Internal
28+import GHCJS.Marshal.Pure ()
29+import Language.Javascript.JSaddle.Value (isUndefinedIO, valToNumber,
30+ valToBool, valMakeJSON)
31+import Language.Javascript.JSaddle.Array (fromListIO)
32+import qualified Language.Javascript.JSaddle.Array as A (read)
33+
34+instance FromJSVal JSVal where
35+ fromJSValUnchecked x = return x
36+ {-# INLINE fromJSValUnchecked #-}
37+ fromJSVal = return . Just
38+ {-# INLINE fromJSVal #-}
39+instance FromJSVal () where
40+ fromJSValUnchecked = fromJSValUnchecked_pure
41+ {-# INLINE fromJSValUnchecked #-}
42+ fromJSVal = fromJSVal_pure
43+-- {-# INLINE fromJSVal #-}
44+instance FromJSVal Bool where
45+ fromJSValUnchecked = valToBool
46+ {-# INLINE fromJSValUnchecked #-}
47+ fromJSVal = fmap Just . valToBool
48+ {-# INLINE fromJSVal #-}
49+instance FromJSVal Int where
50+ fromJSValUnchecked = fmap round . valToNumber
51+ {-# INLINE fromJSValUnchecked #-}
52+ fromJSVal = fmap (Just . round) . valToNumber
53+ {-# INLINE fromJSVal #-}
54+instance FromJSVal Int8 where
55+ fromJSValUnchecked = fmap round . valToNumber
56+ {-# INLINE fromJSValUnchecked #-}
57+ fromJSVal = fmap (Just . round) . valToNumber
58+ {-# INLINE fromJSVal #-}
59+instance FromJSVal Int16 where
60+ fromJSValUnchecked = fmap round . valToNumber
61+ {-# INLINE fromJSValUnchecked #-}
62+ fromJSVal = fmap (Just . round) . valToNumber
63+ {-# INLINE fromJSVal #-}
64+instance FromJSVal Int32 where
65+ fromJSValUnchecked = fmap round . valToNumber
66+ {-# INLINE fromJSValUnchecked #-}
67+ fromJSVal = fmap (Just . round) . valToNumber
68+ {-# INLINE fromJSVal #-}
69+instance FromJSVal Word where
70+ fromJSValUnchecked = fmap round . valToNumber
71+ {-# INLINE fromJSValUnchecked #-}
72+ fromJSVal = fmap (Just . round) . valToNumber
73+ {-# INLINE fromJSVal #-}
74+instance FromJSVal Word8 where
75+ fromJSValUnchecked = fmap round . valToNumber
76+ {-# INLINE fromJSValUnchecked #-}
77+ fromJSVal = fmap (Just . round) . valToNumber
78+ {-# INLINE fromJSVal #-}
79+instance FromJSVal Word16 where
80+ fromJSValUnchecked = fmap round . valToNumber
81+ {-# INLINE fromJSValUnchecked #-}
82+ fromJSVal = fmap (Just . round) . valToNumber
83+ {-# INLINE fromJSVal #-}
84+instance FromJSVal Word32 where
85+ fromJSValUnchecked = fmap round . valToNumber
86+ {-# INLINE fromJSValUnchecked #-}
87+ fromJSVal = fmap (Just . round) . valToNumber
88+ {-# INLINE fromJSVal #-}
89+instance FromJSVal Float where
90+ fromJSValUnchecked = fmap realToFrac . valToNumber
91+ {-# INLINE fromJSValUnchecked #-}
92+ fromJSVal = fmap (Just . realToFrac) . valToNumber
93+ {-# INLINE fromJSVal #-}
94+instance FromJSVal Double where
95+ fromJSValUnchecked = valToNumber
96+ {-# INLINE fromJSValUnchecked #-}
97+ fromJSVal = fmap Just . valToNumber
98+ {-# INLINE fromJSVal #-}
99+instance FromJSVal AE.Value where
100+ fromJSVal r =
101+ withToJSVal r $ \rval -> do
102+ ValueToJSONValueResult result <- sendCommand (ValueToJSONValue rval)
103+ return $ Just result
104+ {-# INLINE fromJSVal #-}
105+instance (FromJSVal a, FromJSVal b) => FromJSVal (a,b) where
106+ fromJSVal r = runMaybeT $ (,) <$> jf r 0 <*> jf r 1
107+ {-# INLINE fromJSVal #-}
108+instance (FromJSVal a, FromJSVal b, FromJSVal c) => FromJSVal (a,b,c) where
109+ fromJSVal r = runMaybeT $ (,,) <$> jf r 0 <*> jf r 1 <*> jf r 2
110+ {-# INLINE fromJSVal #-}
111+instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d) => FromJSVal (a,b,c,d) where
112+ fromJSVal r = runMaybeT $ (,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3
113+ {-# INLINE fromJSVal #-}
114+instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d, FromJSVal e) => FromJSVal (a,b,c,d,e) where
115+ fromJSVal r = runMaybeT $ (,,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3 <*> jf r 4
116+ {-# INLINE fromJSVal #-}
117+instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d, FromJSVal e, FromJSVal f) => FromJSVal (a,b,c,d,e,f) where
118+ fromJSVal r = runMaybeT $ (,,,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3 <*> jf r 4 <*> jf r 5
119+ {-# INLINE fromJSVal #-}
120+instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d, FromJSVal e, FromJSVal f, FromJSVal g) => FromJSVal (a,b,c,d,e,f,g) where
121+ fromJSVal r = runMaybeT $ (,,,,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3 <*> jf r 4 <*> jf r 5 <*> jf r 6
122+ {-# INLINE fromJSVal #-}
123+instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d, FromJSVal e, FromJSVal f, FromJSVal g, FromJSVal h) => FromJSVal (a,b,c,d,e,f,g,h) where
124+ fromJSVal r = runMaybeT $ (,,,,,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3 <*> jf r 4 <*> jf r 5 <*> jf r 6 <*> jf r 7
125+ {-# INLINE fromJSVal #-}
126+
127+jf :: FromJSVal a => JSVal -> Int -> MaybeT JSM a
128+jf r n = MaybeT $ do
129+ r' <- A.read n (SomeJSArray r)
130+ isUndefinedIO r >>= \case
131+ True -> return Nothing
132+ False -> fromJSVal r'
133+
134+instance (ToJSVal a, ToJSVal b) => ToJSVal (a,b) where
135+ toJSVal (a,b) = join $ arr2 <$> toJSVal a <*> toJSVal b
136+ {-# INLINE toJSVal #-}
137+instance (ToJSVal a, ToJSVal b, ToJSVal c) => ToJSVal (a,b,c) where
138+ toJSVal (a,b,c) = join $ arr3 <$> toJSVal a <*> toJSVal b <*> toJSVal c
139+ {-# INLINE toJSVal #-}
140+instance (ToJSVal a, ToJSVal b, ToJSVal c, ToJSVal d) => ToJSVal (a,b,c,d) where
141+ toJSVal (a,b,c,d) = join $ arr4 <$> toJSVal a <*> toJSVal b <*> toJSVal c <*> toJSVal d
142+ {-# INLINE toJSVal #-}
143+instance (ToJSVal a, ToJSVal b, ToJSVal c, ToJSVal d, ToJSVal e) => ToJSVal (a,b,c,d,e) where
144+ toJSVal (a,b,c,d,e) = join $ arr5 <$> toJSVal a <*> toJSVal b <*> toJSVal c <*> toJSVal d <*> toJSVal e
145+ {-# INLINE toJSVal #-}
146+instance (ToJSVal a, ToJSVal b, ToJSVal c, ToJSVal d, ToJSVal e, ToJSVal f) => ToJSVal (a,b,c,d,e,f) where
147+ toJSVal (a,b,c,d,e,f) = join $ arr6 <$> toJSVal a <*> toJSVal b <*> toJSVal c <*> toJSVal d <*> toJSVal e <*> toJSVal f
148+ {-# INLINE toJSVal #-}
149+instance (ToJSVal a, ToJSVal b, ToJSVal c, ToJSVal d, ToJSVal e, ToJSVal f, ToJSVal g) => ToJSVal (a,b,c,d,e,f,g) where
150+ toJSVal (a,b,c,d,e,f,g) = join $ arr7 <$> toJSVal a <*> toJSVal b <*> toJSVal c <*> toJSVal d <*> toJSVal e <*> toJSVal f <*> toJSVal g
151+ {-# INLINE toJSVal #-}
152+
153+arr2 :: JSVal -> JSVal -> JSM JSVal
154+arr2 a b = coerce <$> fromListIO [a,b]
155+arr3 :: JSVal -> JSVal -> JSVal -> JSM JSVal
156+arr3 a b c = coerce <$> fromListIO [a,b,c]
157+arr4 :: JSVal -> JSVal -> JSVal -> JSVal -> JSM JSVal
158+arr4 a b c d = coerce <$> fromListIO [a,b,c,d]
159+arr5 :: JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSM JSVal
160+arr5 a b c d e = coerce <$> fromListIO [a,b,c,d,e]
161+arr6 :: JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSM JSVal
162+arr6 a b c d e f = coerce <$> fromListIO [a,b,c,d,e,f]
163+arr7 :: JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSM JSVal
164+arr7 a b c d e f g = coerce <$> fromListIO [a,b,c,d,e,f,g]
165+
166+toJSVal_aeson :: AE.ToJSON a => a -> JSM JSVal
167+toJSVal_aeson = valMakeJSON . AE.toJSON
168+
jsaddle/src-ghc/GHCJS/Marshal/Internal.hsnew file+248
@@ -0,0 +1,248 @@
1+{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable, DefaultSignatures,
2+ TypeOperators, TupleSections, FlexibleContexts, FlexibleInstances,
3+ LambdaCase
4+ #-}
5+
6+module GHCJS.Marshal.Internal (
7+ FromJSVal(..)
8+ , ToJSVal(..)
9+ , PToJSVal(..)
10+ , PFromJSVal(..)
11+ , Purity(..)
12+ , toJSVal_generic
13+ , fromJSVal_generic
14+ , toJSVal_pure
15+ , fromJSVal_pure
16+ , fromJSValUnchecked_pure
17+ ) where
18+
19+import Control.Monad
20+
21+import Data.Data
22+import Data.Maybe
23+import Data.Coerce (coerce)
24+import qualified Data.Text as T (pack)
25+
26+import GHC.Generics
27+
28+import Language.Javascript.JSaddle.Types (JSM, JSVal, SomeJSArray(..), MutableJSArray, JSString)
29+import Language.Javascript.JSaddle.Foreign (jsNull, jsTrue, isUndefinedIO)
30+import Language.Javascript.JSaddle.String (textToStr)
31+import qualified JavaScript.Object.Internal as OI (Object(..), create, setProp, getProp)
32+import qualified JavaScript.Array.Internal as AI (create, push, read, fromListIO, toListIO)
33+
34+data Purity = PureShared -- ^ conversion is pure even if the original value is shared
35+ | PureExclusive -- ^ conversion is pure if the we only convert once
36+ deriving (Eq, Ord, Typeable, Data)
37+
38+class PToJSVal a where
39+-- type PureOut a :: Purity
40+ pToJSVal :: a -> JSVal
41+
42+class PFromJSVal a where
43+-- type PureIn a :: Purity
44+ pFromJSVal :: JSVal -> a
45+
46+class ToJSVal a where
47+ toJSVal :: a -> JSM JSVal
48+
49+ toJSValListOf :: [a] -> JSM JSVal
50+ toJSValListOf = fmap coerce . AI.fromListIO <=< mapM toJSVal
51+
52+ default toJSVal :: (Generic a, GToJSVal (Rep a ())) => a -> JSM JSVal
53+ toJSVal = toJSVal_generic id
54+
55+class FromJSVal a where
56+ fromJSVal :: JSVal -> JSM (Maybe a)
57+
58+ fromJSValUnchecked :: JSVal -> JSM a
59+ fromJSValUnchecked = fmap fromJust . fromJSVal
60+ {-# INLINE fromJSValUnchecked #-}
61+
62+ fromJSValListOf :: JSVal -> JSM (Maybe [a])
63+ fromJSValListOf = fmap sequence . (mapM fromJSVal <=< AI.toListIO . coerce) -- fixme should check that it's an array
64+
65+ fromJSValUncheckedListOf :: JSVal -> JSM [a]
66+ fromJSValUncheckedListOf = mapM fromJSValUnchecked <=< AI.toListIO . coerce
67+
68+ default fromJSVal :: (Generic a, GFromJSVal (Rep a ())) => JSVal -> JSM (Maybe a)
69+ fromJSVal = fromJSVal_generic id
70+
71+-- -----------------------------------------------------------------------------
72+
73+class GToJSVal a where
74+ gToJSVal :: (String -> String) -> Bool -> a -> JSM JSVal
75+
76+class GToJSProp a where
77+ gToJSProp :: (String -> String) -> JSVal -> a -> JSM ()
78+
79+class GToJSArr a where
80+ gToJSArr :: (String -> String) -> MutableJSArray -> a -> JSM ()
81+
82+instance (ToJSVal b) => GToJSVal (K1 a b c) where
83+ gToJSVal _ _ (K1 x) = toJSVal x
84+
85+instance GToJSVal p => GToJSVal (Par1 p) where
86+ gToJSVal f b (Par1 p) = gToJSVal f b p
87+
88+instance GToJSVal (f p) => GToJSVal (Rec1 f p) where
89+ gToJSVal f b (Rec1 x) = gToJSVal f b x
90+
91+instance (GToJSVal (a p), GToJSVal (b p)) => GToJSVal ((a :+: b) p) where
92+ gToJSVal f _ (L1 x) = gToJSVal f True x
93+ gToJSVal f _ (R1 x) = gToJSVal f True x
94+
95+instance (GToJSVal (a p)) => GToJSVal (M1 D c a p) where
96+ gToJSVal f b (M1 x) = gToJSVal f b x
97+
98+instance (Constructor c, GToJSVal (a p)) => GToJSVal (M1 C c a p) where
99+ gToJSVal f True m@(M1 x) = do
100+ obj@(OI.Object obj') <- OI.create
101+ v <- gToJSVal f (conIsRecord m) x
102+ OI.setProp (packJSS . f $ conName m) v obj
103+ return obj'
104+ gToJSVal f _ m@(M1 x) = gToJSVal f (conIsRecord m) x
105+
106+instance (GToJSArr (a p), GToJSArr (b p), GToJSProp (a p), GToJSProp (b p)) => GToJSVal ((a :*: b) p) where
107+ gToJSVal f True xy = do
108+ (OI.Object obj') <- OI.create
109+ gToJSProp f obj' xy
110+ return obj'
111+ gToJSVal f False xy = do
112+ arr@(SomeJSArray arr') <- AI.create
113+ gToJSArr f arr xy
114+ return arr'
115+
116+instance GToJSVal (a p) => GToJSVal (M1 S c a p) where
117+ gToJSVal f b (M1 x) = gToJSVal f b x
118+
119+instance (GToJSProp (a p), GToJSProp (b p)) => GToJSProp ((a :*: b) p) where
120+ gToJSProp f o (x :*: y) = gToJSProp f o x >> gToJSProp f o y
121+
122+instance (Selector c, GToJSVal (a p)) => GToJSProp (M1 S c a p) where
123+ gToJSProp f o m@(M1 x) = do
124+ r <- gToJSVal f False x
125+ OI.setProp (packJSS . f $ selName m) r (OI.Object o)
126+
127+instance (GToJSArr (a p), GToJSArr (b p)) => GToJSArr ((a :*: b) p) where
128+ gToJSArr f a (x :*: y) = gToJSArr f a x >> gToJSArr f a y
129+
130+instance GToJSVal (a p) => GToJSArr (M1 S c a p) where
131+ gToJSArr f a (M1 x) = do
132+ r <- gToJSVal f False x
133+ AI.push r a
134+
135+instance GToJSVal (V1 p) where
136+ gToJSVal _ _ _ = return jsNull
137+
138+instance GToJSVal (U1 p) where
139+ gToJSVal _ _ _ = return jsTrue
140+
141+toJSVal_generic :: forall a . (Generic a, GToJSVal (Rep a ()))
142+ => (String -> String) -> a -> JSM JSVal
143+toJSVal_generic f x = gToJSVal f False (from x :: Rep a ())
144+
145+-- -----------------------------------------------------------------------------
146+
147+class GFromJSVal a where
148+ gFromJSVal :: (String -> String) -> Bool -> JSVal -> JSM (Maybe a)
149+
150+class GFromJSProp a where
151+ gFromJSProp :: (String -> String) -> JSVal -> JSM (Maybe a)
152+
153+class GFromJSArr a where
154+ gFromJSArr :: (String -> String) -> MutableJSArray -> Int -> JSM (Maybe (a,Int))
155+
156+instance FromJSVal b => GFromJSVal (K1 a b c) where
157+ gFromJSVal _ _ r = fmap K1 <$> fromJSVal r
158+
159+instance GFromJSVal p => GFromJSVal (Par1 p) where
160+ gFromJSVal f b r = gFromJSVal f b r
161+
162+instance GFromJSVal (f p) => GFromJSVal (Rec1 f p) where
163+ gFromJSVal f b r = gFromJSVal f b r
164+
165+instance (GFromJSVal (a p), GFromJSVal (b p)) => GFromJSVal ((a :+: b) p) where
166+ gFromJSVal f _b r = do
167+ l <- gFromJSVal f True r
168+ case l of
169+ Just x -> return (L1 <$> Just x)
170+ Nothing -> fmap R1 <$> gFromJSVal f True r
171+
172+instance GFromJSVal (a p) => GFromJSVal (M1 D c a p) where
173+ gFromJSVal f b r = fmap M1 <$> gFromJSVal f b r
174+
175+instance forall c a p . (Constructor c, GFromJSVal (a p)) => GFromJSVal (M1 C c a p) where
176+ gFromJSVal f True r = do
177+ r' <- OI.getProp (packJSS . f $ conName (undefined :: M1 C c a p)) (OI.Object r)
178+ isUndefinedIO r' >>= \case
179+ True -> return Nothing
180+ False -> fmap M1 <$> gFromJSVal f (conIsRecord (undefined :: M1 C c a p)) r'
181+ gFromJSVal f _ r = fmap M1 <$> gFromJSVal f (conIsRecord (undefined :: M1 C c a p)) r
182+
183+instance (GFromJSArr (a p), GFromJSArr (b p), GFromJSProp (a p), GFromJSProp (b p)) => GFromJSVal ((a :*: b) p) where
184+ gFromJSVal f True r = gFromJSProp f r
185+ gFromJSVal f False r = fmap fst <$> gFromJSArr f (SomeJSArray r) 0
186+
187+instance GFromJSVal (a p) => GFromJSVal (M1 S c a p) where
188+ gFromJSVal f b r = fmap M1 <$> gFromJSVal f b r
189+
190+instance (GFromJSProp (a p), GFromJSProp (b p)) => GFromJSProp ((a :*: b) p) where
191+ gFromJSProp f r = do
192+ a <- gFromJSProp f r
193+ case a of
194+ Nothing -> return Nothing
195+ Just a' -> fmap (a':*:) <$> gFromJSProp f r
196+
197+instance forall c a p . (Selector c, GFromJSVal (a p)) => GFromJSProp (M1 S c a p) where
198+ gFromJSProp f o = do
199+ p <- OI.getProp (packJSS . f $ selName (undefined :: M1 S c a p)) (OI.Object o)
200+ isUndefinedIO p >>= \case
201+ True -> return Nothing
202+ False -> fmap M1 <$> gFromJSVal f False p
203+
204+instance (GFromJSArr (a p), GFromJSArr (b p)) => GFromJSArr ((a :*: b) p) where
205+ gFromJSArr f r _n = do
206+ a <- gFromJSArr f r 0
207+ case a of
208+ Just (a',an) -> do
209+ b <- gFromJSArr f r an
210+ case b of
211+ Just (b',bn) -> return (Just (a' :*: b',bn))
212+ _ -> return Nothing
213+
214+instance (GFromJSVal (a p)) => GFromJSArr (M1 S c a p) where
215+ gFromJSArr f o n = do
216+ r <- AI.read n o
217+ isUndefinedIO r >>= \case
218+ True -> return Nothing
219+ False -> fmap ((,n+1) . M1) <$> gFromJSVal f False r
220+
221+instance GFromJSVal (V1 p) where
222+ gFromJSVal _ _ _ = return Nothing
223+
224+instance GFromJSVal (U1 p) where
225+ gFromJSVal _ _ _ = return (Just U1)
226+
227+fromJSVal_generic :: forall a . (Generic a, GFromJSVal (Rep a ()))
228+ => (String -> String) -> JSVal -> JSM (Maybe a)
229+fromJSVal_generic f x = fmap to <$> (gFromJSVal f False x :: JSM (Maybe (Rep a ())))
230+
231+-- -----------------------------------------------------------------------------
232+
233+fromJSVal_pure :: PFromJSVal a => JSVal -> JSM (Maybe a)
234+fromJSVal_pure x = return (Just (pFromJSVal x))
235+{-# INLINE fromJSVal_pure #-}
236+
237+fromJSValUnchecked_pure :: PFromJSVal a => JSVal -> JSM a
238+fromJSValUnchecked_pure x = return (pFromJSVal x)
239+{-# INLINE fromJSValUnchecked_pure #-}
240+
241+toJSVal_pure :: PToJSVal a => a -> JSM JSVal
242+toJSVal_pure x = return (pToJSVal x)
243+{-# INLINE toJSVal_pure #-}
244+
245+-- -----------------------------------------------------------------------------
246+
247+packJSS :: String -> JSString
248+packJSS = textToStr . T.pack
jsaddle/src-ghc/GHCJS/Marshal/Pure.hsnew file+20
@@ -0,0 +1,20 @@
1+{-# OPTIONS_GHC -fno-warn-orphans #-}
2+module GHCJS.Marshal.Pure
3+ ( PFromJSVal(..)
4+ , PToJSVal(..)
5+ ) where
6+
7+import GHCJS.Marshal.Internal
8+import Language.Javascript.JSaddle.Types (JSVal(..))
9+import Language.Javascript.JSaddle.Foreign (jsFalse, jsTrue)
10+
11+instance PFromJSVal JSVal where pFromJSVal = id
12+ {-# INLINE pFromJSVal #-}
13+instance PFromJSVal () where pFromJSVal _ = ()
14+ {-# INLINE pFromJSVal #-}
15+
16+instance PToJSVal JSVal where pToJSVal = id
17+ {-# INLINE pToJSVal #-}
18+instance PToJSVal Bool where pToJSVal True = jsTrue
19+ pToJSVal False = jsFalse
20+ {-# INLINE pToJSVal #-}
jsaddle/src-ghc/JavaScript/Array/Internal.hsnew file+46
@@ -0,0 +1,46 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module JavaScript.Array.Internal
3+ ( create
4+ , fromListIO
5+ , toListIO
6+ , read
7+ , push
8+ ) where
9+
10+import Prelude hiding(read)
11+import Control.Monad (void)
12+import Language.Javascript.JSaddle.Types (JSM, JSVal, SomeJSArray(..), MutableJSArray, Object(..), JSString(..))
13+import Language.Javascript.JSaddle.Native.Internal
14+ (withObject, withJSVal, withJSString, withJSVals)
15+import Language.Javascript.JSaddle.Run
16+ (Command(..), Result(..), AsyncCommand(..), sendCommand, sendLazyCommand)
17+
18+create :: JSM MutableJSArray
19+create = SomeJSArray <$> sendLazyCommand (NewArray [])
20+{-# INLINE create #-}
21+
22+fromListIO :: [JSVal] -> JSM (SomeJSArray m)
23+fromListIO xs = withJSVals xs $ \xs' -> SomeJSArray <$> sendLazyCommand (NewArray xs')
24+{-# INLINE fromListIO #-}
25+
26+toListIO :: SomeJSArray m -> JSM [JSVal]
27+toListIO (SomeJSArray x) =
28+ withObject (Object x) $ \this -> do
29+ l <- withJSString (JSString "length") $ sendLazyCommand . GetPropertyByName this
30+ withJSVal l $ \l' -> do
31+ ValueToNumberResult len <- sendCommand (ValueToNumber l')
32+ mapM (sendLazyCommand . GetPropertyAtIndex this) [0..round len - 1]
33+{-# INLINE toListIO #-}
34+
35+read :: Int -> SomeJSArray m -> JSM JSVal
36+read n (SomeJSArray x) =
37+ withObject (Object x) $ \this -> sendLazyCommand $ GetPropertyAtIndex this n
38+{-# INLINE read #-}
39+
40+push :: JSVal -> MutableJSArray -> JSM ()
41+push e (SomeJSArray x) =
42+ void $ withJSVal e $ \e' ->
43+ withObject (Object x) $ \this -> do
44+ f <- withJSString (JSString "push") $ sendLazyCommand . GetPropertyByName this
45+ withObject (Object f) $ \f' -> sendLazyCommand $ CallAsFunction f' this [e']
46+{-# INLINE push #-}
jsaddle/src-ghc/JavaScript/Object/Internal.hsnew file+49
@@ -0,0 +1,49 @@
1+module JavaScript.Object.Internal
2+ ( Object(..)
3+ , create
4+-- , allProps
5+ , listProps
6+ , getProp
7+ , unsafeGetProp
8+ , setProp
9+ , unsafeSetProp
10+-- , isInstanceOfIO
11+ ) where
12+
13+import Language.Javascript.JSaddle.Types (JSM, JSVal, Object(..), JSString)
14+import Language.Javascript.JSaddle.Native.Internal
15+ (withObject, withJSString, withJSVal, wrapJSString)
16+import Language.Javascript.JSaddle.Run
17+ (Command(..), AsyncCommand(..), Result(..), sendCommand, sendLazyCommand, sendAsyncCommand)
18+
19+create :: JSM Object
20+create = Object <$> sendLazyCommand NewEmptyObject
21+
22+listProps :: Object -> JSM [JSString]
23+listProps this =
24+ withObject this $ \rthis -> do
25+ PropertyNamesResult result <- sendCommand $ PropertyNames rthis
26+ mapM wrapJSString result
27+{-# INLINE listProps #-}
28+
29+unsafeGetProp :: JSString -> Object -> JSM JSVal
30+unsafeGetProp name this =
31+ withObject this $ \rthis ->
32+ withJSString name $ sendLazyCommand . GetPropertyByName rthis
33+{-# INLINE unsafeGetProp #-}
34+
35+getProp :: JSString -> Object -> JSM JSVal
36+getProp = unsafeGetProp
37+{-# INLINE getProp #-}
38+
39+unsafeSetProp :: JSString -> JSVal -> Object -> JSM ()
40+unsafeSetProp name val this =
41+ withObject this $ \rthis ->
42+ withJSString name $ \rname ->
43+ withJSVal val $ \rval ->
44+ sendAsyncCommand $ SetPropertyByName rthis rname rval
45+{-# INLINE unsafeSetProp #-}
46+
47+setProp :: JSString -> JSVal -> Object -> JSM ()
48+setProp = unsafeSetProp
49+{-# INLINE setProp #-}
jsaddle/src/Language/Javascript/JSaddle.hs+3−1
@@ -64,12 +64,14 @@ module Language.Javascript.JSaddle (
6464 module JSaddle
6565) where
6666
67+import GHCJS.Marshal as JSaddle
6768import Language.Javascript.JSaddle.Types as JSaddle
6869import Language.Javascript.JSaddle.Classes as JSaddle
70+import Language.Javascript.JSaddle.Marshal.String as JSaddle ()
6971import Language.Javascript.JSaddle.Monad as JSaddle
7072import Language.Javascript.JSaddle.Exception as JSaddle
7173import Language.Javascript.JSaddle.Value as JSaddle
72−import Language.Javascript.JSaddle.Arguments as JSaddle
74+import Language.Javascript.JSaddle.Arguments as JSaddle ()
7375import Language.Javascript.JSaddle.Properties as JSaddle
7476import Language.Javascript.JSaddle.Object as JSaddle
7577import Language.Javascript.JSaddle.Evaluate as JSaddle
jsaddle/src/Language/Javascript/JSaddle/Arguments.hs+3−13
@@ -1,5 +1,6 @@
11{-# LANGUAGE FlexibleInstances #-}
22{-# LANGUAGE TypeSynonymInstances #-}
3+{-# OPTIONS_GHC -fno-warn-orphans #-}
34-----------------------------------------------------------------------------
45--
56-- Module : Language.Javascript.JSaddle.Arguments
@@ -16,18 +17,8 @@ module Language.Javascript.JSaddle.Arguments (
1617 MakeArgs(..)
1718) where
1819
19−import Language.Javascript.JSaddle.Classes
20− (ToJSVal(..))
21−import Language.Javascript.JSaddle.Monad (JSM)
22−import Language.Javascript.JSaddle.Types (JSVal)
23−
24−-- | Anything that can be used to make a list of JavaScript value
25−-- references for use as function arguments
26−class MakeArgs this where
27− makeArgs :: this -> JSM [JSVal]
28−
29−instance MakeArgs arg => MakeArgs (JSM arg) where
30− makeArgs arg = arg >>= makeArgs
20+import Language.Javascript.JSaddle.Classes (MakeArgs(..))
21+import GHCJS.Marshal.Internal (ToJSVal(..))
3122
3223instance ToJSVal arg => MakeArgs [arg] where
3324 makeArgs = mapM toJSVal
@@ -62,7 +53,6 @@ instance (ToJSVal arg1, ToJSVal arg2, ToJSVal arg3, ToJSVal arg4, ToJSVal arg5)
6253 rarg5 <- toJSVal arg5
6354 return [rarg1, rarg2, rarg3, rarg4, rarg5]
6455
65−
6656instance (ToJSVal arg1, ToJSVal arg2, ToJSVal arg3, ToJSVal arg4, ToJSVal arg5, ToJSVal arg6) => MakeArgs (arg1, arg2, arg3, arg4, arg5, arg6) where
6757 makeArgs (arg1, arg2, arg3, arg4, arg5, arg6) = do
6858 rarg1 <- toJSVal arg1
jsaddle/src/Language/Javascript/JSaddle/Array.hsnew file+121
@@ -0,0 +1,121 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE FlexibleInstances #-}
3+{-# LANGUAGE TypeSynonymInstances #-}
4+{-# LANGUAGE ScopedTypeVariables #-}
5+{-# LANGUAGE Rank2Types #-}
6+#ifdef ghcjs_HOST_OS
7+{-# LANGUAGE ForeignFunctionInterface #-}
8+{-# LANGUAGE JavaScriptFFI #-}
9+{-# OPTIONS_GHC -Wno-dodgy-exports -Wno-dodgy-imports #-}
10+#endif
11+{-# OPTIONS_GHC -fno-warn-orphans #-}
12+-----------------------------------------------------------------------------
13+--
14+-- Module : Language.Javascript.JSaddle.Object
15+-- Copyright : (c) Hamish Mackenzie
16+-- License : MIT
17+--
18+-- Maintainer : Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
19+--
20+-- | Interface to JavaScript array
21+--
22+-----------------------------------------------------------------------------
23+
24+module Language.Javascript.JSaddle.Array
25+ ( SomeJSArray(..)
26+ , JSArray
27+ , MutableJSArray
28+ , create
29+ , length
30+ , lengthIO
31+ , nullIO
32+ , fromListIO
33+ , toListIO
34+ , read
35+ , write
36+ , append
37+ , push
38+ , pop
39+ , unshift
40+ , shift
41+ , reverse
42+ , takeIO
43+ , dropIO
44+ , sliceIO
45+ , freeze
46+ , unsafeFreeze
47+ , thaw
48+ , unsafeThaw
49+ ) where
50+
51+import Prelude hiding (read, reverse, null)
52+import Control.Monad (void)
53+import Language.Javascript.JSaddle.Types
54+ (JSM, JSVal, SomeJSArray(..), JSArray,
55+ MutableJSArray)
56+import Control.Lens.Operators ((^.))
57+import Language.Javascript.JSaddle.Object (js2, js0, (##), js1, js)
58+import Language.Javascript.JSaddle.Value (valToNumber)
59+import JavaScript.Array.Internal (create, fromListIO, toListIO, read, push)
60+
61+lengthIO :: SomeJSArray m -> JSM Int
62+lengthIO (SomeJSArray x) = round <$> (x ^. js "length" >>= valToNumber)
63+{-# INLINE lengthIO #-}
64+
65+nullIO :: SomeJSArray m -> JSM Bool
66+nullIO = fmap (== 0) . lengthIO
67+{-# INLINE nullIO #-}
68+
69+append :: SomeJSArray m -> SomeJSArray m -> JSM (SomeJSArray m1)
70+append (SomeJSArray x) (SomeJSArray y) = SomeJSArray <$> x ^. js1 "concat" y
71+{-# INLINE append #-}
72+
73+write :: Int -> JSVal -> MutableJSArray -> JSM ()
74+write n e (SomeJSArray x) = void $ (x ## n) e
75+{-# INLINE write #-}
76+
77+pop :: MutableJSArray -> JSM JSVal
78+pop (SomeJSArray x) = x ^. js0 "pop"
79+{-# INLINE pop #-}
80+
81+unshift :: JSVal -> MutableJSArray -> JSM ()
82+unshift e (SomeJSArray x) = void $ x ^. js1 "unshift" e
83+{-# INLINE unshift #-}
84+
85+shift :: MutableJSArray -> JSM JSVal
86+shift (SomeJSArray x) = x ^. js0 "shift"
87+{-# INLINE shift #-}
88+
89+reverse :: MutableJSArray -> JSM ()
90+reverse (SomeJSArray x) = void $ x ^. js0 "reverse"
91+{-# INLINE reverse #-}
92+
93+takeIO :: Int -> SomeJSArray m -> JSM (SomeJSArray m1)
94+takeIO n (SomeJSArray x) = SomeJSArray <$> x ^. js2 "slice" (0::Int) n
95+{-# INLINE takeIO #-}
96+
97+dropIO :: Int -> SomeJSArray m -> JSM (SomeJSArray m1)
98+dropIO n (SomeJSArray x) = SomeJSArray <$> x ^. js1 "slice1" n
99+{-# INLINE dropIO #-}
100+
101+sliceIO :: Int -> Int -> JSArray -> JSM (SomeJSArray m1)
102+sliceIO s n (SomeJSArray x) = SomeJSArray <$> x ^. js2 "slice" s n
103+{-# INLINE sliceIO #-}
104+
105+freeze :: MutableJSArray -> JSM JSArray
106+freeze (SomeJSArray x) = SomeJSArray <$> x ^. js1 "slice" (0::Int)
107+{-# INLINE freeze #-}
108+
109+unsafeFreeze :: MutableJSArray -> JSM JSArray
110+unsafeFreeze (SomeJSArray x) = pure (SomeJSArray x)
111+{-# INLINE unsafeFreeze #-}
112+
113+thaw :: JSArray -> JSM MutableJSArray
114+thaw (SomeJSArray x) = SomeJSArray <$> x ^. js1 "slice" (0::Int)
115+{-# INLINE thaw #-}
116+
117+unsafeThaw :: JSArray -> JSM MutableJSArray
118+unsafeThaw (SomeJSArray x) = pure (SomeJSArray x)
119+{-# INLINE unsafeThaw #-}
120+
121+
jsaddle/src/Language/Javascript/JSaddle/Classes.hs+15−23
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE FlexibleInstances #-}
23{-# LANGUAGE TypeSynonymInstances #-}
34-----------------------------------------------------------------------------
@@ -16,30 +17,21 @@
1617
1718module Language.Javascript.JSaddle.Classes (
1819 -- * Type classes to convert Haskell data to JavaScript
19− ToJSVal(..)
20+ PToJSVal(..)
21+ , PFromJSVal(..)
22+ , ToJSVal(..)
23+ , FromJSVal(..)
2024 , ToJSString(..)
25+ , FromJSString(..)
2126 , MakeObject(..)
27+ , MakeArgs(..)
2228) where
2329
24−import Language.Javascript.JSaddle.Types
25− (JSM, Object(..), JSString, JSVal)
26−
27−-- | Anything that can be used to make a JavaScript value reference
28−class ToJSVal a where
29− toJSVal :: a -> JSM JSVal
30−
31−-- | Anything that can be used to make a JavaScript string reference
32−class ToJSVal a => ToJSString a where
33− toJSString :: a -> JSString
34−
35−-- | Anything that can be used to make a JavaScript object reference
36−class MakeObject this where
37− makeObject :: this -> JSM Object
38−
39−instance ToJSVal Object where
40− toJSVal (Object r) = return r
41−
42−-- | If we already have a Object we are fine
43−instance MakeObject Object where
44− makeObject = return
45−
30+#ifdef ghcjs_HOST_OS
31+import GHCJS.Marshal (ToJSVal(..), FromJSVal(..))
32+#else
33+import GHCJS.Marshal.Internal (ToJSVal(..), FromJSVal(..))
34+#endif
35+import GHCJS.Marshal.Pure (PToJSVal(..), PFromJSVal(..))
36+import Language.Javascript.JSaddle.Classes.Internal (MakeObject(..), MakeArgs(..))
37+import Language.Javascript.JSaddle.Marshal.String (ToJSString(..), FromJSString(..))
jsaddle/src/Language/Javascript/JSaddle/Classes/Internal.hsnew file+41
@@ -0,0 +1,41 @@
1+{-# LANGUAGE FlexibleInstances #-}
2+{-# LANGUAGE TypeSynonymInstances #-}
3+-----------------------------------------------------------------------------
4+--
5+-- Module : Language.Javascript.JSaddle.Classes.Internal
6+-- Copyright : (c) Hamish Mackenzie
7+-- License : MIT
8+--
9+-- Maintainer : Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
10+--
11+-- | These classes are used to make various JavaScript types
12+-- out of whatever we have. Functions in jsaddle take these as inputs.
13+-- This alows implicit casting and eager evaluation.
14+--
15+-----------------------------------------------------------------------------
16+
17+module Language.Javascript.JSaddle.Classes.Internal (
18+ -- * Type classes to convert Haskell data to JavaScript
19+ MakeObject(..)
20+ , MakeArgs(..)
21+) where
22+
23+import Language.Javascript.JSaddle.Types
24+ (JSM, Object(..), JSVal)
25+
26+-- | Anything that can be used to make a JavaScript object reference
27+class MakeObject this where
28+ makeObject :: this -> JSM Object
29+
30+-- | If we already have a Object we are fine
31+instance MakeObject Object where
32+ makeObject = return
33+
34+-- | Anything that can be used to make a list of JavaScript value
35+-- references for use as function arguments
36+class MakeArgs this where
37+ makeArgs :: this -> JSM [JSVal]
38+
39+instance MakeArgs arg => MakeArgs (JSM arg) where
40+ makeArgs arg = arg >>= makeArgs
41+
jsaddle/src/Language/Javascript/JSaddle/Evaluate.hs+2−3
@@ -26,13 +26,12 @@ import Language.Javascript.JSaddle.Types (JSVal)
2626import Control.Monad.IO.Class (MonadIO(..))
2727import Language.Javascript.JSaddle.Types (JSString)
2828#else
29−import Language.Javascript.JSaddle.Native
29+import Language.Javascript.JSaddle.Native.Internal
3030 (withJSString)
3131import Language.Javascript.JSaddle.Run
3232 (AsyncCommand(..), sendLazyCommand)
3333#endif
34−import Language.Javascript.JSaddle.Classes
35− (ToJSString(..))
34+import Language.Javascript.JSaddle.Marshal.String (ToJSString(..))
3635import Language.Javascript.JSaddle.Monad (JSM)
3736
3837-- $setup
jsaddle/src/Language/Javascript/JSaddle/Foreign.hsnew file+99
@@ -0,0 +1,99 @@
1+{-# LANGUAGE CPP #-}
2+-----------------------------------------------------------------------------
3+--
4+-- Module : Language.Javascript.JSaddle.Value
5+-- Copyright : (c) Hamish Mackenzie
6+-- License : MIT
7+--
8+-- Maintainer : Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
9+--
10+-- | This module is like `GHCJS.Foreign` but some functions are in
11+--
12+-----------------------------------------------------------------------------
13+module Language.Javascript.JSaddle.Foreign (
14+ jsTrue
15+ , jsFalse
16+ , jsNull
17+ , toJSBool
18+-- , fromJSBoolIO
19+ , jsUndefined
20+ , isTruthyIO
21+ , isNullIO
22+ , isUndefinedIO
23+-- , isObjectIO
24+-- , isFunctionIO
25+-- , isStringIO
26+-- , isBooleanIO
27+-- , isSymbolIO
28+-- , isNumberIO
29+) where
30+
31+#ifdef ghcjs_HOST_OS
32+import Language.Javascript.JSaddle.Types (JSM, JSVal)
33+import GHCJS.Foreign (toJSBool, isTruthy, jsNull, jsUndefined, jsTrue, jsFalse, isNull, isUndefined)
34+#else
35+import Language.Javascript.JSaddle.Types (JSM, JSVal(..))
36+import Language.Javascript.JSaddle.Native.Internal
37+ (withJSVal)
38+import Language.Javascript.JSaddle.Run
39+ (Command(..), Result(..), sendCommand)
40+#endif
41+
42+#ifndef ghcjs_HOST_OS
43+jsTrue :: JSVal
44+jsTrue = JSVal 3
45+{-# INLINE jsTrue #-}
46+
47+jsFalse :: JSVal
48+jsFalse = JSVal 2
49+{-# INLINE jsFalse #-}
50+
51+jsNull :: JSVal
52+jsNull = JSVal 0
53+{-# INLINE jsNull #-}
54+
55+toJSBool :: Bool -> JSVal
56+toJSBool b = JSVal $ if b then 3 else 2
57+{-# INLINE toJSBool #-}
58+
59+jsUndefined :: JSVal
60+jsUndefined = JSVal 1
61+{-# INLINE jsUndefined #-}
62+#endif
63+
64+isTruthyIO :: JSVal -> JSM Bool
65+#ifdef ghcjs_HOST_OS
66+isTruthyIO = return . isTruthy
67+#else
68+isTruthyIO (JSVal 0) = return False -- null
69+isTruthyIO (JSVal 1) = return False -- undefined
70+isTruthyIO (JSVal 2) = return False -- false
71+isTruthyIO (JSVal 3) = return True -- true
72+isTruthyIO v = withJSVal v $ \rval -> do
73+ ValueToBoolResult result <- sendCommand (ValueToBool rval)
74+ return result
75+#endif
76+{-# INLINE isTruthyIO #-}
77+
78+isNullIO :: JSVal -> JSM Bool
79+#ifdef ghcjs_HOST_OS
80+isNullIO = return . isNull
81+#else
82+isNullIO (JSVal 0) = return True
83+isNullIO v = withJSVal v $ \rval -> do
84+ IsNullResult result <- sendCommand $ IsNull rval
85+ return result
86+#endif
87+{-# INLINE isNullIO #-}
88+
89+isUndefinedIO :: JSVal -> JSM Bool
90+#ifdef ghcjs_HOST_OS
91+isUndefinedIO = return . isUndefined
92+#else
93+isUndefinedIO (JSVal 1) = return True
94+isUndefinedIO v = withJSVal v $ \rval -> do
95+ IsUndefinedResult result <- sendCommand $ IsUndefined rval
96+ return result
97+#endif
98+{-# INLINE isUndefinedIO #-}
99+
jsaddle/src/Language/Javascript/JSaddle/Marshal/String.hsnew file+32
@@ -0,0 +1,32 @@
1+{-# LANGUAGE FlexibleInstances #-}
2+{-# LANGUAGE TypeSynonymInstances #-}
3+-----------------------------------------------------------------------------
4+--
5+-- Module : Language.Javascript.JSaddle.Marshal.String
6+-- Copyright : (c) Hamish Mackenzie
7+-- License : MIT
8+--
9+-- Maintainer : Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
10+--
11+-- | `JSStrings` in JSaddle (when compiled with GHC) is not a `JSVal` instead it
12+-- is implemented with a `Text`.
13+--
14+-----------------------------------------------------------------------------
15+
16+module Language.Javascript.JSaddle.Marshal.String (
17+ -- * Type class to convert Haskell to JavaScript string
18+ ToJSString(..)
19+ , FromJSString(..)
20+) where
21+
22+import Language.Javascript.JSaddle.Types (JSString)
23+import GHCJS.Marshal.Internal (ToJSVal(..), FromJSVal(..))
24+
25+-- | Anything that can be used to make a JavaScript string
26+class ToJSVal a => ToJSString a where
27+ toJSString :: a -> JSString
28+
29+-- | Anything that can be constructed from a JavaScript string
30+class FromJSVal a => FromJSString a where
31+ fromJSString :: JSString -> a
32+
jsaddle/src/Language/Javascript/JSaddle/Native.hs+3−47
@@ -1,4 +1,3 @@
1−{-# LANGUAGE CPP #-}
21-----------------------------------------------------------------------------
32--
43-- Module : Language.Javascript.JSaddle.Native
@@ -12,7 +11,6 @@
1211-----------------------------------------------------------------------------
1312
1413module Language.Javascript.JSaddle.Native (
15−#if !defined(ghcjs_HOST_OS)
1614 wrapJSVal
1715 , wrapJSString
1816 , withJSVal
@@ -20,57 +18,15 @@ module Language.Javascript.JSaddle.Native (
2018 , withObject
2119 , withJSString
2220 , withToJSVal
23−#endif
2421) where
2522
26−#if !defined(ghcjs_HOST_OS)
27−import Control.Monad.Trans.Reader (ask)
28−import Control.Monad.IO.Class (MonadIO(..))
23+import GHCJS.Marshal.Internal (ToJSVal(..))
2924import Language.Javascript.JSaddle.Types
30− (JSContextRef(..), AsyncCommand(..), JSM(..), JSString(..),
31− Object(..), JSVal(..), JSValueReceived(..), JSValueForSend(..),
32− JSStringReceived(..), JSStringForSend(..), JSObjectForSend(..))
33−import Language.Javascript.JSaddle.Classes (ToJSVal(..))
34−import System.Mem.Weak (addFinalizer)
35−import Control.Monad.Primitive (touch)
36−import Control.Monad (when)
37−
38−wrapJSVal :: JSValueReceived -> JSM JSVal
39−wrapJSVal (JSValueReceived ref) = do
40− -- TODO make sure this ref has not already been wrapped (perhaps only in debug version)
41− let result = JSVal ref
42− when (ref >= 5) $ do
43− ctx <- JSM ask
44− liftIO . addFinalizer result $ doSendAsyncCommand ctx $ FreeRef $ JSValueForSend ref
45− return result
46−
47−wrapJSString :: MonadIO m => JSStringReceived -> m JSString
48−wrapJSString (JSStringReceived ref) = return $ JSString ref
49−
50−withJSVal :: MonadIO m => JSVal -> (JSValueForSend -> m a) -> m a
51−withJSVal v@(JSVal ref) f =
52− do result <- f (JSValueForSend ref)
53− liftIO $ touch v
54− return result
55−
56−withJSVals :: MonadIO m => [JSVal] -> ([JSValueForSend] -> m a) -> m a
57−withJSVals v f =
58− do result <- f (map (\(JSVal ref) -> JSValueForSend ref) v)
59− liftIO $ mapM_ touch v
60− return result
61−
62−withObject :: MonadIO m => Object -> (JSObjectForSend -> m a) -> m a
63−withObject (Object o) f = withJSVal o (f . JSObjectForSend)
64−
65−withJSString :: MonadIO m => JSString -> (JSStringForSend -> m a) -> m a
66−withJSString v@(JSString ref) f =
67− do result <- f (JSStringForSend ref)
68− liftIO $ touch v
69− return result
25+ (JSM(..), JSValueForSend(..))
26+import Language.Javascript.JSaddle.Native.Internal
7027
7128withToJSVal :: ToJSVal val => val -> (JSValueForSend -> JSM a) -> JSM a
7229withToJSVal val f = do
7330 v <- toJSVal val
7431 withJSVal v f
75−#endif
7632
jsaddle/src/Language/Javascript/JSaddle/Native/Internal.hsnew file+64
@@ -0,0 +1,64 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.Javascript.JSaddle.Native
4+-- Copyright : (c) Hamish Mackenzie
5+-- License : MIT
6+--
7+-- Maintainer : Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
8+--
9+-- |
10+--
11+-----------------------------------------------------------------------------
12+
13+module Language.Javascript.JSaddle.Native.Internal (
14+ wrapJSVal
15+ , wrapJSString
16+ , withJSVal
17+ , withJSVals
18+ , withObject
19+ , withJSString
20+) where
21+
22+import Control.Monad.Trans.Reader (ask)
23+import Control.Monad.IO.Class (MonadIO(..))
24+import Language.Javascript.JSaddle.Types
25+ (JSContextRef(..), AsyncCommand(..), JSM(..), JSString(..),
26+ Object(..), JSVal(..), JSValueReceived(..), JSValueForSend(..),
27+ JSStringReceived(..), JSStringForSend(..), JSObjectForSend(..))
28+import System.Mem.Weak (addFinalizer)
29+import Control.Monad.Primitive (touch)
30+import Control.Monad (when)
31+
32+wrapJSVal :: JSValueReceived -> JSM JSVal
33+wrapJSVal (JSValueReceived ref) = do
34+ -- TODO make sure this ref has not already been wrapped (perhaps only in debug version)
35+ let result = JSVal ref
36+ when (ref >= 5) $ do
37+ ctx <- JSM ask
38+ liftIO . addFinalizer result $ doSendAsyncCommand ctx $ FreeRef $ JSValueForSend ref
39+ return result
40+
41+wrapJSString :: MonadIO m => JSStringReceived -> m JSString
42+wrapJSString (JSStringReceived ref) = return $ JSString ref
43+
44+withJSVal :: MonadIO m => JSVal -> (JSValueForSend -> m a) -> m a
45+withJSVal v@(JSVal ref) f =
46+ do result <- f (JSValueForSend ref)
47+ liftIO $ touch v
48+ return result
49+
50+withJSVals :: MonadIO m => [JSVal] -> ([JSValueForSend] -> m a) -> m a
51+withJSVals v f =
52+ do result <- f (map (\(JSVal ref) -> JSValueForSend ref) v)
53+ liftIO $ mapM_ touch v
54+ return result
55+
56+withObject :: MonadIO m => Object -> (JSObjectForSend -> m a) -> m a
57+withObject (Object o) f = withJSVal o (f . JSObjectForSend)
58+
59+withJSString :: MonadIO m => JSString -> (JSStringForSend -> m a) -> m a
60+withJSString v@(JSString ref) f =
61+ do result <- f (JSStringForSend ref)
62+ liftIO $ touch v
63+ return result
64+
jsaddle/src/Language/Javascript/JSaddle/Object.hs+25−64
@@ -22,7 +22,7 @@
2222-----------------------------------------------------------------------------
2323
2424module Language.Javascript.JSaddle.Object (
25− Object
25+ Object(..)
2626 , MakeObject(..)
2727
2828 -- * Property lookup
@@ -57,6 +57,11 @@ module Language.Javascript.JSaddle.Object (
5757 , new
5858 , call
5959 , obj
60+ , create
61+ , getProp
62+ , unsafeGetProp
63+ , setProp
64+ , unsafeSetProp
6065
6166 -- * Calling Haskell From JavaScript
6267 , Function(..)
@@ -75,12 +80,14 @@ module Language.Javascript.JSaddle.Object (
7580 -- and pass it to the continuation.
7681
7782 -- * Arrays
83+ , fromListIO
7884 , array
7985
8086 -- * Global Object
8187 , global
8288
8389 -- * Enumerating Properties
90+ , listProps
8491 , propertyNames
8592 , properties
8693
@@ -90,40 +97,42 @@ module Language.Javascript.JSaddle.Object (
9097 , nullObject
9198) where
9299
93−import Control.Applicative
94100import Prelude hiding ((!!))
101+import Data.Coerce (coerce)
95102#ifdef ghcjs_HOST_OS
96−import GHCJS.Types (nullRef, jsval)
103+import GHCJS.Types (nullRef)
97104import GHCJS.Foreign.Callback
98105 (releaseCallback, syncCallback2, OnBlocked(..), Callback)
99−import GHCJS.Marshal.Pure (pFromJSVal)
100−import JavaScript.Array (JSArray, MutableJSArray)
106+import GHCJS.Marshal (ToJSVal(..))
107+import JavaScript.Array (MutableJSArray)
101108import qualified JavaScript.Array as Array (toListIO, fromListIO)
102109import JavaScript.Array.Internal (SomeJSArray(..))
103−import qualified JavaScript.Object as Object (create)
104−import Data.Coerce (coerce)
110+import JavaScript.Object (create, listProps)
105111import Language.Javascript.JSaddle.Monad (JSM)
106112import Language.Javascript.JSaddle.Types
107113 (JSString, Object(..),
108114 JSVal(..), JSCallAsFunction)
109115#else
116+import Data.Text (Text)
117+import GHCJS.Marshal.Internal (ToJSVal(..))
110118import Language.Javascript.JSaddle.Native
111− (wrapJSString, withJSVals, withObject)
119+ (withJSVals, withObject)
112120import Language.Javascript.JSaddle.Run
113− (Command(..), AsyncCommand(..), Result(..), sendCommand, sendLazyCommand)
121+ (AsyncCommand(..), sendLazyCommand)
114122import Language.Javascript.JSaddle.Monad (askJSM, JSM)
115123import Language.Javascript.JSaddle.Types
116− (JSString, Object(..),
124+ (JSString, Object(..), SomeJSArray(..),
117125 JSVal(..), JSCallAsFunction, JSContextRef(..))
126+import JavaScript.Object.Internal (create, listProps)
118127#endif
128+import JavaScript.Array.Internal (fromListIO)
119129import Language.Javascript.JSaddle.Value (valToObject)
120−import Language.Javascript.JSaddle.Classes
121− (ToJSVal(..), ToJSString(..), MakeObject(..))
130+import Language.Javascript.JSaddle.Classes (MakeObject(..))
131+import Language.Javascript.JSaddle.Marshal.String (ToJSString(..))
122132import Language.Javascript.JSaddle.Arguments (MakeArgs(..))
123133import Control.Monad.IO.Class (MonadIO(..))
124134import Language.Javascript.JSaddle.Properties
125135import Control.Lens (IndexPreservingGetter, to)
126−import Data.Text (Text)
127136
128137-- $setup
129138-- >>> import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
@@ -402,11 +411,7 @@ call f this args = do
402411-- >>> testJSaddle $ do { a <- obj; (a <# "x") "Hello"; a ^. js "x" }
403412-- Hello
404413obj :: JSM Object
405−#ifdef ghcjs_HOST_OS
406−obj = liftIO Object.create
407−#else
408−obj = Object <$> sendLazyCommand NewEmptyObject
409−#endif
414+obj = create
410415
411416-- | Short hand @::JSCallAsFunction@ so a haskell function can be passed to
412417-- a to a JavaScipt one.
@@ -487,43 +492,9 @@ instance MakeArgs JSCallAsFunction where
487492-- >>> testJSaddle $ array ("Hello", JSNull, (), True, 1.0::Double)
488493-- Hello,,,true,1
489494array :: MakeArgs args => args -> JSM Object
490−#ifdef ghcjs_HOST_OS
491−array args = do
492− rargs <- makeArgs args
493− liftIO $ Object . jsval <$> Array.fromListIO rargs
494−#else
495495array args = do
496496 rargs <- makeArgs args
497− withJSVals rargs $ \rargs' -> Object <$> sendLazyCommand (NewArray rargs')
498−#endif
499−
500−-- Make an array out of various lists
501−instance ToJSVal [JSVal] where
502− toJSVal = toJSVal . array
503−
504−instance ToJSVal [JSM JSVal] where
505− toJSVal = toJSVal . array
506−
507−instance ToJSVal [Double] where
508− toJSVal = toJSVal . array
509−
510−instance ToJSVal [Float] where
511− toJSVal = toJSVal . array
512−
513−instance ToJSVal [Int] where
514− toJSVal = toJSVal . array
515−
516−instance ToJSVal [JSString] where
517− toJSVal = toJSVal . array
518−
519−instance ToJSVal [String] where
520− toJSVal = toJSVal . array
521−
522−instance ToJSVal [Text] where
523− toJSVal = toJSVal . array
524−
525−instance ToJSVal [Bool] where
526− toJSVal = toJSVal . array
497+ Object . coerce <$> fromListIO rargs
527498
528499-- | JavaScript's global object
529500global :: Object
@@ -541,17 +512,7 @@ global = Object (JSVal 4)
541512-- >>> testJSaddle $ show . map strToText <$> propertyNames (eval "({x:1, y:2})")
542513-- ["x","y"]
543514propertyNames :: MakeObject this => this -> JSM [JSString]
544−#ifdef ghcjs_HOST_OS
545−propertyNames this = makeObject this >>= liftIO . js_propertyNames >>= liftIO . (fmap (map pFromJSVal)) . Array.toListIO
546−foreign import javascript unsafe "$r = []; h$forIn($1, function(n){$r.push(n);})"
547− js_propertyNames :: Object -> IO JSArray
548−#else
549−propertyNames this = do
550− this' <- makeObject this
551− withObject this' $ \rthis -> do
552− PropertyNamesResult result <- sendCommand $ PropertyNames rthis
553− mapM wrapJSString result
554−#endif
515+propertyNames this = makeObject this >>= listProps
555516
556517-- | Get a list containing references to all the properties present on a given object
557518properties :: MakeObject this => this -> JSM [JSVal]
jsaddle/src/Language/Javascript/JSaddle/Properties.hs+11−29
@@ -22,44 +22,37 @@
2222
2323module Language.Javascript.JSaddle.Properties (
2424 -- * Getting Property Values
25− objGetPropertyByName
25+ getProp, unsafeGetProp
26+ , objGetPropertyByName
2627 , objGetPropertyAtIndex
2728 -- * Setting Property Values
29+ , setProp, unsafeSetProp
2830 , objSetPropertyByName
2931 , objSetPropertyAtIndex
3032) where
3133
32−import Language.Javascript.JSaddle.Classes
33− (ToJSVal(..), ToJSString(..))
3434import Language.Javascript.JSaddle.Monad (JSM)
35−import Language.Javascript.JSaddle.Types (Object(..))
35+import Language.Javascript.JSaddle.Types (JSVal, Object(..))
36+import JavaScript.Object.Internal (getProp, unsafeGetProp, setProp, unsafeSetProp)
3637#ifdef ghcjs_HOST_OS
37−import Language.Javascript.JSaddle.Types (JSString)
38+import GHCJS.Marshal (ToJSVal(..))
3839#else
40+import GHCJS.Marshal.Internal (ToJSVal(..))
3941import Language.Javascript.JSaddle.Native
40− (withObject, withJSString, withToJSVal)
42+ (withObject, withToJSVal)
4143import Language.Javascript.JSaddle.Run
4244 (AsyncCommand(..), sendLazyCommand, sendAsyncCommand)
4345#endif
44−import Language.Javascript.JSaddle.Value (JSVal)
4546import Language.Javascript.JSaddle.Arguments ()
4647import Language.Javascript.JSaddle.String ()
48+import Language.Javascript.JSaddle.Marshal.String (ToJSString(..))
4749
4850-- | Get a property value given the object and the name of the property.
4951objGetPropertyByName :: ToJSString name
5052 => Object -- ^ object to find the property on.
5153 -> name -- ^ name of the property.
5254 -> JSM JSVal -- ^ returns the property value.
53−#ifdef ghcjs_HOST_OS
54−objGetPropertyByName this name = js_tryGetProp (toJSString name) this
55−foreign import javascript unsafe "$r=$2[$1]"
56− js_tryGetProp :: JSString -> Object -> IO JSVal
57−#else
58−objGetPropertyByName this name =
59− withObject this $ \rthis ->
60− withJSString (toJSString name) $
61− sendLazyCommand . GetPropertyByName rthis
62−#endif
55+objGetPropertyByName this name = unsafeGetProp (toJSString name) this
6356
6457-- | Get a property value given the object and the index of the property.
6558objGetPropertyAtIndex :: Object -- ^ object to find the property on.
@@ -80,20 +73,9 @@ objSetPropertyByName :: (ToJSString name, ToJSVal val)
8073 -> name -- ^ name of the property.
8174 -> val -- ^ new value to set the property to.
8275 -> JSM ()
83−#ifdef ghcjs_HOST_OS
8476objSetPropertyByName this name val = do
8577 vref <- toJSVal val
86− js_trySetProp (toJSString name) this vref
87−foreign import javascript unsafe "$2[$1]=$3"
88− js_trySetProp :: JSString -> Object -> JSVal -> IO ()
89−#else
90−objSetPropertyByName this name val = do
91− let name' = toJSString name
92− withObject this $ \rthis ->
93− withJSString name' $ \rname ->
94− withToJSVal val $ \rval ->
95− sendAsyncCommand $ SetPropertyByName rthis rname rval
96−#endif
78+ unsafeSetProp (toJSString name) vref this
9779
9880-- | Set a property value given the object and the index of the property.
9981objSetPropertyAtIndex :: (ToJSVal val)
jsaddle/src/Language/Javascript/JSaddle/Run.hs+1−1
@@ -58,7 +58,7 @@ import Language.Javascript.JSaddle.Types
5858 (Command(..), AsyncCommand(..), Result(..), JSContextRef(..), JSVal(..),
5959 Object(..), JSValueReceived(..), JSM(..), Batch(..), JSValueForSend(..))
6060import Language.Javascript.JSaddle.Exception (JSException(..))
61−import Language.Javascript.JSaddle.Native (wrapJSVal)
61+import Language.Javascript.JSaddle.Native.Internal (wrapJSVal)
6262#endif
6363
6464-- | Forces execution of pending asyncronous code
jsaddle/src/Language/Javascript/JSaddle/Run/Files.hs+75
@@ -16,6 +16,7 @@ module Language.Javascript.JSaddle.Run.Files (
1616 , jsaddleJs
1717 , initState
1818 , runBatch
19+ , ghcjsHelpers
1920) where
2021
2122import Data.ByteString.Lazy (ByteString)
@@ -166,6 +167,9 @@ runBatch send = "\
166167 \ var s = jsaddle_values.get(d.contents) === undefined ? \"\" : JSON.stringify(jsaddle_values.get(d.contents));\n\
167168 \ " <> send "{\"tag\": \"ValueToJSONResult\", \"contents\": s}" <> "\n\
168169 \ break;\n\
170+ \ case \"ValueToJSONValue\":\n\
171+ \ " <> send "{\"tag\": \"ValueToJSONValueResult\", \"contents\": jsaddle_values.get(d.contents)}" <> "\n\
172+ \ break;\n\
169173 \ case \"DeRefVal\":\n\
170174 \ var n = d.contents;\n\
171175 \ var v = jsaddle_values.get(n);\n\
@@ -247,5 +251,76 @@ jsaddleJs = "\
247251 \ };\n\
248252 \}\n\
249253 \\n\
254+ \ " <> ghcjsHelpers <> "\
250255 \connect();\n\
251256 \"
257+
258+ghcjsHelpers :: ByteString
259+ghcjsHelpers = "\
260+ \function h$isNumber(o) {\
261+ \ return typeof(o) === 'number';\n\
262+ \}\n\
263+ \\n\
264+ \// returns true for null, but not for functions and host objects\n\
265+ \function h$isObject(o) {\n\
266+ \ return typeof(o) === 'object';\n\
267+ \}\n\
268+ \\n\
269+ \function h$isString(o) {\n\
270+ \ return typeof(o) === 'string';\n\
271+ \}\n\
272+ \\n\
273+ \function h$isSymbol(o) {\n\
274+ \ return typeof(o) === 'symbol';\n\
275+ \}\n\
276+ \\n\
277+ \function h$isBoolean(o) {\n\
278+ \ return typeof(o) === 'boolean';\n\
279+ \}\n\
280+ \\n\
281+ \function h$isFunction(o) {\n\
282+ \ return typeof(o) === 'function';\n\
283+ \}\n\
284+ \\n\
285+ \function h$jsTypeOf(o) {\n\
286+ \ var t = typeof(o);\n\
287+ \ if(t === 'undefined') return 0;\n\
288+ \ if(t === 'object') return 1;\n\
289+ \ if(t === 'boolean') return 2;\n\
290+ \ if(t === 'number') return 3;\n\
291+ \ if(t === 'string') return 4;\n\
292+ \ if(t === 'symbol') return 5;\n\
293+ \ if(t === 'function') return 6;\n\
294+ \ return 7; // other, host object etc\n\
295+ \}\n\
296+ \\n\
297+ \function h$jsonTypeOf(o) {\n\
298+ \ if (!(o instanceof Object)) {\n\
299+ \ if (o == null) {\n\
300+ \ return 0;\n\
301+ \ } else if (typeof o == 'number') {\n\
302+ \ if (h$isInteger(o)) {\n\
303+ \ return 1;\n\
304+ \ } else {\n\
305+ \ return 2;\n\
306+ \ }\n\
307+ \ } else if (typeof o == 'boolean') {\n\
308+ \ return 3;\n\
309+ \ } else {\n\
310+ \ return 4;\n\
311+ \ }\n\
312+ \ } else {\n\
313+ \ if (Object.prototype.toString.call(o) == '[object Array]') {\n\
314+ \ // it's an array\n\
315+ \ return 5;\n\
316+ \ } else if (!o) {\n\
317+ \ // null \n\
318+ \ return 0;\n\
319+ \ } else {\n\
320+ \ // it's an object\n\
321+ \ return 6;\n\
322+ \ }\n\
323+ \ }\n\
324+ \\n\
325+ \}\n\
326+ \"
jsaddle/src/Language/Javascript/JSaddle/String.hs+10−11
@@ -18,9 +18,10 @@
1818
1919module Language.Javascript.JSaddle.String (
2020 JSString
21− , ToJSString(..)
2221
2322 -- * Data.Text helpers
23+ , textFromJSString
24+ , textToJSString
2425 , strToText
2526 , textToStr
2627) where
@@ -30,21 +31,19 @@ import Language.Javascript.JSaddle.Types (JSString(..))
3031#ifdef ghcjs_HOST_OS
3132import Data.JSString.Text (textFromJSString, textToJSString)
3233#endif
33−import Language.Javascript.JSaddle.Classes (ToJSString(..))
34+
35+#ifndef ghcjs_HOST_OS
36+textFromJSString :: JSString -> Text
37+textFromJSString (JSString text) = text
38+
39+textToJSString :: Text -> JSString
40+textToJSString = JSString
41+#endif
3442
3543-- | Convert a JavaScript string to a Haskell 'Text'
3644strToText :: JSString -> Text
37−#ifdef ghcjs_HOST_OS
3845strToText = textFromJSString
39−#else
40−strToText (JSString text) = text
41−#endif
4246
4347-- | Convert a Haskell 'Text' to a JavaScript string
4448textToStr :: Text -> JSString
45−#ifdef ghcjs_HOST_OS
4649textToStr = textToJSString
47−#else
48−textToStr = JSString
49−#endif
50−
jsaddle/src/Language/Javascript/JSaddle/Types.hs+51−4
@@ -7,6 +7,11 @@
77{-# LANGUAGE UndecidableInstances #-}
88{-# LANGUAGE GeneralizedNewtypeDeriving #-}
99{-# LANGUAGE DeriveGeneric #-}
10+{-# LANGUAGE DefaultSignatures #-}
11+{-# LANGUAGE DataKinds #-}
12+{-# LANGUAGE KindSignatures #-}
13+{-# LANGUAGE PolyKinds #-}
14+{-# LANGUAGE FlexibleContexts #-}
1015#endif
1116-----------------------------------------------------------------------------
1217--
@@ -31,7 +36,9 @@ module Language.Javascript.JSaddle.Types (
3136
3237 -- * JavaScript Value Types
3338 , JSVal(..)
34− , MutableJSArray(..)
39+ , SomeJSArray(..)
40+ , JSArray
41+ , MutableJSArray
3542 , Object(..)
3643 , JSString(..)
3744 , Nullable(..)
@@ -55,9 +62,10 @@ import Control.Monad.IO.Class (MonadIO(..))
5562#ifdef ghcjs_HOST_OS
5663import GHCJS.Types
5764import JavaScript.Object.Internal (Object(..))
58−import JavaScript.Array (MutableJSArray)
65+import JavaScript.Array.Internal (SomeJSArray(..), JSArray, MutableJSArray)
5966import GHCJS.Nullable (Nullable(..))
6067#else
68+import Control.DeepSeq (NFData(..))
6169import Control.Monad.Trans.Reader (ReaderT(..))
6270import Control.Monad.Trans.State.Lazy (StateT(..))
6371import qualified Control.Monad.Trans.State.Strict as Strict
@@ -66,11 +74,13 @@ import Control.Monad.Trans.Class (MonadTrans(..))
6674import Control.Monad.Fix (MonadFix)
6775import Control.Monad.Ref (MonadAtomicRef(..), MonadRef(..))
6876import Control.Concurrent.STM.TVar (TVar)
77+import Data.Coerce (Coercible, coerce)
6978import Data.Int (Int64)
7079import Data.Text (Text)
7180import Data.Time.Clock (UTCTime(..))
81+import Data.Typeable (Typeable)
7282import Data.Aeson
73− (defaultOptions, genericToEncoding, ToJSON(..), FromJSON(..))
83+ (defaultOptions, genericToEncoding, ToJSON(..), FromJSON(..), Value)
7484import GHC.Generics (Generic)
7585#endif
7686
@@ -168,8 +178,42 @@ type JSValueRef = Int64
168178-- | See 'GHCJS.Prim.JSVal'
169179newtype JSVal = JSVal JSValueRef deriving(Show, ToJSON, FromJSON)
170180
181+instance NFData JSVal where
182+ rnf x = x `seq` ()
183+
184+class IsJSVal a where
185+ jsval_ :: a -> JSVal
186+
187+ default jsval_ :: Coercible a JSVal => a -> JSVal
188+ jsval_ = coerce
189+ {-# INLINE jsval_ #-}
190+
191+jsval :: IsJSVal a => a -> JSVal
192+jsval = jsval_
193+{-# INLINE jsval #-}
194+
195+data MutabilityType s = Mutable_ s
196+ | Immutable_ s
197+ | STMutable s
198+
199+type Mutable = Mutable_ ()
200+type Immutable = Immutable_ ()
201+
202+data IsItMutable = IsImmutable
203+ | IsMutable
204+
205+type family Mutability (a :: MutabilityType s) :: IsItMutable where
206+ Mutability Immutable = IsImmutable
207+ Mutability Mutable = IsMutable
208+ Mutability (STMutable s) = IsMutable
209+
210+newtype SomeJSArray (m :: MutabilityType s) = SomeJSArray JSVal
211+ deriving (Typeable)
212+
213+-- | See 'JavaScript.Array.Internal.JSArray'
214+type JSArray = SomeJSArray Immutable
171215-- | See 'JavaScript.Array.Internal.MutableJSArray'
172−newtype MutableJSArray = MutableJSArray JSValueRef deriving(Show, ToJSON, FromJSON)
216+type MutableJSArray = SomeJSArray Mutable
173217
174218-- | See 'JavaScript.Object.Internal.Object'
175219newtype Object = Object JSVal deriving(Show, ToJSON, FromJSON)
@@ -201,6 +245,7 @@ data AsyncCommand = FreeRef JSValueForSend
201245 | SetPropertyAtIndex JSObjectForSend Int JSValueForSend
202246 | StringToValue JSStringForSend JSValueForSend
203247 | NumberToValue Double JSValueForSend
248+ | JSONValueToValue Value JSValueForSend
204249 | GetPropertyByName JSObjectForSend JSStringForSend JSValueForSend
205250 | GetPropertyAtIndex JSObjectForSend Int JSValueForSend
206251 | CallAsFunction JSObjectForSend JSObjectForSend [JSValueForSend] JSValueForSend
@@ -223,6 +268,7 @@ data Command = DeRefVal JSValueForSend
223268 | ValueToNumber JSValueForSend
224269 | ValueToString JSValueForSend
225270 | ValueToJSON JSValueForSend
271+ | ValueToJSONValue JSValueForSend
226272 | IsNull JSValueForSend
227273 | IsUndefined JSValueForSend
228274 | StrictEqual JSValueForSend JSValueForSend
@@ -251,6 +297,7 @@ data Result = DeRefValResult JSValueRef Text
251297 | ValueToNumberResult Double
252298 | ValueToStringResult JSStringReceived
253299 | ValueToJSONResult JSStringReceived
300+ | ValueToJSONValueResult Value
254301 | IsNullResult Bool
255302 | IsUndefinedResult Bool
256303 | StrictEqualResult Bool
jsaddle/src/Language/Javascript/JSaddle/Value.hs+160−76
@@ -45,6 +45,7 @@ module Language.Javascript.JSaddle.Value (
4545 , showJSValue
4646
4747 -- * Converting JavaScript values
48+ , isTruthyIO
4849 , valToBool
4950 , valToNumber
5051 , valToStr
@@ -54,15 +55,24 @@ module Language.Javascript.JSaddle.Value (
5455
5556 -- * Make JavaScript values from Haskell ones
5657 , val
58+ , jsNull
5759 , valNull
60+ , isNullIO
5861 , valIsNull
62+ , jsUndefined
5963 , valUndefined
64+ , isUndefinedIO
6065 , valIsUndefined
6166 , maybeNullOrUndefined
6267 , maybeNullOrUndefined'
68+ , toJSBool
69+ , jsTrue
70+ , jsFalse
6371 , valBool
6472 , valMakeNumber
6573 , valMakeString
74+ , valMakeText
75+ , valMakeJSON
6676
6777 -- * Convert to and from JSValue
6878 , deRefVal
@@ -71,33 +81,35 @@ module Language.Javascript.JSaddle.Value (
7181 , instanceOf
7282) where
7383
84+import Data.Text (Text)
85+import qualified Data.Text as T (pack, unpack)
86+import Data.Aeson (Value)
87+
88+#ifdef ghcjs_HOST_OS
7489import Language.Javascript.JSaddle.Types
7590 (Object(..), JSString(..), JSVal(..))
76−#ifdef ghcjs_HOST_OS
77−import Control.Monad.IO.Class (MonadIO(..))
78−import GHCJS.Types (isNull, isUndefined)
79−import GHCJS.Foreign (toJSBool, isTruthy, jsNull, jsUndefined)
80−import qualified GHCJS.Marshal as GHCJS (toJSVal)
91+import GHCJS.Marshal (ToJSVal(..))
8192import GHCJS.Marshal.Pure (pToJSVal)
8293import Data.JSString.Text (textToJSString)
83−import qualified Data.Text as T (pack)
8494#else
85−import qualified Data.Text as T (pack, unpack)
95+import Data.Char (chr, ord)
96+import Data.Word (Word, Word8, Word16, Word32)
97+import Data.Int (Int8, Int16, Int32)
98+import GHCJS.Marshal.Internal (ToJSVal(..), FromJSVal(..))
99+import Language.Javascript.JSaddle.Types
100+ (Object(..), JSString(..), JSVal(..), JSValueForSend(..))
86101import Language.Javascript.JSaddle.Native
87− (wrapJSString, withJSVal, withObject, withJSString,
88− withToJSVal)
102+ (wrapJSString, withJSVal, withObject, withJSString, withToJSVal)
89103import Language.Javascript.JSaddle.Run
90104 (Command(..), AsyncCommand(..), Result(..), sendCommand,
91105 sendLazyCommand)
92106#endif
93107import Language.Javascript.JSaddle.Monad (JSM)
94−import Data.Text (Text)
95108import Language.Javascript.JSaddle.Classes
96− (MakeObject(..), ToJSString(..), ToJSVal(..))
109+ (MakeObject(..), MakeArgs(..))
110+import Language.Javascript.JSaddle.Marshal.String (ToJSString(..), FromJSString(..))
97111import Language.Javascript.JSaddle.String (strToText, textToStr)
98−import Language.Javascript.JSaddle.Arguments (MakeArgs(..))
99−import Data.Word (Word32, Word, Word64)
100−import Data.Int (Int32, Int64)
112+import Language.Javascript.JSaddle.Foreign (jsTrue, jsFalse, jsNull, toJSBool, jsUndefined, isTruthyIO, isNullIO, isUndefinedIO)
101113
102114-- $setup
103115-- >>> import Language.Javascript.JSaddle.Test (testJSaddle)
@@ -154,20 +166,7 @@ showJSValue (ValObject _) = "object"
154166-- >>> testJSaddle $ valToBool "1"
155167-- true
156168valToBool :: ToJSVal value => value -> JSM Bool
157−#ifdef ghcjs_HOST_OS
158−valToBool value = isTruthy <$> toJSVal value
159−#else
160−valToBool value =
161− toJSVal value >>= \case
162− (JSVal 0) -> return False -- null
163− (JSVal 1) -> return False -- undefined
164− (JSVal 2) -> return False -- false
165− (JSVal 3) -> return True -- true
166− v ->
167− withJSVal v $ \rval -> do
168− ValueToBoolResult result <- sendCommand (ValueToBool rval)
169− return result
170−#endif
169+valToBool value = toJSVal value >>= isTruthyIO
171170
172171-- | Given a JavaScript value get its numeric value.
173172-- May throw JSException.
@@ -308,15 +307,21 @@ valToObject value = Object <$> toJSVal value
308307instance MakeObject JSVal where
309308 makeObject = valToObject
310309
310+instance ToJSVal Object where
311+ toJSVal (Object r) = return r
312+
311313-- | Convert to a JavaScript value (just an alias for 'toJSVal')
312314val :: ToJSVal value
313315 => value -- ^ value to convert to a JavaScript value
314316 -> JSM JSVal
315317val = toJSVal
316318
319+#ifndef ghcjs_HOST_OS
317320-- | If we already have a JSVal we are fine
318321instance ToJSVal JSVal where
319322 toJSVal = return
323+ {-# INLINE toJSVal #-}
324+#endif
320325
321326-- | A single JSVal can be used as the argument list
322327instance MakeArgs JSVal where
@@ -326,55 +331,68 @@ instance MakeArgs JSVal where
326331-- as it returns something we can make into a JSVal.
327332instance ToJSVal v => ToJSVal (JSM v) where
328333 toJSVal v = v >>= toJSVal
334+ {-# INLINE toJSVal #-}
329335
330336----------- null ---------------
331337-- | A @null@ JavaScript value
332338valNull :: JSVal
333−#ifdef ghcjs_HOST_OS
334339valNull = jsNull
335−#else
336−valNull = JSVal 0
337−#endif
340+{-# INLINE valNull #-}
338341
339342-- | Makes a @null@ JavaScript value
340343instance ToJSVal JSNull where
341− toJSVal = const (return valNull)
344+ toJSVal = const (return jsNull)
345+ {-# INLINE toJSVal #-}
342346
343347-- | Makes an argument list with just a single @null@ JavaScript value
344348instance MakeArgs JSNull where
345− makeArgs _ = return [valNull]
349+ makeArgs _ = return [jsNull]
346350
351+#ifndef ghcjs_HOST_OS
347352-- | Makes a JSVal or @null@ JavaScript value
348353instance ToJSVal a => ToJSVal (Maybe a) where
349− toJSVal Nothing = return valNull
354+ toJSVal Nothing = return jsNull
350355 toJSVal (Just a) = toJSVal a
356+ {-# INLINE toJSVal #-}
357+instance FromJSVal a => FromJSVal (Maybe a) where
358+ fromJSValUnchecked x =
359+ isUndefinedIO x >>= \case
360+ True -> return Nothing
361+ False -> isNullIO x >>= \case
362+ True -> return Nothing
363+ False -> fromJSVal x
364+ {-# INLINE fromJSValUnchecked #-}
365+ fromJSVal x =
366+ isUndefinedIO x >>= \case
367+ True -> return (Just Nothing)
368+ False -> isNullIO x >>= \case
369+ True -> return (Just Nothing)
370+ False -> fmap (fmap Just) fromJSVal x
371+ {-# INLINE fromJSVal #-}
372+
373+-- Make an array out of various lists
374+instance ToJSVal a => ToJSVal [a] where
375+ toJSVal = toJSValListOf
376+ {-# INLINE toJSVal #-}
377+
378+instance FromJSVal a => FromJSVal [a] where
379+ fromJSVal = fromJSValListOf
380+ {-# INLINE fromJSVal #-}
381+#endif
351382
352383-- | Test a JavaScript value to see if it is @null@
353384valIsNull :: ToJSVal value => value -> JSM Bool
354−#ifdef ghcjs_HOST_OS
355−valIsNull value = isNull <$> toJSVal value
356−#else
357−valIsNull value =
358− toJSVal value >>= \case
359− JSVal 0 -> return True
360− v ->
361− withJSVal v $ \rval -> do
362− IsNullResult result <- sendCommand $ IsNull rval
363− return result
364−#endif
385+valIsNull value = toJSVal value >>= isNullIO
365386
366387----------- undefined ---------------
367388-- | An @undefined@ JavaScript value
368389valUndefined :: JSVal
369−#ifdef ghcjs_HOST_OS
370390valUndefined = jsUndefined
371−#else
372−valUndefined = JSVal 1
373−#endif
391+{-# INLINE valUndefined #-}
374392
375393-- | Makes an @undefined@ JavaScript value
376394instance ToJSVal JSUndefined where
377− toJSVal = const (return valUndefined)
395+ toJSVal = const (return jsUndefined)
378396
379397--We can't allow this if JSUndefined is () as () is no args not "(null)".
380398--Use [()] instead.
@@ -387,16 +405,7 @@ instance MakeArgs () where
387405
388406-- | Test a JavaScript value to see if it is @undefined@
389407valIsUndefined :: ToJSVal value => value -> JSM Bool
390−#ifdef ghcjs_HOST_OS
391−valIsUndefined value = isUndefined <$> toJSVal value
392−#else
393−valIsUndefined value = toJSVal value >>= \case
394− JSVal 1 -> return True
395− v ->
396− withJSVal v $ \rval -> do
397− IsUndefinedResult result <- sendCommand $ IsUndefined rval
398− return result
399−#endif
408+valIsUndefined value = toJSVal value >>= isUndefinedIO
400409
401410-- | Convert a JSVal to a Maybe JSVal (converting null and undefined to Nothing)
402411maybeNullOrUndefined :: ToJSVal value => value -> JSM (Maybe JSVal)
@@ -422,15 +431,15 @@ maybeNullOrUndefined' f value = do
422431----------- booleans ---------------
423432-- | A JavaScript boolean value
424433valBool :: Bool -> JSVal
425−#ifdef ghcjs_HOST_OS
426−valBool b = toJSBool b
427−#else
428−valBool b = JSVal $ if b then 3 else 2
429−#endif
434+valBool = toJSBool
435+{-# INLINE valBool #-}
430436
437+#ifndef ghcjs_HOST_OS
431438-- | Make a JavaScript boolean value
432439instance ToJSVal Bool where
433440 toJSVal = return . valBool
441+ {-# INLINE toJSVal #-}
442+#endif
434443
435444-- | Makes an argument list with just a single JavaScript boolean value
436445instance MakeArgs Bool where
@@ -440,35 +449,53 @@ instance MakeArgs Bool where
440449-- | Make a JavaScript number
441450valMakeNumber :: Double -> JSM JSVal
442451#ifdef ghcjs_HOST_OS
443−valMakeNumber n = liftIO $ GHCJS.toJSVal n
452+valMakeNumber n = toJSVal n
444453#else
445454valMakeNumber = sendLazyCommand . NumberToValue
446455#endif
447456
457+#ifndef ghcjs_HOST_OS
448458-- | Makes a JavaScript number
449459instance ToJSVal Double where
450460 toJSVal = valMakeNumber
461+ {-# INLINE toJSVal #-}
451462
452463instance ToJSVal Float where
453464 toJSVal = valMakeNumber . realToFrac
465+ {-# INLINE toJSVal #-}
454466
455467instance ToJSVal Word where
456468 toJSVal = valMakeNumber . fromIntegral
469+ {-# INLINE toJSVal #-}
457470
458−instance ToJSVal Word32 where
471+instance ToJSVal Word8 where
472+ toJSVal = valMakeNumber . fromIntegral
473+ {-# INLINE toJSVal #-}
474+
475+instance ToJSVal Word16 where
459476 toJSVal = valMakeNumber . fromIntegral
477+ {-# INLINE toJSVal #-}
460478
461−instance ToJSVal Word64 where
479+instance ToJSVal Word32 where
462480 toJSVal = valMakeNumber . fromIntegral
481+ {-# INLINE toJSVal #-}
463482
464483instance ToJSVal Int where
465484 toJSVal = valMakeNumber . fromIntegral
485+ {-# INLINE toJSVal #-}
466486
467−instance ToJSVal Int32 where
487+instance ToJSVal Int8 where
468488 toJSVal = valMakeNumber . fromIntegral
489+ {-# INLINE toJSVal #-}
469490
470−instance ToJSVal Int64 where
491+instance ToJSVal Int16 where
471492 toJSVal = valMakeNumber . fromIntegral
493+ {-# INLINE toJSVal #-}
494+
495+instance ToJSVal Int32 where
496+ toJSVal = valMakeNumber . fromIntegral
497+ {-# INLINE toJSVal #-}
498+#endif
472499
473500-- | Makes an argument list with just a single JavaScript number
474501instance MakeArgs Double where
@@ -491,21 +518,33 @@ valMakeString s =
491518 withJSString s $ sendLazyCommand . StringToValue
492519#endif
493520
521+#ifndef ghcjs_HOST_OS
494522-- | Makes a JavaScript string
495523instance ToJSVal Text where
496524 toJSVal = valMakeText
525+ {-# INLINE toJSVal #-}
526+instance FromJSVal Text where
527+ fromJSValUnchecked = valToText
528+ {-# INLINE fromJSValUnchecked #-}
529+ fromJSVal = fmap Just . valToText
530+ {-# INLINE fromJSVal #-}
531+#endif
497532
498533-- | Makes an argument list with just a single JavaScript string
499534instance MakeArgs Text where
500535 makeArgs t = valMakeText t >>= (\ref -> return [ref])
501536
502−-- | Makes a JavaScript string
503−instance ToJSVal String where
504− toJSVal = valMakeText . T.pack
505−
537+#ifndef ghcjs_HOST_OS
506538-- | Makes a JavaScript string
507539instance ToJSVal JSString where
508540 toJSVal = valMakeString
541+ {-# INLINE toJSVal #-}
542+instance FromJSVal JSString where
543+ fromJSValUnchecked = valToStr
544+ {-# INLINE fromJSValUnchecked #-}
545+ fromJSVal = fmap Just . valToStr
546+ {-# INLINE fromJSVal #-}
547+#endif
509548
510549-- | If we already have a JSString we are fine
511550instance ToJSString JSString where
@@ -517,6 +556,51 @@ instance ToJSString Text where
517556instance ToJSString String where
518557 toJSString = textToStr . T.pack
519558
559+instance FromJSString Text where
560+ fromJSString = strToText
561+
562+instance FromJSString String where
563+ fromJSString v = T.unpack $ strToText v
564+
565+instance FromJSString JSString where
566+ fromJSString = id
567+
568+#ifndef ghcjs_HOST_OS
569+instance ToJSVal Char where
570+ toJSVal = valMakeNumber . fromIntegral . ord
571+ {-# INLINE toJSVal #-}
572+ toJSValListOf = valMakeText . T.pack
573+ {-# INLINE toJSValListOf #-}
574+instance FromJSVal Char where
575+ fromJSValUnchecked = fmap (chr . round) . valToNumber
576+ {-# INLINE fromJSValUnchecked #-}
577+ fromJSVal = fmap (Just . chr . round) . valToNumber
578+ {-# INLINE fromJSVal #-}
579+ fromJSValUncheckedListOf = fmap (T.unpack . strToText) . valToStr
580+ {-# INLINE fromJSValListOf #-}
581+ fromJSValListOf = fmap (Just . T.unpack . strToText) . valToStr
582+ {-# INLINE fromJSValUncheckedListOf #-}
583+#endif
584+
585+-- | Make a JavaScript string from AESON `Value`
586+valMakeJSON :: Value -> JSM JSVal
587+#ifdef ghcjs_HOST_OS
588+valMakeJSON = toJSVal
589+#else
590+valMakeJSON = sendLazyCommand . JSONValueToValue
591+#endif
592+
593+#ifndef ghcjs_HOST_OS
594+-- | Makes a JSON value
595+instance ToJSVal Value where
596+ toJSVal = valMakeJSON
597+ {-# INLINE toJSVal #-}
598+#endif
599+
600+-- | Makes an argument list with just a single JSON value
601+instance MakeArgs Value where
602+ makeArgs t = valMakeJSON t >>= (\ref -> return [ref])
603+
520604-- | Derefernce a value reference.
521605--
522606-- >>> testJSaddle $ showJSValue <$> deRefVal JSNull
@@ -597,6 +681,7 @@ valMakeRef value =
597681-- | Makes a JavaScript value from a 'JSValue' ADT.
598682instance ToJSVal JSValue where
599683 toJSVal = valMakeRef
684+ {-# INLINE toJSVal #-}
600685
601686-- | Makes an argument list with just a single JavaScript value from a 'JSValue' ADT.
602687instance MakeArgs JSValue where
@@ -664,4 +749,3 @@ instanceOf value constructor = do
664749
665750
666751
667−