@@ -3,10 +3,11 @@
3{-# LANGUAGE TypeSynonymInstances #-}
3{-# LANGUAGE TypeSynonymInstances #-}
4{-# LANGUAGE ScopedTypeVariables #-}
4{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE Rank2Types #-}
5{-# LANGUAGE Rank2Types #-}
6−{-# LANGUAGE ForeignFunctionInterface #-}
7#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
6#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
7+{-# LANGUAGE ForeignFunctionInterface #-}
8{-# LANGUAGE JavaScriptFFI #-}
8{-# LANGUAGE JavaScriptFFI #-}
10+{-# OPTIONS_GHC -fno-warn-orphans #-}
10-----------------------------------------------------------------------------
11-----------------------------------------------------------------------------
12-- Module : Language.Javascript.JSaddle.Object
13-- Module : Language.Javascript.JSaddle.Object
@@ -28,7 +29,7 @@ module Language.Javascript.JSaddle.Object (
@@ -57,9 +58,11 @@ module Language.Javascript.JSaddle.Object (
59 -- * Calling Haskell From JavaScript
60 -- * Calling Haskell From JavaScript
60 , function
62 , function
62− , JSCallAsFunction(..)
65+ , JSCallAsFunction
63 -- ** Object Constructors
66 -- ** Object Constructors
65 -- | There is no good way to support calling haskell code as a JavaScript
68 -- | There is no good way to support calling haskell code as a JavaScript
@@ -78,20 +81,23 @@ module Language.Javascript.JSaddle.Object (
79 -- * Enumerating Properties
82 -- * Enumerating Properties
80 , propertyNames
83 , propertyNames
82 -- * Low level
86 -- * Low level
83 , objCallAsFunction
87 , objCallAsFunction
84 , objCallAsConstructor
88 , objCallAsConstructor
87import Prelude hiding ((!!))
92import Prelude hiding ((!!))
88import Language.Javascript.JSaddle.Types
93import Language.Javascript.JSaddle.Types
89 (JSPropertyNameArray, JSString, Object(..), MutableJSArray,
94 (JSPropertyNameArray, JSString, Object(..), MutableJSArray,
90 JSVal, Index)
95 JSVal, Index)
91−import Foreign.C.Types (CSize(..), CULong(..), CUInt(..), CULLong(..))
96+import Foreign.C.Types (CSize(..), CULong(..))
92#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
97#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
93import GHCJS.Types (nullRef, jsval)
98import GHCJS.Types (nullRef, jsval)
94−import GHCJS.Foreign.Callback (syncCallback2, OnBlocked(..), Callback)
99+import GHCJS.Foreign.Callback
100+ (releaseCallback, syncCallback2, OnBlocked(..), Callback)
95import GHCJS.Marshal.Pure (pFromJSVal)
101import GHCJS.Marshal.Pure (pFromJSVal)
96import JavaScript.Array (JSArray)
102import JavaScript.Array (JSArray)
97import qualified JavaScript.Array as Array (toListIO, fromListIO)
103import qualified JavaScript.Array as Array (toListIO, fromListIO)
@@ -104,39 +110,39 @@ import Data.Coerce (coerce)
104import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSObjectRef
110import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSObjectRef
105 (jsobjectmake, jspropertynamearraygetnameatindex,
111 (jsobjectmake, jspropertynamearraygetnameatindex,
106 jspropertynamearraygetcount, jsobjectcopypropertynames,
112 jspropertynamearraygetcount, jsobjectcopypropertynames,
107− jsobjectsetpropertyatindex, jsobjectgetpropertyatindex,
108 jsobjectcallasconstructor, jsobjectmakearray,
113 jsobjectcallasconstructor, jsobjectmakearray,
109− jsobjectcallasfunction, jsobjectgetproperty, jsobjectsetproperty,
114+ jsobjectcallasfunction,
110− JSPropertyAttributes, JSObjectCallAsFunctionCallback,
115+ JSObjectCallAsFunctionCallback,
111 jsobjectmakefunctionwithcallback, JSObjectCallAsFunctionCallback')
116 jsobjectmakefunctionwithcallback, JSObjectCallAsFunctionCallback')
112import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSValueRef
117import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSValueRef
113 (jsvaluemakeundefined)
118 (jsvaluemakeundefined)
114import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSContextRef
119import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSContextRef
115 (jscontextgetglobalobject)
120 (jscontextgetglobalobject)
116import Foreign (peekArray, nullPtr, withArrayLen)
121import Foreign (peekArray, nullPtr, withArrayLen)
122+import Foreign.Ptr (freeHaskellFunPtr)
123+import Language.Javascript.JSaddle.Native
124+ (makeNewJSVal, wrapJSString, withJSVals, withObject, withJSString,
126+import System.IO.Unsafe (unsafePerformIO)
127+import Foreign.ForeignPtr (newForeignPtr_)
118import Language.Javascript.JSaddle.Exception (rethrow)
129import Language.Javascript.JSaddle.Exception (rethrow)
119import Language.Javascript.JSaddle.Value
130import Language.Javascript.JSaddle.Value
120− (JSUndefined, valMakeUndefined, valToObject)
131+ (JSUndefined, valToObject)
121import Language.Javascript.JSaddle.Classes
132import Language.Javascript.JSaddle.Classes
122− (MakeVal(..), MakeString(..), MakeArgs(..), MakeObject(..))
133+ (ToJSVal(..), ToJSString(..), MakeObject(..))
134+import Language.Javascript.JSaddle.Arguments (MakeArgs(..))
123import Language.Javascript.JSaddle.Monad
135import Language.Javascript.JSaddle.Monad
125import Control.Monad.Trans.Reader (runReaderT, ask)
137import Control.Monad.Trans.Reader (runReaderT, ask)
126import Control.Monad.IO.Class (MonadIO(..))
138import Control.Monad.IO.Class (MonadIO(..))
127import qualified Control.Exception as E (catch)
139import qualified Control.Exception as E (catch)
128import Control.Exception (SomeException)
140import Control.Exception (SomeException)
129−import qualified Data.Text as T (pack)
130import Foreign.Storable (Storable(..))
141import Foreign.Storable (Storable(..))
131import Language.Javascript.JSaddle.Properties
142import Language.Javascript.JSaddle.Properties
133− (IndexPreservingGetter, to, (^.))
143+import Control.Lens (IndexPreservingGetter, to)
134−import Language.Javascript.JSaddle.String (textToStr)
144+import Language.Javascript.JSaddle.String (nullJSString)
135−
145+import Data.Text (Text)
136−-- | If we already have a Object we are fine
137−instance MakeObject Object where
139− {-# INLINE makeObject #-}
141-- | Object can be made by evaluating a function in 'JSM' as long
147-- | Object can be made by evaluating a function in 'JSM' as long
142-- as it returns something we can make into a Object.
148-- as it returns something we can make into a Object.
@@ -149,7 +155,7 @@ instance MakeObject v => MakeObject (JSM v) where
149-- >>> testJSaddle $ eval "'Hello World'.length"
155-- >>> testJSaddle $ eval "'Hello World'.length"
150-- >>> testJSaddle $ val "Hello World" ! "length"
156-- >>> testJSaddle $ val "Hello World" ! "length"
152−(!) :: (MakeObject this, MakeString name)
158+(!) :: (MakeObject this, ToJSString name)
153 => this -- ^ Object to look on
159 => this -- ^ Object to look on
154 -> name -- ^ Name of the property to find
160 -> name -- ^ Name of the property to find
155 -> JSM JSVal -- ^ Property reference
161 -> JSM JSVal -- ^ Property reference
@@ -157,7 +163,7 @@ this ! name = do
157 rthis <- makeObject this
163 rthis <- makeObject this
158 rethrow $ objGetPropertyByName rthis rname
164 rethrow $ objGetPropertyByName rthis rname
160− rname = makeString name
166+ rname = toJSString name
161{-# INLINE (!) #-}
167{-# INLINE (!) #-}
163-- | Lookup a property based on its index.
169-- | Lookup a property based on its index.
@@ -181,7 +187,7 @@ this !! index = do
181-- >>> testJSaddle $ eval "'Hello World'.length"
187-- >>> testJSaddle $ eval "'Hello World'.length"
182-- >>> testJSaddle $ val "Hello World" ^. js "length"
188-- >>> testJSaddle $ val "Hello World" ^. js "length"
184−js :: (MakeObject s, MakeString name)
190+js :: (MakeObject s, ToJSString name)
185 => name -- ^ Name of the property to find
191 => name -- ^ Name of the property to find
186 -> IndexPreservingGetter s (JSM JSVal)
192 -> IndexPreservingGetter s (JSM JSVal)
187js name = to (!name)
193js name = to (!name)
@@ -194,7 +200,7 @@ js name = to (!name)
194-- >>> testJSaddle $ eval "'Hello World'.length"
200-- >>> testJSaddle $ eval "'Hello World'.length"
195-- >>> testJSaddle $ val "Hello World" ^. js "length"
201-- >>> testJSaddle $ val "Hello World" ^. js "length"
197−jss :: (MakeString name, MakeVal val)
203+jss :: (ToJSString name, ToJSVal val)
198 => name -- ^ Name of the property to find
204 => name -- ^ Name of the property to find
200 -> forall o . MakeObject o => IndexPreservingGetter o (JSM ())
206 -> forall o . MakeObject o => IndexPreservingGetter o (JSM ())
@@ -207,7 +213,7 @@ jss name val = to (\o -> o <# name $ val)
208-- >>> testJSaddle $ val "Hello World" ^. jsf "indexOf" ["World"]
214-- >>> testJSaddle $ val "Hello World" ^. jsf "indexOf" ["World"]
210−jsf :: (MakeString name, MakeArgs args) => name -> args -> JSF
216+jsf :: (ToJSString name, MakeArgs args) => name -> args -> JSF
211jsf name args = to (\o -> o # name $ args)
217jsf name args = to (\o -> o # name $ args)
212{-# INLINE jsf #-}
218{-# INLINE jsf #-}
@@ -220,7 +226,7 @@ type JSF = forall o . MakeObject o => IndexPreservingGetter o (JSM JSVal)
221-- >>> testJSaddle $ val "Hello World" ^. js0 "toLowerCase"
227-- >>> testJSaddle $ val "Hello World" ^. js0 "toLowerCase"
222-- hello world
228-- hello world
223−js0 :: (MakeString name) => name -> JSF
229+js0 :: (ToJSString name) => name -> JSF
224js0 name = jsf name ()
230js0 name = jsf name ()
225{-# INLINE js0 #-}
231{-# INLINE js0 #-}
@@ -230,31 +236,31 @@ js0 name = jsf name ()
231-- >>> testJSaddle $ val "Hello World" ^. js1 "indexOf" "World"
237-- >>> testJSaddle $ val "Hello World" ^. js1 "indexOf" "World"
233−js1 :: (MakeString name, MakeVal a0) => name -> a0 -> JSF
239+js1 :: (ToJSString name, ToJSVal a0) => name -> a0 -> JSF
234js1 name a0 = jsf name [a0]
240js1 name a0 = jsf name [a0]
235{-# INLINE js1 #-}
241{-# INLINE js1 #-}
237-- | Handy way to call a function that expects two arguments
243-- | Handy way to call a function that expects two arguments
238−js2 :: (MakeString name, MakeVal a0, MakeVal a1) => name -> a0 -> a1 -> JSF
244+js2 :: (ToJSString name, ToJSVal a0, ToJSVal a1) => name -> a0 -> a1 -> JSF
239js2 name a0 a1 = jsf name (a0, a1)
245js2 name a0 a1 = jsf name (a0, a1)
240{-# INLINE js2 #-}
246{-# INLINE js2 #-}
242-- | Handy way to call a function that expects three arguments
248-- | Handy way to call a function that expects three arguments
243−js3 :: (MakeString name, MakeVal a0, MakeVal a1, MakeVal a2)
249+js3 :: (ToJSString name, ToJSVal a0, ToJSVal a1, ToJSVal a2)
244 => name -> a0 -> a1 -> a2 -> JSF
250 => name -> a0 -> a1 -> a2 -> JSF
245js3 name a0 a1 a2 = jsf name (a0, a1, a2)
251js3 name a0 a1 a2 = jsf name (a0, a1, a2)
246{-# INLINE js3 #-}
252{-# INLINE js3 #-}
248-- | Handy way to call a function that expects four arguments
254-- | Handy way to call a function that expects four arguments
249−js4 :: (MakeString name, MakeVal a0, MakeVal a1, MakeVal a2,
255+js4 :: (ToJSString name, ToJSVal a0, ToJSVal a1, ToJSVal a2,
250− MakeVal a3)
256+ ToJSVal a3)
251 => name -> a0 -> a1 -> a2 -> a3 -> JSF
257 => name -> a0 -> a1 -> a2 -> a3 -> JSF
252js4 name a0 a1 a2 a3 = jsf name (a0, a1, a2, a3)
258js4 name a0 a1 a2 a3 = jsf name (a0, a1, a2, a3)
253{-# INLINE js4 #-}
259{-# INLINE js4 #-}
255-- | Handy way to call a function that expects five arguments
261-- | Handy way to call a function that expects five arguments
256−js5 :: (MakeString name, MakeVal a0, MakeVal a1, MakeVal a2,
262+js5 :: (ToJSString name, ToJSVal a0, ToJSVal a1, ToJSVal a2,
257− MakeVal a3, MakeVal a4)
263+ ToJSVal a3, ToJSVal a4)
258 => name -> a0 -> a1 -> a2 -> a3 -> a4 -> JSF
264 => name -> a0 -> a1 -> a2 -> a3 -> a4 -> JSF
259js5 name a0 a1 a2 a3 a4 = jsf name (a0, a1, a2, a3, a4)
265js5 name a0 a1 a2 a3 a4 = jsf name (a0, a1, a2, a3, a4)
260{-# INLINE js5 #-}
266{-# INLINE js5 #-}
@@ -265,7 +271,7 @@ js5 name a0 a1 a2 a3 a4 = jsf name (a0, a1, a2, a3, a4)
265-- >>> testJSaddle $ eval "w = console; w.log('Hello World')"
271-- >>> testJSaddle $ eval "w = console; w.log('Hello World')"
266-- >>> testJSaddle $ do w <- jsg "console"; w ^. js "log" # ["Hello World"]
272-- >>> testJSaddle $ do w <- jsg "console"; w ^. js "log" # ["Hello World"]
268−jsg :: MakeString a => a -> JSM JSVal
274+jsg :: ToJSString a => a -> JSM JSVal
269jsg name = global ! name
275jsg name = global ! name
270{-# INLINE jsg #-}
276{-# INLINE jsg #-}
@@ -275,7 +281,7 @@ jsg name = global ! name
276-- >>> testJSaddle $ jsf "globalFunc" ["World"]
282-- >>> testJSaddle $ jsf "globalFunc" ["World"]
278−jsgf :: (MakeString name, MakeArgs args) => name -> args -> JSM JSVal
284+jsgf :: (ToJSString name, MakeArgs args) => name -> args -> JSM JSVal
279jsgf name = global # name
285jsgf name = global # name
280{-# INLINE jsgf #-}
286{-# INLINE jsgf #-}
@@ -285,7 +291,7 @@ jsgf name = global # name
286-- >>> testJSaddle $ js0 "globalFunc"
292-- >>> testJSaddle $ js0 "globalFunc"
287-- hello world
293-- hello world
288−jsg0 :: (MakeString name) => name -> JSM JSVal
294+jsg0 :: (ToJSString name) => name -> JSM JSVal
289jsg0 name = jsgf name ()
295jsg0 name = jsgf name ()
290{-# INLINE jsg0 #-}
296{-# INLINE jsg0 #-}
@@ -295,31 +301,31 @@ jsg0 name = jsgf name ()
296-- >>> testJSaddle $ jsg1 "globalFunc" "World"
302-- >>> testJSaddle $ jsg1 "globalFunc" "World"
298−jsg1 :: (MakeString name, MakeVal a0) => name -> a0 -> JSM JSVal
304+jsg1 :: (ToJSString name, ToJSVal a0) => name -> a0 -> JSM JSVal
299jsg1 name a0 = jsgf name [a0]
305jsg1 name a0 = jsgf name [a0]
300{-# INLINE jsg1 #-}
306{-# INLINE jsg1 #-}
302-- | Handy way to call a function that expects two arguments
308-- | Handy way to call a function that expects two arguments
303−jsg2 :: (MakeString name, MakeVal a0, MakeVal a1) => name -> a0 -> a1 -> JSM JSVal
309+jsg2 :: (ToJSString name, ToJSVal a0, ToJSVal a1) => name -> a0 -> a1 -> JSM JSVal
304jsg2 name a0 a1 = jsgf name (a0, a1)
310jsg2 name a0 a1 = jsgf name (a0, a1)
305{-# INLINE jsg2 #-}
311{-# INLINE jsg2 #-}
307-- | Handy way to call a function that expects three arguments
313-- | Handy way to call a function that expects three arguments
308−jsg3 :: (MakeString name, MakeVal a0, MakeVal a1, MakeVal a2)
314+jsg3 :: (ToJSString name, ToJSVal a0, ToJSVal a1, ToJSVal a2)
309 => name -> a0 -> a1 -> a2 -> JSM JSVal
315 => name -> a0 -> a1 -> a2 -> JSM JSVal
310jsg3 name a0 a1 a2 = jsgf name (a0, a1, a2)
316jsg3 name a0 a1 a2 = jsgf name (a0, a1, a2)
311{-# INLINE jsg3 #-}
317{-# INLINE jsg3 #-}
313-- | Handy way to call a function that expects four arguments
319-- | Handy way to call a function that expects four arguments
314−jsg4 :: (MakeString name, MakeVal a0, MakeVal a1, MakeVal a2,
320+jsg4 :: (ToJSString name, ToJSVal a0, ToJSVal a1, ToJSVal a2,
315− MakeVal a3)
321+ ToJSVal a3)
316 => name -> a0 -> a1 -> a2 -> a3 -> JSM JSVal
322 => name -> a0 -> a1 -> a2 -> a3 -> JSM JSVal
317jsg4 name a0 a1 a2 a3 = jsgf name (a0, a1, a2, a3)
323jsg4 name a0 a1 a2 a3 = jsgf name (a0, a1, a2, a3)
318{-# INLINE jsg4 #-}
324{-# INLINE jsg4 #-}
320-- | Handy way to call a function that expects five arguments
326-- | Handy way to call a function that expects five arguments
321−jsg5 :: (MakeString name, MakeVal a0, MakeVal a1, MakeVal a2,
327+jsg5 :: (ToJSString name, ToJSVal a0, ToJSVal a1, ToJSVal a2,
322− MakeVal a3, MakeVal a4)
328+ ToJSVal a3, ToJSVal a4)
323 => name -> a0 -> a1 -> a2 -> a3 -> a4 -> JSM JSVal
329 => name -> a0 -> a1 -> a2 -> a3 -> a4 -> JSM JSVal
324jsg5 name a0 a1 a2 a3 a4 = jsgf name (a0, a1, a2, a3, a4)
330jsg5 name a0 a1 a2 a3 a4 = jsgf name (a0, a1, a2, a3, a4)
325{-# INLINE jsg5 #-}
331{-# INLINE jsg5 #-}
@@ -330,7 +336,7 @@ jsg5 name a0 a1 a2 a3 a4 = jsgf name (a0, a1, a2, a3, a4)
330-- >>> testJSaddle $ val "Hello World" # "indexOf" $ ["World"]
336-- >>> testJSaddle $ val "Hello World" # "indexOf" $ ["World"]
332infixr 2 #
338infixr 2 #
333−(#) :: (MakeObject this, MakeString name, MakeArgs args)
339+(#) :: (MakeObject this, ToJSString name, MakeArgs args)
334 => this -> name -> args -> JSM JSVal
340 => this -> name -> args -> JSM JSVal
335(#) this name args = do
341(#) this name args = do
336 rthis <- makeObject this
342 rthis <- makeObject this
@@ -359,7 +365,7 @@ infixr 2 ##
359-- >>> testJSaddle $ do {j <- eval "({})"; j <# "x" 1; j!"x"}
365-- >>> testJSaddle $ do {j <- eval "({})"; j <# "x" 1; j!"x"}
361infixr 1 <#
367infixr 1 <#
362−(<#) :: (MakeObject this, MakeString name, MakeVal val)
368+(<#) :: (MakeObject this, ToJSString name, ToJSVal val)
363 => this -- ^ Object to set the property on
369 => this -- ^ Object to set the property on
364 -> name -- ^ Name of the property to set
370 -> name -- ^ Name of the property to set
365 -> val -- ^ Value to set it to
371 -> val -- ^ Value to set it to
@@ -375,7 +381,7 @@ infixr 1 <#
375-- >>> testJSaddle $ do {j <- eval "({})"; j <## 6 1; j!!6}
381-- >>> testJSaddle $ do {j <- eval "({})"; j <## 6 1; j!!6}
377infixr 1 <##
383infixr 1 <##
378−(<##) :: (MakeObject this, MakeVal val)
384+(<##) :: (MakeObject this, ToJSVal val)
379 => this -- ^ Object to set the property on
385 => this -- ^ Object to set the property on
380 -> Index -- ^ Index of the property to set
386 -> Index -- ^ Index of the property to set
381 -> val -- ^ Value to set it to
387 -> val -- ^ Value to set it to
@@ -406,10 +412,10 @@ new constructor args = do
406-- >>> testJSaddle $ eval "(function(){return this;}).apply('Hello', [])"
412-- >>> testJSaddle $ eval "(function(){return this;}).apply('Hello', [])"
407-- >>> testJSaddle $ do { test <- eval "(function(){return this;})"; call test (val "Hello") () }
413-- >>> testJSaddle $ do { test <- eval "(function(){return this;})"; call test (val "Hello") () }
409−call :: (MakeObject function, MakeObject this, MakeArgs args)
415+call :: (MakeObject f, MakeObject this, MakeArgs args)
410− => function -> this -> args -> JSM JSVal
416+ => f -> this -> args -> JSM JSVal
411−call function this args = do
417+call f this args = do
412− rfunction <- makeObject function
418+ rfunction <- makeObject f
413 rthis <- makeObject this
419 rthis <- makeObject this
414 rethrow $ objCallAsFunction rfunction rthis args
420 rethrow $ objCallAsFunction rfunction rthis args
415{-# INLINE call #-}
421{-# INLINE call #-}
@@ -425,7 +431,7 @@ obj = liftIO Object.create
427 gctxt <- ask
433 gctxt <- ask
428− liftIO $ Object <$> jsobjectmake gctxt nullPtr nullPtr
434+ Object <$> ((liftIO $ jsobjectmake gctxt nullPtr nullPtr) >>= makeNewJSVal)
430{-# INLINE obj #-}
436{-# INLINE obj #-}
@@ -455,56 +461,74 @@ foreign import ccall "wrapper"
455 mkJSObjectCallAsFunctionCallback :: JSObjectCallAsFunctionCallback' -> IO JSObjectCallAsFunctionCallback
461 mkJSObjectCallAsFunctionCallback :: JSObjectCallAsFunctionCallback' -> IO JSObjectCallAsFunctionCallback
464+#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI) || !defined(USE_WEBKIT)
465+type HaskellCallback = Callback (JSVal -> JSVal -> IO ())
467+type HaskellCallback = JSObjectCallAsFunctionCallback
470+data Function = Function {functionCallback :: HaskellCallback, functionObject :: Object}
458-- ^ Make a JavaScript function object that wraps a Haskell function.
472-- ^ Make a JavaScript function object that wraps a Haskell function.
459−function :: MakeString name
473+function :: ToJSString name
460 => name -- ^ Name of the function
474 => name -- ^ Name of the function
461 -> JSCallAsFunction -- ^ Haskell function to call
475 -> JSCallAsFunction -- ^ Haskell function to call
462− -> JSM Object -- ^ Returns a JavaScript function object that will
476+ -> JSM Function -- ^ Returns a JavaScript function object that will
463 -- call the Haskell one when it is called
477 -- call the Haskell one when it is called
464#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
478#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
465function name f = liftIO $ do
479function name f = liftIO $ do
466 callback <- syncCallback2 ContinueAsync $ \this args -> do
480 callback <- syncCallback2 ContinueAsync $ \this args -> do
467 rargs <- Array.toListIO (coerce args)
481 rargs <- Array.toListIO (coerce args)
468 runReaderT (f this this rargs) () -- TODO pass function object through
482 runReaderT (f this this rargs) () -- TODO pass function object through
469− makeFunctionWithCallback (makeString name) callback
483+ Function callback <$> makeFunctionWithCallback (toJSString name) callback
470foreign import javascript unsafe "$r = function () { $2(this, arguments); }"
484foreign import javascript unsafe "$r = function () { $2(this, arguments); }"
471 makeFunctionWithCallback :: JSString -> Callback (JSVal -> JSVal -> IO ()) -> IO Object
485 makeFunctionWithCallback :: JSString -> Callback (JSVal -> JSVal -> IO ()) -> IO Object
472#elif defined(USE_WEBKIT)
486#elif defined(USE_WEBKIT)
473function name f = do
487function name f = do
474 gctxt <- ask
488 gctxt <- ask
475− callback <- liftIO $ mkJSObjectCallAsFunctionCallback wrap
489+ callback <- liftIO $ mkJSObjectCallAsFunctionCallback (wrap gctxt)
490+ withJSString (toJSString name) $ \name' ->
491+ Function callback . Object <$>
476− liftIO $ Object <$> jsobjectmakefunctionwithcallback gctxt (makeString name) callback
492+ ((liftIO $ jsobjectmakefunctionwithcallback gctxt name' callback) >>= makeNewJSVal)
478− wrap ctx fobj this argc argv exception = do
494+ wrap gctxt _ctx fobj' this' argc argv exception = do
479− args <- peekArray (fromIntegral argc) argv
495+ args' <- peekArray (fromIntegral argc) argv
480− (`runReaderT` ctx) $
496+ (`runReaderT` gctxt) $ do
497+ fobj <- makeNewJSVal fobj'
498+ this <- makeNewJSVal this'
499+ args <- mapM makeNewJSVal args'
481− f fobj this args >>= makeVal
500+ f fobj this args
501+ liftIO $ jsvaluemakeundefined gctxt
482 `E.catch` \(e :: SomeException) -> do
502 `E.catch` \(e :: SomeException) -> do
483− str <- runReaderT (makeVal . T.pack $ show e) ctx
503+ (`runReaderT` gctxt) $ do
484− poke exception str
504+ withToJSVal (show e) $ liftIO . poke exception
485− jsvaluemakeundefined ctx
505+ liftIO $ jsvaluemakeundefined gctxt
487function = undefined
507function = undefined
510+freeFunction :: MonadIO m => Function -> m ()
511+freeFunction (Function callback _) = liftIO $
512+#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI) || !defined(USE_WEBKIT)
513+ releaseCallback callback
515+ freeHaskellFunPtr callback
518+instance ToJSVal Function where
519+ toJSVal (Function _ f) = toJSVal f
520+ {-# INLINE toJSVal #-}
490-- | A callback to Haskell can be used as a JavaScript value. This will create
522-- | A callback to Haskell can be used as a JavaScript value. This will create
491-- an anonymous JavaScript function object. Use 'function' to create one with
523-- an anonymous JavaScript function object. Use 'function' to create one with
492-- a name.
524-- a name.
493−instance MakeVal JSCallAsFunction where
525+instance ToJSVal JSCallAsFunction where
494−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
526+ toJSVal f = functionObject <$> function nullJSString f >>= toJSVal
495− makeVal f = jsval <$> function (pFromJSVal nullRef :: JSString) f
497− makeVal f = function (nullPtr :: JSString) f >>= makeVal
499− {-# INLINE makeVal #-}
527+ {-# INLINE toJSVal #-}
501instance MakeArgs JSCallAsFunction where
529instance MakeArgs JSCallAsFunction where
502 makeArgs f = do
530 makeArgs f = do
503−#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
531+ rarg <- functionObject <$> function nullJSString f >>= toJSVal
504− rarg <- jsval <$> function (pFromJSVal nullRef :: JSString) f
506− rarg <- function (nullPtr:: JSString) f >>= makeVal
508 return [rarg]
532 return [rarg]
509 {-# INLINE makeArgs #-}
533 {-# INLINE makeArgs #-}
@@ -517,8 +541,11 @@ makeArray args exceptions = do
517makeArray args exceptions = do
541makeArray args exceptions = do
518 gctxt <- ask
542 gctxt <- ask
519 rargs <- makeArgs args
543 rargs <- makeArgs args
545+ withJSVals rargs $ \rargs' ->
520− liftIO $ withArrayLen rargs $ \ len ptr ->
546+ liftIO $ withArrayLen rargs' $ \ len ptr ->
521− Object <$> jsobjectmakearray gctxt (fromIntegral len) ptr exceptions
547+ jsobjectmakearray gctxt (fromIntegral len) ptr exceptions
548+ Object <$> makeNewJSVal result
523{-# INLINE makeArray #-}
550{-# INLINE makeArray #-}
@@ -533,6 +560,43 @@ makeArray args exceptions = do
533array :: MakeArgs args => args -> JSM Object
560array :: MakeArgs args => args -> JSM Object
534array = rethrow . makeArray
561array = rethrow . makeArray
563+-- Make an array out of various lists
564+instance ToJSVal [JSVal] where
565+ toJSVal = toJSVal . array
566+ {-# INLINE toJSVal #-}
568+instance ToJSVal [JSM JSVal] where
569+ toJSVal = toJSVal . array
570+ {-# INLINE toJSVal #-}
572+instance ToJSVal [Double] where
573+ toJSVal = toJSVal . array
574+ {-# INLINE toJSVal #-}
576+instance ToJSVal [Float] where
577+ toJSVal = toJSVal . array
578+ {-# INLINE toJSVal #-}
580+instance ToJSVal [Int] where
581+ toJSVal = toJSVal . array
582+ {-# INLINE toJSVal #-}
584+instance ToJSVal [JSString] where
585+ toJSVal = toJSVal . array
586+ {-# INLINE toJSVal #-}
588+instance ToJSVal [String] where
589+ toJSVal = toJSVal . array
590+ {-# INLINE toJSVal #-}
592+instance ToJSVal [Text] where
593+ toJSVal = toJSVal . array
594+ {-# INLINE toJSVal #-}
596+instance ToJSVal [Bool] where
597+ toJSVal = toJSVal . array
598+ {-# INLINE toJSVal #-}
536-- | JavaScript's global object
600-- | JavaScript's global object
537global :: JSM Object
601global :: JSM Object
538#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
602#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
@@ -541,7 +605,10 @@ global = liftIO js_window
541foreign import javascript unsafe "$r = window"
605foreign import javascript unsafe "$r = window"
542 js_window :: IO Object
606 js_window :: IO Object
543#elif defined(USE_WEBKIT)
607#elif defined(USE_WEBKIT)
544−global = ask >>= (liftIO . fmap Object . jscontextgetglobalobject)
608+global = do
610+ result <- liftIO $ jscontextgetglobalobject gctxt
611+ Object <$> makeNewJSVal result
545{-# INLINE global #-}
612{-# INLINE global #-}
547global = undefined
614global = undefined
@@ -552,8 +619,9 @@ global = undefined
552copyPropertyNames :: MakeObject this => this -> JSM JSPropertyNameArray
619copyPropertyNames :: MakeObject this => this -> JSM JSPropertyNameArray
553copyPropertyNames this = do
620copyPropertyNames this = do
554 gctxt <- ask
621 gctxt <- ask
555− Object rthis <- makeObject this
622+ this' <- makeObject this
623+ withObject this' $ \rthis ->
556− liftIO $ jsobjectcopypropertynames gctxt rthis
624+ liftIO $ jsobjectcopypropertynames gctxt rthis
557{-# INLINE copyPropertyNames #-}
625{-# INLINE copyPropertyNames #-}
559-- | Get the number of names in a property name array
627-- | Get the number of names in a property name array
@@ -563,7 +631,7 @@ propertyNamesCount names = liftIO $ jspropertynamearraygetcount names
564-- | Get a name out of a property name array
632-- | Get a name out of a property name array
565propertyNamesAt :: MonadIO m => JSPropertyNameArray -> CSize -> m JSString
633propertyNamesAt :: MonadIO m => JSPropertyNameArray -> CSize -> m JSString
566−propertyNamesAt names index = liftIO $ jspropertynamearraygetnameatindex names index
634+propertyNamesAt names index = liftIO $ jspropertynamearraygetnameatindex names index >>= wrapJSString
567{-# INLINE propertyNamesAt #-}
635{-# INLINE propertyNamesAt #-}
569-- | Convert property array to a list
637-- | Convert property array to a list
@@ -600,18 +668,23 @@ objCallAsFunction :: MakeArgs args
600 -> MutableJSArray
668 -> MutableJSArray
601 -> JSM JSVal
669 -> JSM JSVal
602#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
670#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
603−objCallAsFunction function this args exceptions = do
671+objCallAsFunction f this args exceptions = do
604 rargs <- makeArgs args >>= liftIO . Array.fromListIO
672 rargs <- makeArgs args >>= liftIO . Array.fromListIO
605− liftIO $ js_apply function this rargs exceptions
673+ liftIO $ js_apply f this rargs exceptions
606{-# INLINE objCallAsFunction #-}
674{-# INLINE objCallAsFunction #-}
607foreign import javascript unsafe "try { $r = $1.apply($2, $3) } catch(e) { $4[0] = e }"
675foreign import javascript unsafe "try { $r = $1.apply($2, $3) } catch(e) { $4[0] = e }"
608 js_apply :: Object -> Object -> MutableJSArray -> MutableJSArray -> IO JSVal
676 js_apply :: Object -> Object -> MutableJSArray -> MutableJSArray -> IO JSVal
609#elif defined(USE_WEBKIT)
677#elif defined(USE_WEBKIT)
610−objCallAsFunction (Object function) (Object this) args exceptions = do
678+objCallAsFunction f this args exceptions = do
611 gctxt <- ask
679 gctxt <- ask
612 rargs <- makeArgs args
680 rargs <- makeArgs args
682+ withObject f $ \rfunction ->
683+ withObject this $ \rthis ->
684+ withJSVals rargs $ \rargs' ->
613− liftIO $ withArrayLen rargs $ \ largs pargs ->
685+ liftIO $ withArrayLen rargs' $ \ largs pargs ->
614− jsobjectcallasfunction gctxt function this (fromIntegral largs) pargs exceptions
686+ jsobjectcallasfunction gctxt rfunction rthis (fromIntegral largs) pargs exceptions
615{-# INLINE objCallAsFunction #-}
688{-# INLINE objCallAsFunction #-}
617objCallAsFunction = undefined
690objCallAsFunction = undefined
@@ -627,9 +700,9 @@ objCallAsConstructor :: MakeArgs args
627 -> MutableJSArray
700 -> MutableJSArray
628 -> JSM JSVal
701 -> JSM JSVal
629#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
702#if defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)
630−objCallAsConstructor function args exceptions = do
703+objCallAsConstructor f args exceptions = do
631 rargs <- makeArgs args >>= liftIO . Array.fromListIO
704 rargs <- makeArgs args >>= liftIO . Array.fromListIO
632− liftIO $ js_new function rargs exceptions
705+ liftIO $ js_new f rargs exceptions
633foreign import javascript unsafe "\
706foreign import javascript unsafe "\
635 switch($2.length) {\
708 switch($2.length) {\
@@ -659,15 +732,25 @@ foreign import javascript unsafe "\
660 js_new :: Object -> MutableJSArray -> MutableJSArray -> IO JSVal
733 js_new :: Object -> MutableJSArray -> MutableJSArray -> IO JSVal
661#elif defined(USE_WEBKIT)
734#elif defined(USE_WEBKIT)
662−objCallAsConstructor (Object function) args exceptions = do
735+objCallAsConstructor f args exceptions = do
663 gctxt <- ask
736 gctxt <- ask
664 rargs <- makeArgs args
737 rargs <- makeArgs args
739+ withObject f $ \rfunction ->
740+ withJSVals rargs $ \rargs' ->
665− liftIO $ withArrayLen rargs $ \ largs pargs ->
741+ liftIO $ withArrayLen rargs' $ \ largs pargs ->
666− jsobjectcallasconstructor gctxt function (fromIntegral largs) pargs exceptions
742+ jsobjectcallasconstructor gctxt rfunction (fromIntegral largs) pargs exceptions
668objCallAsConstructor = undefined
745objCallAsConstructor = undefined
749+#if (defined(ghcjs_HOST_OS) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
750+nullObject = Object nullRef
752+nullObject = Object . unsafePerformIO $ newForeignPtr_ nullPtr