@@ -27,6 +27,7 @@ module Language.Javascript.JSaddle.Object (
@@ -36,12 +37,21 @@ module Language.Javascript.JSaddle.Object (
40 -- * Setting the value of a property
48 -- * Setting the value of a property
43 -- * Calling JavaSctipt
52 -- * Calling JavaSctipt
@@ -108,10 +118,8 @@ import Foreign (peekArray, nullPtr, withArrayLen)
108import Language.Javascript.JSaddle.Exception (rethrow)
118import Language.Javascript.JSaddle.Exception (rethrow)
109import Language.Javascript.JSaddle.Value
119import Language.Javascript.JSaddle.Value
110 (JSUndefined, valMakeUndefined, valToObject)
120 (JSUndefined, valMakeUndefined, valToObject)
111−import Language.Javascript.JSaddle.PropRef (JSPropRef(..))
112import Language.Javascript.JSaddle.Classes
121import Language.Javascript.JSaddle.Classes
113− (MakeValueRef(..), MakeStringRef(..), MakeArgRefs(..), MakePropRef(..),
122+ (MakeValueRef(..), MakeStringRef(..), MakeArgRefs(..), MakeObject(..))
115import Language.Javascript.JSaddle.Monad
123import Language.Javascript.JSaddle.Monad
117import Control.Monad.Trans.Reader (runReaderT, ask)
125import Control.Monad.Trans.Reader (runReaderT, ask)
@@ -136,38 +144,34 @@ instance MakeObject v => MakeObject (JSM v) where
136 makeObject v = v >>= makeObject
144 makeObject v = v >>= makeObject
137 {-# INLINE makeObject #-}
145 {-# INLINE makeObject #-}
139−-- | Lookup a property based on its name. This function just constructs a JSPropRef
147+-- | Lookup a property based on its name.
140−-- the lookup is delayed until we use the JSPropRef. This makes it a bit lazy compared
141−-- to JavaScript's @.@ operator.
143-- >>> testJSaddle $ eval "'Hello World'.length"
149-- >>> testJSaddle $ eval "'Hello World'.length"
144-- >>> testJSaddle $ val "Hello World" ! "length"
150-- >>> testJSaddle $ val "Hello World" ! "length"
146(!) :: (MakeObject this, MakeStringRef name)
152(!) :: (MakeObject this, MakeStringRef name)
147− => this -- ^ Object to look on
153+ => this -- ^ Object to look on
148− -> name -- ^ Name of the property to find
154+ -> name -- ^ Name of the property to find
149− -> JSM JSPropRef -- ^ Property reference
155+ -> JSM JSValueRef -- ^ Property reference
150this ! name = do
156this ! name = do
151 rthis <- makeObject this
157 rthis <- makeObject this
152− return (JSPropRef rthis rname)
158+ rethrow $ objGetPropertyByName rthis rname
154 rname = makeStringRef name
160 rname = makeStringRef name
155{-# INLINE (!) #-}
161{-# INLINE (!) #-}
157−-- | Lookup a property based on its index. This function just constructs a JSPropRef
163+-- | Lookup a property based on its index.
158−-- the lookup is delayed until we use the JSPropRef. This makes it a bit lazy compared
159−-- to JavaScript's @[]@ operator.
161-- >>> testJSaddle $ eval "'Hello World'[6]"
165-- >>> testJSaddle $ eval "'Hello World'[6]"
162-- >>> testJSaddle $ val "Hello World" !! 6
166-- >>> testJSaddle $ val "Hello World" !! 6
164(!!) :: (MakeObject this)
168(!!) :: (MakeObject this)
165− => this -- ^ Object to look on
169+ => this -- ^ Object to look on
166− -> Index -- ^ Index of the property to lookup
170+ -> Index -- ^ Index of the property to lookup
167− -> JSM JSPropRef -- ^ Property reference
171+ -> JSM JSValueRef -- ^ Property reference
168this !! index = do
172this !! index = do
169 rthis <- makeObject this
173 rthis <- makeObject this
170− return (JSPropIndexRef rthis index)
174+ rethrow $ objGetPropertyAtIndex rthis index
171{-# INLINE (!!) #-}
175{-# INLINE (!!) #-}
173-- | Makes a getter for a particular property name.
177-- | Makes a getter for a particular property name.
@@ -179,25 +183,37 @@ this !! index = do
180js :: (MakeObject s, MakeStringRef name)
184js :: (MakeObject s, MakeStringRef name)
181 => name -- ^ Name of the property to find
185 => name -- ^ Name of the property to find
182− -> IndexPreservingGetter s (JSM JSPropRef)
186+ -> IndexPreservingGetter s (JSM JSValueRef)
183js name = to (!name)
187js name = to (!name)
184{-# INLINE js #-}
188{-# INLINE js #-}
186−-- | Java script function applications have this type
190+-- | Makes a setter for a particular property name.
192+-- > jss name = to (<#name)
194+-- >>> testJSaddle $ eval "'Hello World'.length"
195+-- >>> testJSaddle $ val "Hello World" ^. js "length"
197+jss :: (MakeStringRef name, MakeValueRef val)
198+ => name -- ^ Name of the property to find
187−type JSF = forall o . MakeObject o => IndexPreservingGetter o (JSM JSValueRef)
200+ -> forall o . MakeObject o => IndexPreservingGetter o (JSM ())
201+jss name val = to (\o -> o <# name $ val)
189-- | Handy way to call a function
204-- | Handy way to call a function
191−-- > jsf name = js name . to (# args)
206+-- > jsf name = to (\o -> o # name $ args)
193-- >>> testJSaddle $ val "Hello World" ^. jsf "indexOf" ["World"]
208-- >>> testJSaddle $ val "Hello World" ^. jsf "indexOf" ["World"]
195jsf :: (MakeStringRef name, MakeArgRefs args) => name -> args -> JSF
210jsf :: (MakeStringRef name, MakeArgRefs args) => name -> args -> JSF
196−jsf name args = function . to (# args)
211+jsf name args = to (\o -> o # name $ args)
199{-# INLINE jsf #-}
212{-# INLINE jsf #-}
214+-- | Java script function applications have this type
215+type JSF = forall o . MakeObject o => IndexPreservingGetter o (JSM JSValueRef)
201-- | Handy way to call a function that expects no arguments
217-- | Handy way to call a function that expects no arguments
203-- > js0 name = jsf name ()
219-- > js0 name = jsf name ()
@@ -249,41 +265,126 @@ js5 name a0 a1 a2 a3 a4 = jsf name (a0, a1, a2, a3, a4)
249-- >>> testJSaddle $ eval "w = console; w.log('Hello World')"
265-- >>> testJSaddle $ eval "w = console; w.log('Hello World')"
250-- >>> testJSaddle $ do w <- jsg "console"; w ^. js "log" # ["Hello World"]
266-- >>> testJSaddle $ do w <- jsg "console"; w ^. js "log" # ["Hello World"]
252−jsg :: MakeStringRef a => a -> JSM JSPropRef
268+jsg :: MakeStringRef a => a -> JSM JSValueRef
253jsg name = global ! name
269jsg name = global ! name
254{-# INLINE jsg #-}
270{-# INLINE jsg #-}
272+-- | Handy way to call a function
274+-- > jsgf name = jsg name . to (# args)
276+-- >>> testJSaddle $ jsf "globalFunc" ["World"]
278+jsgf :: (MakeStringRef name, MakeArgRefs args) => name -> args -> JSM JSValueRef
279+jsgf name = global # name
282+-- | Handy way to call a function that expects no arguments
284+-- > jsg0 name = jsgf name ()
286+-- >>> testJSaddle $ js0 "globalFunc"
288+jsg0 :: (MakeStringRef name) => name -> JSM JSValueRef
289+jsg0 name = jsgf name ()
292+-- | Handy way to call a function that expects one argument
294+-- > jsg1 name a0 = jsgf name [a0]
296+-- >>> testJSaddle $ jsg1 "globalFunc" "World"
298+jsg1 :: (MakeStringRef name, MakeValueRef a0) => name -> a0 -> JSM JSValueRef
299+jsg1 name a0 = jsgf name [a0]
302+-- | Handy way to call a function that expects two arguments
303+jsg2 :: (MakeStringRef name, MakeValueRef a0, MakeValueRef a1) => name -> a0 -> a1 -> JSM JSValueRef
304+jsg2 name a0 a1 = jsgf name (a0, a1)
307+-- | Handy way to call a function that expects three arguments
308+jsg3 :: (MakeStringRef name, MakeValueRef a0, MakeValueRef a1, MakeValueRef a2)
309+ => name -> a0 -> a1 -> a2 -> JSM JSValueRef
310+jsg3 name a0 a1 a2 = jsgf name (a0, a1, a2)
313+-- | Handy way to call a function that expects four arguments
314+jsg4 :: (MakeStringRef name, MakeValueRef a0, MakeValueRef a1, MakeValueRef a2,
316+ => name -> a0 -> a1 -> a2 -> a3 -> JSM JSValueRef
317+jsg4 name a0 a1 a2 a3 = jsgf name (a0, a1, a2, a3)
320+-- | Handy way to call a function that expects five arguments
321+jsg5 :: (MakeStringRef name, MakeValueRef a0, MakeValueRef a1, MakeValueRef a2,
322+ MakeValueRef a3, MakeValueRef a4)
323+ => name -> a0 -> a1 -> a2 -> a3 -> a4 -> JSM JSValueRef
324+jsg5 name a0 a1 a2 a3 a4 = jsgf name (a0, a1, a2, a3, a4)
256-- | Call a JavaScript function
327-- | Call a JavaScript function
258-- >>> testJSaddle $ eval "'Hello World'.indexOf('World')"
329-- >>> testJSaddle $ eval "'Hello World'.indexOf('World')"
259−-- >>> testJSaddle $ val "Hello World" ! "indexOf" # ["World"]
330+-- >>> testJSaddle $ val "Hello World" # "indexOf" $ ["World"]
261infixr 2 #
332infixr 2 #
262−(#) :: (MakePropRef prop, MakeArgRefs args)
333+(#) :: (MakeObject this, MakeStringRef name, MakeArgRefs args)
263− => prop -> args -> JSM JSValueRef
334+ => this -> name -> args -> JSM JSValueRef
264−prop # args = do
335+(#) this name args = do
265− rprop <- makePropRef prop
336+ rthis <- makeObject this
266− (this, f) <- objGetProperty' rprop
337+ f <- rethrow $ objGetPropertyByName rthis name
267 f' <- valToObject f
338 f' <- valToObject f
268− rethrow $ objCallAsFunction f' this args
339+ rethrow $ objCallAsFunction f' rthis args
269{-# INLINE (#) #-}
340{-# INLINE (#) #-}
271-- | Call a JavaScript function
342-- | Call a JavaScript function
344+-- >>> testJSaddle $ eval "something[6]('World')"
345+-- >>> testJSaddle $ val something ## 6 ["World"]
347+(##) :: (MakeObject this, MakeArgRefs args)
348+ => this -> Index -> args -> JSM JSValueRef
349+(##) this index args = do
350+ rthis <- makeObject this
351+ f <- rethrow $ objGetPropertyAtIndex rthis index
353+ rethrow $ objCallAsFunction f' rthis args
356+-- | Set a JavaScript property
273-- >>> testJSaddle $ eval "var j = {}; j.x = 1; j.x"
358-- >>> testJSaddle $ eval "var j = {}; j.x = 1; j.x"
274−-- >>> testJSaddle $ do {j <- eval "({})"; j!"x" <# 1; j!"x"}
359+-- >>> testJSaddle $ do {j <- eval "({})"; j <# "x" 1; j!"x"}
276−infixr 0 <#
361+infixr 1 <#
277−(<#) :: (MakePropRef prop, MakeValueRef val)
362+(<#) :: (MakeObject this, MakeStringRef name, MakeValueRef val)
278− => prop -- ^ Property to set
363+ => this -- ^ Object to set the property on
364+ -> name -- ^ Name of the property to set
279− -> val -- ^ Value to set it to
365+ -> val -- ^ Value to set it to
280− -> JSM JSPropRef -- ^ Reference to the property set
366+ -> JSM ()
281−prop <# val = do
367+(<#) this name val = do
282− p <- makePropRef prop
368+ rthis <- makeObject this
283− objSetProperty p val
369+ rethrow $ objSetPropertyByName rthis name val 0
285{-# INLINE (<#) #-}
370{-# INLINE (<#) #-}
372+-- | Set a JavaScript property
374+-- >>> testJSaddle $ eval "var j = {}; j[6] = 1; j[6]"
375+-- >>> testJSaddle $ do {j <- eval "({})"; j <## 6 1; j!!6}
378+(<##) :: (MakeObject this, MakeValueRef val)
379+ => this -- ^ Object to set the property on
380+ -> Index -- ^ Index of the property to set
381+ -> val -- ^ Value to set it to
383+(<##) this index val = do
384+ rthis <- makeObject this
385+ rethrow $ objSetPropertyAtIndex rthis index val
287-- | Use this to create a new JavaScript object
388-- | Use this to create a new JavaScript object
289-- If you pass more than 7 arguments to a constructor for a built in
390-- If you pass more than 7 arguments to a constructor for a built in
@@ -488,7 +589,7 @@ propertyNames = undefined
490-- | Get a list containing references to all the properties present on a given object
591-- | Get a list containing references to all the properties present on a given object
491−properties :: MakeObject this => this -> JSM [JSPropRef]
592+properties :: MakeObject this => this -> JSM [JSValueRef]
492properties this = propertyNames this >>= mapM (this !)
593properties this = propertyNames this >>= mapM (this !)
494-- | Call a JavaScript object as function. Consider using '#'.
595-- | Call a JavaScript object as function. Consider using '#'.