{-# LANGUAGE GeneralizedNewtypeDeriving #-} module JavaScript.Extras ( strval , Property , getProperty , setProperty , PureJSVal(..) , toMaybeJSObject , toJSObject ) where import Data.Foldable import qualified Data.JSString as J import qualified GHCJS.Marshal.Pure as J import qualified GHCJS.Types as J import qualified JavaScript.Object as JO -- | This makes it easier to use OverloadedStrings with inputs that accept a JSVal that could be a JSString strval :: J.JSString -> J.JSVal strval = J.jsval type Property = (J.JSString, J.JSVal) -- | throws an exception if undefined or null foreign import javascript unsafe "$2[$1]" js_unsafeGetProperty :: J.JSString -> J.JSVal -> IO J.JSVal -- | throws an exception if undefined or null foreign import javascript unsafe "$3[$1] = $2;" js_unsafeSetProperty :: J.JSString -> J.JSVal -> J.JSVal -> IO () -- | get a property of any JSVal. If a null or undefined is queried, the result will also be null getProperty :: J.JSString -> J.JSVal -> IO J.JSVal getProperty k x = let k' = J.pToJSVal k in if J.isUndefined x || J.isNull x || J.isUndefined k' || J.isNull k' then pure J.nullRef else js_unsafeGetProperty k x -- | set a property of any JSVal setProperty :: Property -> J.JSVal -> IO () setProperty (k, v) x = let k' = J.pToJSVal k in if J.isUndefined x || J.isNull x || J.isUndefined k' || J.isNull k' then pure () else js_unsafeSetProperty k v x -- | This is to enable conversion between equivalent classes 'IsJSVal' and 'PToJSVal' -- So you can convert ((PureJSVal Object) to JSVal with pToJSVal without requiring IO) newtype PureJSVal a = PureJSVal a deriving J.IsJSVal instance J.IsJSVal a => J.PToJSVal (PureJSVal a) where pToJSVal (PureJSVal a) = J.jsval a toMaybeJSObject :: [Property] -> IO (Maybe JO.Object) toMaybeJSObject [] = pure Nothing toMaybeJSObject xs = Just <$> toJSObject xs toJSObject :: [Property] -> IO JO.Object toJSObject [] = JO.create toJSObject xs = do obj <- JO.create traverse_ (\(k, v) -> JO.unsafeSetProp k v obj) xs pure obj