{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeSynonymInstances #-} #if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT) {-# LANGUAGE ForeignFunctionInterface, JavaScriptFFI #-} #endif ----------------------------------------------------------------------------- -- -- Module : Language.Javascript.JSaddle.Properties -- Copyright : (c) Hamish Mackenzie -- License : MIT -- -- Maintainer : Hamish Mackenzie -- -- | Low level JavaScript object property access. In most cases you -- should use "Language.Javascript.JSaddle.Object" instead. -- -- This module is mostly here to implement functions needed to use -- 'JSPropRef'. -- ----------------------------------------------------------------------------- module Language.Javascript.JSaddle.Properties ( -- * Propery Reference JSPropRef(..) , MakePropRef(..) -- * Getting Property Values , objGetPropertyByName , objGetPropertyAtIndex , objGetProperty , objGetProperty' -- * Setting Property Values , objSetPropertyByName , objSetPropertyAtIndex , objSetProperty ) where import Control.Applicative ((<$>)) import Language.Javascript.JSaddle.PropRef (JSPropRef(..)) import Language.Javascript.JSaddle.Classes (MakePropRef(..), MakeObjectRef(..), MakeValueRef(..), MakeArgRefs(..), MakeStringRef(..)) import Language.Javascript.JSaddle.Monad (JSM) import Language.Javascript.JSaddle.Types (JSValueRefRef, JSObjectRef, JSPropertyAttributes, Index(..), JSStringRef) #if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT) #else import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSObjectRef (jsobjectgetpropertyatindex, jsobjectgetproperty, jsobjectsetpropertyatindex, jsobjectsetproperty, JSPropertyAttributes) #endif import Control.Monad.Trans.Reader (ask) import Control.Monad.IO.Class (MonadIO(..)) import Language.Javascript.JSaddle.Exception (rethrow) import Language.Javascript.JSaddle.Value (JSValueRef) import Language.Javascript.JSaddle.Arguments () import Language.Javascript.JSaddle.String () -- | If we already have a JSPropRef we are fine instance MakePropRef JSPropRef where makePropRef = return -- | JSPropRef can be made by evaluating a function in 'JSM' as long -- as it returns something we can make into a JSPropRef. instance MakePropRef prop => MakePropRef (JSM prop) where makePropRef prop = prop >>= makePropRef -- | We can use a property as an object. instance MakeObjectRef JSPropRef where makeObjectRef = objGetProperty -- | We can use a property as a value. instance MakeValueRef JSPropRef where makeValueRef = objGetProperty -- | We can pass a property as the only paramter to a function. instance MakeArgRefs JSPropRef where makeArgRefs p = do rarg <- objGetProperty p return [rarg] -- | Get a property value given the object and the name of the property. objGetPropertyByName :: MakeStringRef name => JSObjectRef -- ^ object to find the property on. -> name -- ^ name of the property. -> JSValueRefRef -- ^ exception if one is raised. -> JSM JSValueRef -- ^ returns the property value. #if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI) objGetPropertyByName this name = liftIO . js_tryGetProp (makeStringRef name) this foreign import javascript unsafe "try { $r=$2[$1] } catch(e) { $3[0] = e }" js_tryGetProp :: JSStringRef -> JSObjectRef -> JSValueRefRef -> IO JSValueRef #elif defined(USE_WEBKIT) objGetPropertyByName this name exceptions = do gctxt <- ask liftIO $ jsobjectgetproperty gctxt this (makeStringRef name) exceptions #else objGetPropertyByName = undefined #endif -- | Get a property value given the object and the index of the property. objGetPropertyAtIndex :: JSObjectRef -- ^ object to find the property on. -> Index -- ^ index of the property. -> JSValueRefRef -- ^ exception if one is raised. -> JSM JSValueRef -- ^ returns the property value. #if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI) objGetPropertyAtIndex this index = liftIO . js_tryIndex index this foreign import javascript unsafe "try { $r=$2[$1] } catch(e) { $3[0] = e }" js_tryIndex :: Index -> JSObjectRef -> JSValueRefRef -> IO JSValueRef #elif defined(USE_WEBKIT) objGetPropertyAtIndex this index exceptions = do gctxt <- ask liftIO $ jsobjectgetpropertyatindex gctxt this index exceptions #else objGetPropertyAtIndex = undefined #endif -- | Gets the value of a property given a 'JSPropRef'. objGetProperty :: JSPropRef -- ^ property reference. -> JSM JSValueRef -- ^ returns the property value. objGetProperty (JSPropRef this name ) = rethrow $ objGetPropertyByName this name objGetProperty (JSPropIndexRef this index) = rethrow $ objGetPropertyAtIndex this index -- | This version of 'objGetProperty' is handy when you also need to perform. -- another operation on the object the property is on. objGetProperty' :: JSPropRef -- ^ property reference. -> JSM (JSObjectRef, JSValueRef) -- ^ returns the object and property value. objGetProperty' (JSPropRef this name) = do p <- rethrow $ objGetPropertyByName this name return (this, p) objGetProperty' (JSPropIndexRef this index) = do p <- rethrow $ objGetPropertyAtIndex this index return (this, p) -- | Set a property value given the object and the name of the property. objSetPropertyByName :: (MakeStringRef name, MakeValueRef val) => JSObjectRef -- ^ object to set the property on. -> name -- ^ name of the property. -> val -- ^ new value to set the property to. -> JSPropertyAttributes -- ^ property attributes to give the property. -> JSValueRefRef -- ^ exception if one is raised. -> JSM () #if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI) objSetPropertyByName this name val attributes exceptions = do vref <- makeValueRef val liftIO $ js_trySetProp (makeStringRef name) this vref exceptions foreign import javascript unsafe "try { $2[$1]=$3 } catch(e) { $4[0] = e }" js_trySetProp :: JSStringRef -> JSObjectRef -> JSValueRef -> JSValueRefRef -> IO () #elif defined(USE_WEBKIT) objSetPropertyByName this name val attributes exceptions = do gctxt <- ask vref <- makeValueRef val liftIO $ jsobjectsetproperty gctxt this (makeStringRef name) vref attributes exceptions #else objSetPropertyByName = undefined #endif -- | Set a property value given the object and the index of the property. objSetPropertyAtIndex :: (MakeValueRef val) => JSObjectRef -- ^ object to find property on. -> Index -- ^ index of the property. -> val -- ^ new value to set the property to. -> JSValueRefRef -- ^ exception if one is raised. -> JSM () #if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI) objSetPropertyAtIndex this index val exceptions = do vref <- makeValueRef val liftIO $ js_trySetAtIndex index this vref exceptions foreign import javascript unsafe "try { $2[$1]=$3 } catch(e) { $4[0] = e }" js_trySetAtIndex :: Index -> JSObjectRef -> JSValueRef -> JSValueRefRef -> IO () #elif defined(USE_WEBKIT) objSetPropertyAtIndex this index val exceptions = do gctxt <- ask vref <- makeValueRef val liftIO $ jsobjectsetpropertyatindex gctxt this index vref exceptions #else objSetPropertyAtIndex = undefined #endif -- | Sets the value of a property given a 'JSPropRef'. objSetProperty :: (MakeValueRef val) => JSPropRef -- ^ property reference. -> val -- ^ new value to set the property to. -> JSM () objSetProperty (JSPropRef this name ) val = rethrow $ objSetPropertyByName this name val 0 objSetProperty (JSPropIndexRef this index) val = rethrow $ objSetPropertyAtIndex this index val