on master help sign in
Change the way properties work (remove JSPropRef)
commit4c3bedd22f1fbd6b5cecba151a08a5afd17c3995 authorHamish Mackenzie <Hamish.K.Mackenzie@googlemail.com> dateMon 9 Nov 2015, 04:57 (11 years ago) parenta657c4c
6 files changed+150−147
jsaddle.cabal−1 src/Language/Javascript/JSaddle/Classes.hs−6 src/Language/Javascript/JSaddle/Object.hs+144−43 src/Language/Javascript/JSaddle/PropRef.hs−25 src/Language/Javascript/JSaddle/Properties.hs+2−72 src/Language/Javascript/JSaddle/Value.hs+4
jsaddle.cabal−1
@@ -58,7 +58,6 @@ library
5858 buildable: True
5959 default-language: Haskell2010
6060 hs-source-dirs: src
61− other-modules: Language.Javascript.JSaddle.PropRef
6261 ghc-options: -ferror-spans
6362
6463test-suite test-tool
src/Language/Javascript/JSaddle/Classes.hs−6
@@ -18,14 +18,12 @@ module Language.Javascript.JSaddle.Classes (
1818 , MakeStringRef(..)
1919 , MakeArgRefs(..)
2020 , MakeObject(..)
21− , MakePropRef(..)
2221) where
2322
2423import Control.Monad.IO.Class (MonadIO)
2524import Language.Javascript.JSaddle.Types
2625 (Object(..), JSStringRef, JSValueRef)
2726import Language.Javascript.JSaddle.Monad (JSM)
28−import Language.Javascript.JSaddle.PropRef (JSPropRef)
2927
3028-- | Anything that can be used to make a JavaScript value reference
3129class MakeValueRef a where
@@ -44,10 +42,6 @@ class MakeArgRefs this where
4442class MakeObject this where
4543 makeObject :: this -> JSM Object
4644
47−-- | Anything that can be used to make a JavaScript property reference
48−class MakePropRef this where
49− makePropRef :: this -> JSM JSPropRef
50−
5145instance MakeValueRef Object where
5246 makeValueRef (Object r) = return r
5347 {-# INLINE makeValueRef #-}
src/Language/Javascript/JSaddle/Object.hs+144−43
@@ -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 '#'.
src/Language/Javascript/JSaddle/PropRef.hsdeleted−25
@@ -1,25 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.Javascript.JSaddle.PropRef
4−-- Copyright : (c) Hamish Mackenzie
5−-- License : MIT
6−--
7−-- Maintainer : Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
8−--
9−-- | Implements a reference to a property
10−--
11−-----------------------------------------------------------------------------
12−
13−module Language.Javascript.JSaddle.PropRef (
14− JSPropRef(..)
15−) where
16−
17−import Language.Javascript.JSaddle.Types
18− (JSStringRef, Object, Index)
19−
20−-- | A reference to a property.
21−-- Implemented as a reference to an object and something to find the property.
22−data JSPropRef = JSPropRef Object JSStringRef -- ^ Object and property name.
23− | JSPropIndexRef Object Index -- ^ Object and property index.
24−
25−
src/Language/Javascript/JSaddle/Properties.hs+2−72
@@ -21,25 +21,17 @@
2121-----------------------------------------------------------------------------
2222
2323module Language.Javascript.JSaddle.Properties (
24− -- * Propery Reference
25− JSPropRef(..)
26− , MakePropRef(..)
27−
2824 -- * Getting Property Values
29− , objGetPropertyByName
25+ objGetPropertyByName
3026 , objGetPropertyAtIndex
31− , objGetProperty
32− , objGetProperty'
3327 -- * Setting Property Values
3428 , objSetPropertyByName
3529 , objSetPropertyAtIndex
36− , objSetProperty
3730) where
3831
3932import Control.Applicative ((<$>))
40−import Language.Javascript.JSaddle.PropRef (JSPropRef(..))
4133import Language.Javascript.JSaddle.Classes
42− (MakePropRef(..), MakeObject(..), MakeValueRef(..),
34+ (MakeObject(..), MakeValueRef(..),
4335 MakeArgRefs(..), MakeStringRef(..))
4436import Language.Javascript.JSaddle.Monad (JSM)
4537import Language.Javascript.JSaddle.Types
@@ -59,34 +51,6 @@ import Language.Javascript.JSaddle.Value (JSValueRef)
5951import Language.Javascript.JSaddle.Arguments ()
6052import Language.Javascript.JSaddle.String ()
6153
62−-- | If we already have a JSPropRef we are fine
63−instance MakePropRef JSPropRef where
64− makePropRef = return
65− {-# INLINE makePropRef #-}
66−
67−-- | JSPropRef can be made by evaluating a function in 'JSM' as long
68−-- as it returns something we can make into a JSPropRef.
69−instance MakePropRef prop => MakePropRef (JSM prop) where
70− makePropRef prop = prop >>= makePropRef
71− {-# INLINE makePropRef #-}
72−
73−-- | We can use a property as an object.
74−instance MakeObject JSPropRef where
75− makeObject prop = Object <$> objGetProperty prop
76− {-# INLINE makeObject #-}
77−
78−-- | We can use a property as a value.
79−instance MakeValueRef JSPropRef where
80− makeValueRef = objGetProperty
81− {-# INLINE makeValueRef #-}
82−
83−-- | We can pass a property as the only paramter to a function.
84−instance MakeArgRefs JSPropRef where
85− makeArgRefs p = do
86− rarg <- objGetProperty p
87− return [rarg]
88− {-# INLINE makeArgRefs #-}
89−
9054-- | Get a property value given the object and the name of the property.
9155objGetPropertyByName :: MakeStringRef name
9256 => Object -- ^ object to find the property on.
@@ -126,27 +90,6 @@ objGetPropertyAtIndex (Object this) index exceptions = do
12690objGetPropertyAtIndex = undefined
12791#endif
12892
129−-- | Gets the value of a property given a 'JSPropRef'.
130−objGetProperty :: JSPropRef -- ^ property reference.
131− -> JSM JSValueRef -- ^ returns the property value.
132−objGetProperty (JSPropRef this name ) =
133− rethrow $ objGetPropertyByName this name
134−objGetProperty (JSPropIndexRef this index) =
135− rethrow $ objGetPropertyAtIndex this index
136−{-# INLINE objGetProperty #-}
137−
138−-- | This version of 'objGetProperty' is handy when you also need to perform.
139−-- another operation on the object the property is on.
140−objGetProperty' :: JSPropRef -- ^ property reference.
141− -> JSM (Object, JSValueRef) -- ^ returns the object and property value.
142−objGetProperty' (JSPropRef this name) = do
143− p <- rethrow $ objGetPropertyByName this name
144− return (this, p)
145−objGetProperty' (JSPropIndexRef this index) = do
146− p <- rethrow $ objGetPropertyAtIndex this index
147− return (this, p)
148−{-# INLINE objGetProperty' #-}
149−
15093-- | Set a property value given the object and the name of the property.
15194objSetPropertyByName :: (MakeStringRef name, MakeValueRef val)
15295 => Object -- ^ object to set the property on.
@@ -196,16 +139,3 @@ objSetPropertyAtIndex (Object this) index val exceptions = do
196139objSetPropertyAtIndex = undefined
197140#endif
198141
199−-- | Sets the value of a property given a 'JSPropRef'.
200−objSetProperty :: (MakeValueRef val)
201− => JSPropRef -- ^ property reference.
202− -> val -- ^ new value to set the property to.
203− -> JSM ()
204−objSetProperty (JSPropRef this name ) val = rethrow $ objSetPropertyByName this name val 0
205−objSetProperty (JSPropIndexRef this index) val = rethrow $ objSetPropertyAtIndex this index val
206−{-# INLINE objSetProperty #-}
207−
208−
209−
210−
211−
src/Language/Javascript/JSaddle/Value.hs+4
@@ -304,6 +304,10 @@ valToObject val = Object <$>
304304#endif
305305{-# INLINE valToObject #-}
306306
307+instance MakeObject JSValueRef where
308+ makeObject = valToObject
309+ {-# INLINE makeObject #-}
310+
307311-- | Convert to a JavaScript value (just an alias for 'makeValueRef')
308312val :: MakeValueRef value
309313 => value -- ^ value to convert to a JavaScript value