@@ -3,7 +3,7 @@
33{-# LANGUAGE FlexibleInstances #-}
44{-# LANGUAGE TypeSynonymInstances #-}
55{-# LANGUAGE LambdaCase #-}
6−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
6+#ifdef ghcjs_HOST_OS
77{-# LANGUAGE ForeignFunctionInterface, JavaScriptFFI #-}
88#endif
99{-# OPTIONS_GHC -fno-warn-orphans #-}
@@ -41,6 +41,7 @@ module Language.Javascript.JSaddle.Value (
4141 , JSUndefined
4242 , JSString
4343 , JSValue(..)
44+ , showJSValue
4445
4546 -- * Converting JavaScript values
4647 , valToBool
@@ -69,10 +70,11 @@ module Language.Javascript.JSaddle.Value (
6970 , instanceOf
7071) where
7172
73+import Control.Applicative ((<$>))
7274import Prelude hiding (catch)
7375import Language.Javascript.JSaddle.Types
7476 (Object(..), JSString, JSVal)
75−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
77+#ifdef ghcjs_HOST_OS
7678import Language.Javascript.JSaddle.Types
7779 (MutableJSArray)
7880import GHCJS.Types (JSVal(..), isNull, isUndefined)
@@ -102,9 +104,14 @@ import Language.Javascript.JSaddle.Classes
102104 (MakeObject(..), ToJSString(..), ToJSVal(..))
103105import Language.Javascript.JSaddle.String (strToText, textToStr)
104106import Language.Javascript.JSaddle.Arguments (MakeArgs(..))
105−import Data.Word (Word32, Word64)
107+import Data.Word (Word32, Word, Word64)
106108import Data.Int (Int32, Int64)
107109
110+-- $setup
111+-- >>> import Language.Javascript.JSaddle.Test (testJSaddle)
112+-- >>> import Language.Javascript.JSaddle.Monad (catch)
113+-- >>> import Language.Javascript.JSaddle.Exception (JSException(..))
114+
108115data JSNull = JSNull -- ^ Type that represents a value that can only be null.
109116 -- Haskell of course has no null so we are adding this type.
110117type JSUndefined = () -- ^ A type that can only be undefined in JavaScript. Using ()
@@ -122,7 +129,16 @@ data JSValue = ValNull -- ^ null
122129 | ValNumber Double -- ^ a number
123130 | ValString Text -- ^ a string
124131 | ValObject Object -- ^ an object
125−-- deriving(Show, Eq)
132+
133+-- | Show a JSValue but just say "object" if the value is a JavaScript object.
134+showJSValue :: JSValue -> String
135+showJSValue ValNull = "null"
136+showJSValue ValUndefined = "undefined"
137+showJSValue (ValBool True) = "true"
138+showJSValue (ValBool False) = "false"
139+showJSValue (ValNumber x) = show x
140+showJSValue (ValString s) = show s
141+showJSValue (ValObject _) = "object"
126142
127143-- | Given a JavaScript value get its boolean value.
128144-- All values in JavaScript convert to bool.
@@ -144,7 +160,7 @@ data JSValue = ValNull -- ^ null
144160-- >>> testJSaddle $ valToBool "1"
145161-- true
146162valToBool :: ToJSVal value => value -> JSM Bool
147−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
163+#ifdef ghcjs_HOST_OS
148164valToBool value = isTruthy <$> toJSVal value
149165#else
150166valToBool value = do
@@ -174,18 +190,16 @@ valToBool value = do
174190-- >>> testJSaddle $ show <$> valToNumber "1"
175191-- 1.0
176192valToNumber :: ToJSVal value => value -> JSM Double
177−#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
193+#ifdef ghcjs_HOST_OS
178194valToNumber value = jsrefToNumber <$> toJSVal value
179195{-# INLINE valToNumber #-}
180196foreign import javascript unsafe "$r = Number($1);" jsrefToNumber :: JSVal -> Double
181−#elif defined(USE_WEBKIT)
197+#else
182198valToNumber value = do
183199 gctxt <- ask
184200 withToJSVal value $ \rval ->
185201 rethrow $ liftIO . jsvaluetonumber gctxt rval
186202{-# INLINE valToNumber #-}
187−#else
188−valToNumber = undefined
189203#endif
190204
191205-- | Given a JavaScript value get its string value (as a JavaScript string).
@@ -208,18 +222,16 @@ valToNumber = undefined
208222-- >>> testJSaddle $ valToStr "1" >>= strToText
209223-- 1
210224valToStr :: ToJSVal value => value -> JSM JSString
211−#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
225+#ifdef ghcjs_HOST_OS
212226valToStr value = jsrefToString <$> toJSVal value
213227{-# INLINE valToStr #-}
214228foreign import javascript unsafe "$r = $1.toString();" jsrefToString :: JSVal -> JSString
215−#elif defined(USE_WEBKIT)
229+#else
216230valToStr value = do
217231 gctxt <- ask
218232 withToJSVal value $ \rval ->
219− (rethrow $ liftIO . jsvaluetostringcopy gctxt rval) >>= wrapJSString
233+ rethrow (liftIO . jsvaluetostringcopy gctxt rval) >>= wrapJSString
220234{-# INLINE valToStr #-}
221−#else
222−valToStr = undefined
223235#endif
224236
225237-- | Given a JavaScript value get its string value (as a Haskell 'Text').
@@ -267,18 +279,16 @@ valToText jsvar = valToStr jsvar >>= strToText
267279-- >>> testJSaddle $ obj >>= valToJSON 0 >>= strToText
268280-- {}
269281valToJSON :: ToJSVal value => Word -> value -> JSM JSString
270−#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
282+#ifdef ghcjs_HOST_OS
271283valToJSON indent value = jsrefToJSON <$> toJSVal value
272284{-# INLINE valToJSON #-}
273285foreign import javascript unsafe "$r = JSON.stringify($1);" jsrefToJSON :: JSVal -> JSString
274−#elif defined(USE_WEBKIT)
286+#else
275287valToJSON indent value = do
276288 gctxt <- ask
277289 withToJSVal value $ \rval ->
278− (rethrow $ liftIO . jsvaluecreatejsonstring gctxt rval (fromIntegral indent)) >>= wrapJSString
290+ rethrow (liftIO . jsvaluecreatejsonstring gctxt rval (fromIntegral indent)) >>= wrapJSString
279291{-# INLINE valToJSON #-}
280−#else
281−valToJSON = undefined
282292#endif
283293
284294-- | Given a JavaScript value get its object value.
@@ -302,12 +312,12 @@ valToJSON = undefined
302312-- 1
303313valToObject :: ToJSVal value => value -> JSM Object
304314valToObject value = Object <$>
305−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
315+#ifdef ghcjs_HOST_OS
306316 toJSVal value
307317#else
308318 do gctxt <- ask
309319 withToJSVal value $ \rval ->
310− (rethrow $ liftIO . jsvaluetoobject gctxt rval) >>= makeNewJSVal
320+ rethrow (liftIO . jsvaluetoobject gctxt rval) >>= makeNewJSVal
311321#endif
312322{-# INLINE valToObject #-}
313323
@@ -341,7 +351,7 @@ instance ToJSVal v => ToJSVal (JSM v) where
341351----------- null ---------------
342352-- | Make a @null@ JavaScript value
343353valMakeNull :: JSM JSVal
344−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
354+#ifdef ghcjs_HOST_OS
345355valMakeNull = return jsNull
346356#else
347357valMakeNull = ask >>= (liftIO . jsvaluemakenull) >>= makeNewJSVal
@@ -366,7 +376,7 @@ instance ToJSVal a => ToJSVal (Maybe a) where
366376
367377-- | Test a JavaScript value to see if it is @null@
368378valIsNull :: ToJSVal value => value -> JSM Bool
369−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
379+#ifdef ghcjs_HOST_OS
370380valIsNull value = isNull <$> toJSVal value
371381#else
372382valIsNull value = do
@@ -379,7 +389,7 @@ valIsNull value = do
379389----------- undefined ---------------
380390-- | Make an @undefined@ JavaScript value
381391valMakeUndefined :: JSM JSVal
382−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
392+#ifdef ghcjs_HOST_OS
383393valMakeUndefined = return jsUndefined
384394#else
385395valMakeUndefined = ask >>= (liftIO . jsvaluemakeundefined) >>= makeNewJSVal
@@ -403,7 +413,7 @@ instance MakeArgs () where
403413
404414-- | Test a JavaScript value to see if it is @undefined@
405415valIsUndefined :: ToJSVal value => value -> JSM Bool
406−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
416+#ifdef ghcjs_HOST_OS
407417valIsUndefined value = isUndefined <$> toJSVal value
408418#else
409419valIsUndefined value = do
@@ -439,12 +449,12 @@ maybeNullOrUndefined' f value = do
439449----------- booleans ---------------
440450-- | Make a JavaScript boolean value
441451valMakeBool :: Bool -> JSM JSVal
442−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
452+#ifdef ghcjs_HOST_OS
443453valMakeBool b = return $ toJSBool b
444454#else
445455valMakeBool b = do
446456 gctxt <- ask
447− (liftIO $ jsvaluemakeboolean gctxt b) >>= makeNewJSVal
457+ liftIO (jsvaluemakeboolean gctxt b) >>= makeNewJSVal
448458#endif
449459{-# INLINE valMakeBool #-}
450460
@@ -461,12 +471,12 @@ instance MakeArgs Bool where
461471----------- numbers ---------------
462472-- | Make a JavaScript number
463473valMakeNumber :: Double -> JSM JSVal
464−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
474+#ifdef ghcjs_HOST_OS
465475valMakeNumber n = liftIO $ GHCJS.toJSVal n
466476#else
467477valMakeNumber n = do
468478 gctxt <- ask
469− (liftIO $ jsvaluemakenumber gctxt n) >>= makeNewJSVal
479+ liftIO (jsvaluemakenumber gctxt n) >>= makeNewJSVal
470480#endif
471481{-# INLINE valMakeNumber #-}
472482
@@ -510,25 +520,25 @@ instance MakeArgs Double where
510520
511521-- | Make a JavaScript string from `Text`
512522valMakeText :: Text -> JSM JSVal
513−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
523+#ifdef ghcjs_HOST_OS
514524valMakeText = return . pToJSVal . textToJSString
515525#else
516526valMakeText text = do
517527 gctxt <- ask
518528 withJSString (textToStr text) $ \s ->
519− (liftIO $ jsvaluemakestring gctxt s) >>= makeNewJSVal
529+ liftIO (jsvaluemakestring gctxt s) >>= makeNewJSVal
520530#endif
521531{-# INLINE valMakeText #-}
522532
523533-- | Make a JavaScript string from `JSString`
524534valMakeString :: JSString -> JSM JSVal
525−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
535+#ifdef ghcjs_HOST_OS
526536valMakeString = return . pToJSVal
527537#else
528538valMakeString str = do
529539 gctxt <- ask
530540 withJSString str $ \s ->
531− (liftIO $ jsvaluemakestring gctxt s) >>= makeNewJSVal
541+ liftIO (jsvaluemakestring gctxt s) >>= makeNewJSVal
532542#endif
533543{-# INLINE valMakeString #-}
534544
@@ -567,26 +577,26 @@ instance ToJSString String where
567577
568578-- | Derefernce a value reference.
569579--
570−-- >>> testJSaddle $ show <$> deRefVal JSNull
580+-- >>> testJSaddle $ showJSValue <$> deRefVal JSNull
571581-- ValNull
572−-- >>> testJSaddle $ show <$> deRefVal ()
582+-- >>> testJSaddle $ showJSValue <$> deRefVal ()
573583-- ValUndefined
574−-- >>> testJSaddle $ show <$> deRefVal True
584+-- >>> testJSaddle $ showJSValue <$> deRefVal True
575585-- ValBool True
576−-- >>> testJSaddle $ show <$> deRefVal False
586+-- >>> testJSaddle $ showJSValue <$> deRefVal False
577587-- ValBool False
578−-- >>> testJSaddle $ show <$> deRefVal (1.0 :: Double)
588+-- >>> testJSaddle $ showJSValue <$> deRefVal (1.0 :: Double)
579589-- ValNumber 1.0
580−-- >>> testJSaddle $ show <$> deRefVal (0.0 :: Double)
590+-- >>> testJSaddle $ showJSValue <$> deRefVal (0.0 :: Double)
581591-- ValNumber 0.0
582−-- >>> testJSaddle $ show <$> deRefVal ""
592+-- >>> testJSaddle $ showJSValue <$> deRefVal ""
583593-- ValString ""
584−-- >>> testJSaddle $ show <$> deRefVal "1"
594+-- >>> testJSaddle $ showJSValue <$> deRefVal "1"
585595-- ValString "1"
586−-- >>> testJSaddle $ show <$> valToObject True >>= deRefVal
596+-- >>> testJSaddle $ showJSValue <$> valToObject True >>= deRefVal
587597-- ValObject 0x...
588598deRefVal :: ToJSVal value => value -> JSM JSValue
589−#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
599+#ifdef ghcjs_HOST_OS
590600deRefVal value = do
591601 valref <- toJSVal value
592602 case (jsrefGetType valref :: Int) of
@@ -602,20 +612,18 @@ foreign import javascript unsafe "$r = ($1 === undefined)?0:\
602612 (typeof $1===\"number\")?3:\
603613 (typeof $1===\"string\")?4:\
604614 (typeof $1===\"object\")?5:-1;" jsrefGetType :: JSVal -> Int
605−#elif defined(USE_WEBKIT)
615+#else
606616deRefVal value = do
607617 gctxt <- ask
608618 v <- toJSVal value
609619 withJSVal v $ \rval ->
610− (liftIO $ jsvaluegettype gctxt rval) >>= \case
620+ liftIO (jsvaluegettype gctxt rval) >>= \case
611621 Kjstypenull -> return ValNull
612622 Kjstypeundefined -> return ValUndefined
613623 Kjstypeboolean -> ValBool <$> valToBool v
614624 Kjstypenumber -> ValNumber <$> valToNumber v
615625 Kjstypestring -> ValString <$> valToText v
616626 Kjstypeobject -> ValObject <$> valToObject v
617−#else
618−deRefVal = undefined
619627#endif
620628
621629-- | Make a JavaScript value out of a 'JSValue' ADT.
@@ -654,7 +662,7 @@ instance MakeArgs JSValue where
654662-- makeObjectRef _ = Object <$> valMakeNull
655663-- {-# INLINE makeObjectRef #-}
656664
657−#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
665+#ifdef ghcjs_HOST_OS
658666foreign import javascript unsafe
659667 "$1===$2" jsvalueisstrictequal :: JSVal -> JSVal -> Bool
660668#endif
@@ -663,7 +671,7 @@ strictEqual :: (ToJSVal a, ToJSVal b) => a -> b -> JSM Bool
663671strictEqual a b = do
664672 aval <- toJSVal a
665673 bval <- toJSVal b
666−#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
674+#ifdef ghcjs_HOST_OS
667675 return $ jsvalueisstrictequal aval bval
668676#else
669677 gctxt <- ask
@@ -672,7 +680,7 @@ strictEqual a b = do
672680 liftIO $ jsvalueisstrictequal gctxt aref bref
673681#endif
674682
675−#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
683+#ifdef ghcjs_HOST_OS
676684foreign import javascript unsafe "\
677685 try {\
678686 $r = $1 instanceof $2\
@@ -687,7 +695,7 @@ instanceOf :: (ToJSVal value, MakeObject constructor) => value -> constructor ->
687695instanceOf value constructor = do
688696 v <- toJSVal value
689697 c <- makeObject constructor
690−#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
698+#ifdef ghcjs_HOST_OS
691699 rethrow $ return . js_isInstanceOf v c
692700#else
693701 gctxt <- ask