@@ -27,6 +27,7 @@ module Language.Javascript.JSaddle.Object (
2727 , (!)
2828 , (!!)
2929 , js
30+ , jss
3031 , JSF(..)
3132 , jsf
3233 , js0
@@ -36,12 +37,21 @@ module Language.Javascript.JSaddle.Object (
3637 , js4
3738 , js5
3839 , jsg
40+ , jsgf
41+ , jsg0
42+ , jsg1
43+ , jsg2
44+ , jsg3
45+ , jsg4
46+ , jsg5
3947
4048 -- * Setting the value of a property
4149 , (<#)
50+ , (<##)
4251
4352 -- * Calling JavaSctipt
4453 , (#)
54+ , (##)
4555 , new
4656 , call
4757 , obj
@@ -108,10 +118,8 @@ import Foreign (peekArray, nullPtr, withArrayLen)
108118import Language.Javascript.JSaddle.Exception (rethrow)
109119import Language.Javascript.JSaddle.Value
110120 (JSUndefined, valMakeUndefined, valToObject)
111−import Language.Javascript.JSaddle.PropRef (JSPropRef(..))
112121import Language.Javascript.JSaddle.Classes
113− (MakeValueRef(..), MakeStringRef(..), MakeArgRefs(..), MakePropRef(..),
114− MakeObject(..))
122+ (MakeValueRef(..), MakeStringRef(..), MakeArgRefs(..), MakeObject(..))
115123import Language.Javascript.JSaddle.Monad
116124 (JSM)
117125import Control.Monad.Trans.Reader (runReaderT, ask)
@@ -136,38 +144,34 @@ instance MakeObject v => MakeObject (JSM v) where
136144 makeObject v = v >>= makeObject
137145 {-# INLINE makeObject #-}
138146
139−-- | Lookup a property based on its name. This function just constructs a JSPropRef
140−-- the lookup is delayed until we use the JSPropRef. This makes it a bit lazy compared
141−-- to JavaScript's @.@ operator.
147+-- | Lookup a property based on its name.
142148--
143149-- >>> testJSaddle $ eval "'Hello World'.length"
144150-- >>> testJSaddle $ val "Hello World" ! "length"
145151-- 11
146152(!) :: (MakeObject this, MakeStringRef name)
147− => this -- ^ Object to look on
148− -> name -- ^ Name of the property to find
149− -> JSM JSPropRef -- ^ Property reference
153+ => this -- ^ Object to look on
154+ -> name -- ^ Name of the property to find
155+ -> JSM JSValueRef -- ^ Property reference
150156this ! name = do
151157 rthis <- makeObject this
152− return (JSPropRef rthis rname)
158+ rethrow $ objGetPropertyByName rthis rname
153159 where
154160 rname = makeStringRef name
155161{-# INLINE (!) #-}
156162
157−-- | Lookup a property based on its index. This function just constructs a JSPropRef
158−-- the lookup is delayed until we use the JSPropRef. This makes it a bit lazy compared
159−-- to JavaScript's @[]@ operator.
163+-- | Lookup a property based on its index.
160164--
161165-- >>> testJSaddle $ eval "'Hello World'[6]"
162166-- >>> testJSaddle $ val "Hello World" !! 6
163167-- W
164168(!!) :: (MakeObject this)
165− => this -- ^ Object to look on
166− -> Index -- ^ Index of the property to lookup
167− -> JSM JSPropRef -- ^ Property reference
169+ => this -- ^ Object to look on
170+ -> Index -- ^ Index of the property to lookup
171+ -> JSM JSValueRef -- ^ Property reference
168172this !! index = do
169173 rthis <- makeObject this
170− return (JSPropIndexRef rthis index)
174+ rethrow $ objGetPropertyAtIndex rthis index
171175{-# INLINE (!!) #-}
172176
173177-- | Makes a getter for a particular property name.
@@ -179,25 +183,37 @@ this !! index = do
179183-- 11
180184js :: (MakeObject s, MakeStringRef name)
181185 => name -- ^ Name of the property to find
182− -> IndexPreservingGetter s (JSM JSPropRef)
186+ -> IndexPreservingGetter s (JSM JSValueRef)
183187js name = to (!name)
184188{-# INLINE js #-}
185189
186−-- | Java script function applications have this type
187−type JSF = forall o . MakeObject o => IndexPreservingGetter o (JSM JSValueRef)
190+-- | Makes a setter for a particular property name.
191+--
192+-- > jss name = to (<#name)
193+--
194+-- >>> testJSaddle $ eval "'Hello World'.length"
195+-- >>> testJSaddle $ val "Hello World" ^. js "length"
196+-- 11
197+jss :: (MakeStringRef name, MakeValueRef val)
198+ => name -- ^ Name of the property to find
199+ -> val
200+ -> forall o . MakeObject o => IndexPreservingGetter o (JSM ())
201+jss name val = to (\o -> o <# name $ val)
202+{-# INLINE jss #-}
188203
189204-- | Handy way to call a function
190205--
191−-- > jsf name = js name . to (# args)
206+-- > jsf name = to (\o -> o # name $ args)
192207--
193208-- >>> testJSaddle $ val "Hello World" ^. jsf "indexOf" ["World"]
194209-- 6
195210jsf :: (MakeStringRef name, MakeArgRefs args) => name -> args -> JSF
196−jsf name args = function . to (# args)
197− where
198− function = js name
211+jsf name args = to (\o -> o # name $ args)
199212{-# INLINE jsf #-}
200213
214+-- | Java script function applications have this type
215+type JSF = forall o . MakeObject o => IndexPreservingGetter o (JSM JSValueRef)
216+
201217-- | Handy way to call a function that expects no arguments
202218--
203219-- > js0 name = jsf name ()
@@ -249,41 +265,126 @@ js5 name a0 a1 a2 a3 a4 = jsf name (a0, a1, a2, a3, a4)
249265-- >>> testJSaddle $ eval "w = console; w.log('Hello World')"
250266-- >>> testJSaddle $ do w <- jsg "console"; w ^. js "log" # ["Hello World"]
251267-- 11
252−jsg :: MakeStringRef a => a -> JSM JSPropRef
268+jsg :: MakeStringRef a => a -> JSM JSValueRef
253269jsg name = global ! name
254270{-# INLINE jsg #-}
255271
272+-- | Handy way to call a function
273+--
274+-- > jsgf name = jsg name . to (# args)
275+--
276+-- >>> testJSaddle $ jsf "globalFunc" ["World"]
277+-- 6
278+jsgf :: (MakeStringRef name, MakeArgRefs args) => name -> args -> JSM JSValueRef
279+jsgf name = global # name
280+{-# INLINE jsgf #-}
281+
282+-- | Handy way to call a function that expects no arguments
283+--
284+-- > jsg0 name = jsgf name ()
285+--
286+-- >>> testJSaddle $ js0 "globalFunc"
287+-- hello world
288+jsg0 :: (MakeStringRef name) => name -> JSM JSValueRef
289+jsg0 name = jsgf name ()
290+{-# INLINE jsg0 #-}
291+
292+-- | Handy way to call a function that expects one argument
293+--
294+-- > jsg1 name a0 = jsgf name [a0]
295+--
296+-- >>> testJSaddle $ jsg1 "globalFunc" "World"
297+-- 6
298+jsg1 :: (MakeStringRef name, MakeValueRef a0) => name -> a0 -> JSM JSValueRef
299+jsg1 name a0 = jsgf name [a0]
300+{-# INLINE jsg1 #-}
301+
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)
305+{-# INLINE jsg2 #-}
306+
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)
311+{-# INLINE jsg3 #-}
312+
313+-- | Handy way to call a function that expects four arguments
314+jsg4 :: (MakeStringRef name, MakeValueRef a0, MakeValueRef a1, MakeValueRef a2,
315+ MakeValueRef a3)
316+ => name -> a0 -> a1 -> a2 -> a3 -> JSM JSValueRef
317+jsg4 name a0 a1 a2 a3 = jsgf name (a0, a1, a2, a3)
318+{-# INLINE jsg4 #-}
319+
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)
325+{-# INLINE jsg5 #-}
326+
256327-- | Call a JavaScript function
257328--
258329-- >>> testJSaddle $ eval "'Hello World'.indexOf('World')"
259−-- >>> testJSaddle $ val "Hello World" ! "indexOf" # ["World"]
330+-- >>> testJSaddle $ val "Hello World" # "indexOf" $ ["World"]
260331-- 6
261332infixr 2 #
262−(#) :: (MakePropRef prop, MakeArgRefs args)
263− => prop -> args -> JSM JSValueRef
264−prop # args = do
265− rprop <- makePropRef prop
266− (this, f) <- objGetProperty' rprop
333+(#) :: (MakeObject this, MakeStringRef name, MakeArgRefs args)
334+ => this -> name -> args -> JSM JSValueRef
335+(#) this name args = do
336+ rthis <- makeObject this
337+ f <- rethrow $ objGetPropertyByName rthis name
267338 f' <- valToObject f
268− rethrow $ objCallAsFunction f' this args
339+ rethrow $ objCallAsFunction f' rthis args
269340{-# INLINE (#) #-}
270341
271342-- | Call a JavaScript function
272343--
344+-- >>> testJSaddle $ eval "something[6]('World')"
345+-- >>> testJSaddle $ val something ## 6 ["World"]
346+infixr 2 ##
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
352+ f' <- valToObject f
353+ rethrow $ objCallAsFunction f' rthis args
354+{-# INLINE (##) #-}
355+
356+-- | Set a JavaScript property
357+--
273358-- >>> 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"}
275360-- 1
276−infixr 0 <#
277−(<#) :: (MakePropRef prop, MakeValueRef val)
278− => prop -- ^ Property to set
279− -> val -- ^ Value to set it to
280− -> JSM JSPropRef -- ^ Reference to the property set
281−prop <# val = do
282− p <- makePropRef prop
283− objSetProperty p val
284− return p
361+infixr 1 <#
362+(<#) :: (MakeObject this, MakeStringRef name, MakeValueRef val)
363+ => this -- ^ Object to set the property on
364+ -> name -- ^ Name of the property to set
365+ -> val -- ^ Value to set it to
366+ -> JSM ()
367+(<#) this name val = do
368+ rthis <- makeObject this
369+ rethrow $ objSetPropertyByName rthis name val 0
285370{-# INLINE (<#) #-}
286371
372+-- | Set a JavaScript property
373+--
374+-- >>> testJSaddle $ eval "var j = {}; j[6] = 1; j[6]"
375+-- >>> testJSaddle $ do {j <- eval "({})"; j <## 6 1; j!!6}
376+-- 1
377+infixr 1 <##
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
382+ -> JSM ()
383+(<##) this index val = do
384+ rthis <- makeObject this
385+ rethrow $ objSetPropertyAtIndex rthis index val
386+{-# INLINE (<##) #-}
387+
287388-- | Use this to create a new JavaScript object
288389--
289390-- If you pass more than 7 arguments to a constructor for a built in
@@ -488,7 +589,7 @@ propertyNames = undefined
488589#endif
489590
490591-- | 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]
492593properties this = propertyNames this >>= mapM (this !)
493594
494595-- | Call a JavaScript object as function. Consider using '#'.