@@ -1,8 +1,12 @@
1−{-# LANGUAGE ForeignFunctionInterface #-}
1+{-# LANGUAGE CPP #-}
2{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE FlexibleInstances #-}
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__) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
8+{-# LANGUAGE JavaScriptFFI #-}
6-----------------------------------------------------------------------------
10-----------------------------------------------------------------------------
8-- Module : Language.Javascript.JSC.Object
12-- Module : Language.Javascript.JSC.Object
@@ -63,7 +67,6 @@ module Language.Javascript.JSC.Object (
65 -- * Enumerating Properties
69 -- * Enumerating Properties
67 , propertyNames
70 , propertyNames
69 -- * Low level
72 -- * Low level
@@ -72,10 +75,16 @@ module Language.Javascript.JSC.Object (
74import Prelude hiding ((!!))
77import Prelude hiding ((!!))
75−import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSBase
78+import Language.Javascript.JSC.Types
76 (JSPropertyNameArrayRef, JSStringRef, JSObjectRef, JSValueRefRef,
79 (JSPropertyNameArrayRef, JSStringRef, JSObjectRef, JSValueRefRef,
77− JSValueRef, JSContextRef)
80+ JSValueRef, JSContextRef, Index)
78−import Foreign.C (CSize(..), CUInt(..), CULong(..))
81+import Foreign.C (CSize(..), CUInt(..))
82+#if (defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
83+import GHCJS.Types (nullRef, castRef, JSArray, JSFun)
84+import GHCJS.Foreign (newObj, toArray, fromArray, syncCallback2)
85+import Control.Monad (liftM)
86+import Control.Applicative ((<$>))
79import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSObjectRef
88import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSObjectRef
80 (jsobjectmake, jspropertynamearraygetnameatindex,
89 (jsobjectmake, jspropertynamearraygetnameatindex,
81 jspropertynamearraygetcount, jsobjectcopypropertynames,
90 jspropertynamearraygetcount, jsobjectcopypropertynames,
@@ -84,6 +93,12 @@ import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSObjectRef
84 jsobjectcallasfunction, jsobjectgetproperty, jsobjectsetproperty,
93 jsobjectcallasfunction, jsobjectgetproperty, jsobjectsetproperty,
85 JSPropertyAttributes, JSObjectCallAsFunctionCallback,
94 JSPropertyAttributes, JSObjectCallAsFunctionCallback,
86 jsobjectmakefunctionwithcallback)
95 jsobjectmakefunctionwithcallback)
96+import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSValueRef
97+ (jsvaluemakeundefined)
98+import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSContextRef
99+ (jscontextgetglobalobject)
100+import Foreign (peekArray, nullPtr, withArrayLen)
87import Language.Javascript.JSC.Exception (rethrow)
102import Language.Javascript.JSC.Exception (rethrow)
88import Language.Javascript.JSC.Value
103import Language.Javascript.JSC.Value
89 (JSUndefined, valMakeUndefined, valToObject)
104 (JSUndefined, valMakeUndefined, valToObject)
@@ -95,15 +110,10 @@ import Language.Javascript.JSC.Monad
96import Control.Monad.Trans.Reader (runReaderT, ask)
111import Control.Monad.Trans.Reader (runReaderT, ask)
97import Control.Monad.IO.Class (MonadIO(..))
112import Control.Monad.IO.Class (MonadIO(..))
98−import Foreign (peekArray, nullPtr, withArrayLen)
99import qualified Control.Exception as E (catch)
113import qualified Control.Exception as E (catch)
100import Control.Exception (SomeException)
114import Control.Exception (SomeException)
101import qualified Data.Text as T (pack)
115import qualified Data.Text as T (pack)
102import Foreign.Storable (Storable(..))
116import Foreign.Storable (Storable(..))
103−import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSValueRef
104− (jsvaluemakeundefined)
105−import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSContextRef
106− (jscontextgetglobalobject)
107import Language.Javascript.JSC.Properties
117import Language.Javascript.JSC.Properties
108import Control.Lens
118import Control.Lens
109 (IndexPreservingGetter, to, (^.))
119 (IndexPreservingGetter, to, (^.))
@@ -144,7 +154,7 @@ this ! name = do
145(!!) :: (MakeObjectRef this)
155(!!) :: (MakeObjectRef this)
146 => this -- ^ Object to look on
156 => this -- ^ Object to look on
147− -> CUInt -- ^ Index of the property to lookup
157+ -> Index -- ^ Index of the property to lookup
148 -> JSC JSPropRef -- ^ Property reference
158 -> JSC JSPropRef -- ^ Property reference
149this !! index = do
159this !! index = do
150 rthis <- makeObjectRef this
160 rthis <- makeObjectRef this
@@ -282,15 +292,19 @@ call function this args = do
282-- >>> testJSC $ do { a <- obj; a ^. js "x" <# "Hello"; a ^. js "x" }
292-- >>> testJSC $ do { a <- obj; a ^. js "x" <# "Hello"; a ^. js "x" }
284obj :: JSC JSObjectRef
294obj :: JSC JSObjectRef
295+#if (defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
296+obj = liftIO $ newObj
286 gctxt <- ask
299 gctxt <- ask
287 liftIO $ jsobjectmake gctxt nullPtr nullPtr
300 liftIO $ jsobjectmake gctxt nullPtr nullPtr
289type JSObjectCallAsFunctionCallback' =
303type JSObjectCallAsFunctionCallback' =
290 JSContextRef
304 JSContextRef
291 -> JSValueRef
305 -> JSValueRef
292 -> JSValueRef
306 -> JSValueRef
293− -> CULong
307+ -> CUInt
294 -> JSValueRefRef
308 -> JSValueRefRef
295 -> JSValueRefRef
309 -> JSValueRefRef
296 -> IO JSValueRef
310 -> IO JSValueRef
@@ -315,8 +329,10 @@ type JSCallAsFunction = JSValueRef -- ^ Function object
315fun :: JSCallAsFunction -> JSCallAsFunction
329fun :: JSCallAsFunction -> JSCallAsFunction
332+#if (!defined(__GHCJS__) || !defined(USE_JAVASCRIPTFFI)) && defined(USE_WEBKIT)
318foreign import ccall "wrapper"
333foreign import ccall "wrapper"
319 mkJSObjectCallAsFunctionCallback :: JSObjectCallAsFunctionCallback' -> IO JSObjectCallAsFunctionCallback
334 mkJSObjectCallAsFunctionCallback :: JSObjectCallAsFunctionCallback' -> IO JSObjectCallAsFunctionCallback
321-- ^ Make a JavaScript function object that wraps a Haskell function.
337-- ^ Make a JavaScript function object that wraps a Haskell function.
322function :: MakeStringRef name
338function :: MakeStringRef name
@@ -324,6 +340,15 @@ function :: MakeStringRef name
324 -> JSCallAsFunction -- ^ Haskell function to call
340 -> JSCallAsFunction -- ^ Haskell function to call
325 -> JSC JSObjectRef -- ^ Returns a JavaScript function object that will
341 -> JSC JSObjectRef -- ^ Returns a JavaScript function object that will
326 -- call the Haskell one when it is called
342 -- call the Haskell one when it is called
343+#if defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)
344+function name f = liftIO $ do
345+ callback <- syncCallback2 False True $ \this args -> do
346+ rargs <- fromArray args
347+ runReaderT (f this this rargs) () -- TODO pass function object through
348+ makeFunctionWithCallback (makeStringRef name) callback
349+foreign import javascript unsafe "$r = function () { $2(this, arguments); }"
350+ makeFunctionWithCallback :: JSStringRef -> JSFun (JSValueRef -> JSValueRefRef -> IO ()) -> IO JSObjectRef
351+#elif defined(USE_WEBKIT)
327function name f = do
352function name f = do
328 gctxt <- ask
353 gctxt <- ask
329 callback <- liftIO $ mkJSObjectCallAsFunctionCallback wrap
354 callback <- liftIO $ mkJSObjectCallAsFunctionCallback wrap
@@ -337,24 +362,39 @@ function name f = do
337 str <- runReaderT (makeValueRef . T.pack $ show e) ctx
362 str <- runReaderT (makeValueRef . T.pack $ show e) ctx
338 poke exception str
363 poke exception str
339 jsvaluemakeundefined ctx
364 jsvaluemakeundefined ctx
341-- | A callback to Haskell can be used as a JavaScript value. This will create
369-- | A callback to Haskell can be used as a JavaScript value. This will create
342-- an anonymous JavaScript function object. Use 'function' to create one with
370-- an anonymous JavaScript function object. Use 'function' to create one with
343-- a name.
371-- a name.
344instance MakeValueRef JSCallAsFunction where
372instance MakeValueRef JSCallAsFunction where
373+#if (defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
374+ makeValueRef = function (nullRef::JSStringRef)
345 makeValueRef = function (nullPtr::JSStringRef)
376 makeValueRef = function (nullPtr::JSStringRef)
347instance MakeArgRefs JSCallAsFunction where
379instance MakeArgRefs JSCallAsFunction where
348 makeArgRefs f = do
380 makeArgRefs f = do
381+#if (defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
382+ rarg <- function (nullRef::JSStringRef) f
349 rarg <- function (nullPtr::JSStringRef) f
384 rarg <- function (nullPtr::JSStringRef) f
350 return [rarg]
386 return [rarg]
352makeArray :: MakeArgRefs args => args -> JSValueRefRef -> JSC JSObjectRef
388makeArray :: MakeArgRefs args => args -> JSValueRefRef -> JSC JSObjectRef
389+#if (defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)) || !defined(USE_WEBKIT)
390+makeArray args exceptions = makeArgRefs args >>= liftM castRef . liftIO . toArray
353makeArray args exceptions = do
392makeArray args exceptions = do
354 gctxt <- ask
393 gctxt <- ask
355 rargs <- makeArgRefs args
394 rargs <- makeArgRefs args
356 liftIO $ withArrayLen rargs $ \ len ptr ->
395 liftIO $ withArrayLen rargs $ \ len ptr ->
357 jsobjectmakearray gctxt (fromIntegral len) ptr exceptions
396 jsobjectmakearray gctxt (fromIntegral len) ptr exceptions
359-- | Make an JavaScript array from a list of values
399-- | Make an JavaScript array from a list of values
@@ -369,9 +409,18 @@ array = rethrow . makeArray
370-- | JavaScript's global object
410-- | JavaScript's global object
371global :: JSC JSObjectRef
411global :: JSC JSObjectRef
412+#if defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)
413+global = liftIO js_window
414+foreign import javascript unsafe "$r = window"
415+ js_window :: IO JSObjectRef
416+#elif defined(USE_WEBKIT)
372global = ask >>= (liftIO . jscontextgetglobalobject)
417global = ask >>= (liftIO . jscontextgetglobalobject)
374-- | Get an array containing the property names present on a given object
422-- | Get an array containing the property names present on a given object
423+#if (!defined(__GHCJS__) || !defined(USE_JAVASCRIPTFFI)) && defined(USE_WEBKIT)
375copyPropertyNames :: MakeObjectRef this => this -> JSC JSPropertyNameArrayRef
424copyPropertyNames :: MakeObjectRef this => this -> JSC JSPropertyNameArrayRef
376copyPropertyNames this = do
425copyPropertyNames this = do
377 gctxt <- ask
426 gctxt <- ask
@@ -391,10 +440,19 @@ propertyNamesList :: MonadIO m => JSPropertyNameArrayRef -> m [JSStringRef]
391propertyNamesList names = do
440propertyNamesList names = do
392 count <- propertyNamesCount names
441 count <- propertyNamesCount names
393 mapM (propertyNamesAt names) $ enumFromTo 0 (count - 1)
442 mapM (propertyNamesAt names) $ enumFromTo 0 (count - 1)
395-- | Get a list containing the property names present on a given object
445-- | Get a list containing the property names present on a given object
396propertyNames :: MakeObjectRef this => this -> JSC [JSStringRef]
446propertyNames :: MakeObjectRef this => this -> JSC [JSStringRef]
447+#if defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)
448+propertyNames this = makeObjectRef this >>= liftIO . js_propertyNames >>= liftIO . fromArray
449+foreign import javascript unsafe "$r = []; h$forIn($1, function(n){$r.push(n);})"
450+ js_propertyNames :: JSObjectRef -> IO (JSArray a)
451+#elif defined(USE_WEBKIT)
397propertyNames this = copyPropertyNames this >>= propertyNamesList
452propertyNames this = copyPropertyNames this >>= propertyNamesList
454+propertyNames = undefined
399-- | Get a list containing references to all the properties present on a given object
457-- | Get a list containing references to all the properties present on a given object
400properties :: MakeObjectRef this => this -> JSC [JSPropRef]
458properties :: MakeObjectRef this => this -> JSC [JSPropRef]
@@ -407,11 +465,21 @@ objCallAsFunction :: MakeArgRefs args
408 -> JSValueRefRef
466 -> JSValueRefRef
409 -> JSC JSValueRef
467 -> JSC JSValueRef
468+#if defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)
469+objCallAsFunction function this args exceptions = do
470+ rargs <- makeArgRefs args >>= liftIO . toArray
471+ liftIO $ js_apply function this rargs exceptions
472+foreign import javascript unsafe "try { $r = $1.apply($2, $3) } catch(e) { $4[0] = e }"
473+ js_apply :: JSObjectRef -> JSObjectRef -> JSValueRefRef -> JSValueRefRef -> IO JSValueRef
474+#elif defined(USE_WEBKIT)
410objCallAsFunction function this args exceptions = do
475objCallAsFunction function this args exceptions = do
411 gctxt <- ask
476 gctxt <- ask
412 rargs <- makeArgRefs args
477 rargs <- makeArgRefs args
413 liftIO $ withArrayLen rargs $ \ largs pargs ->
478 liftIO $ withArrayLen rargs $ \ largs pargs ->
414 jsobjectcallasfunction gctxt function this (fromIntegral largs) pargs exceptions
479 jsobjectcallasfunction gctxt function this (fromIntegral largs) pargs exceptions
481+objCallAsFunction = undefined
416-- | Call a JavaScript object as a constructor. Consider using 'new'.
484-- | Call a JavaScript object as a constructor. Consider using 'new'.
417objCallAsConstructor :: MakeArgRefs args
485objCallAsConstructor :: MakeArgRefs args
@@ -419,11 +487,44 @@ objCallAsConstructor :: MakeArgRefs args
420 -> JSValueRefRef
488 -> JSValueRefRef
421 -> JSC JSValueRef
489 -> JSC JSValueRef
490+#if defined(__GHCJS__) && defined(USE_JAVASCRIPTFFI)
491+objCallAsConstructor function args exceptions = do
492+ rargs <- makeArgRefs args >>= liftIO . toArray
493+ liftIO $ js_new function rargs exceptions
494+foreign import javascript unsafe "\
496+ switch($2.length) {\
497+ case 0 : $r = new $1();\
498+ case 1 : $r = new $1($2[0]);\
499+ case 2 : $r = new $1($2[0],$2[1]);\
500+ case 3 : $r = new $1($2[0],$2[1],$2[2]);\
501+ case 4 : $r = new $1($2[0],$2[1],$2[2],$2[3]);\
502+ case 5 : $r = new $1($2[0],$2[1],$2[2],$2[3],$2[4]);\
503+ case 6 : $r = new $1($2[0],$2[1],$2[2],$2[3],$2[4],$2[5]);\
504+ case 6 : $r = new $1($2[0],$2[1],$2[2],$2[3],$2[4],$2[5],$2[6]);\
507+ var temp = function() {\
508+ ret = $1.apply(this, $2);\
510+ temp.prototype = f.prototype;\
511+ var i = new temp();\
512+ $r = ret instanceof Object ? ret : i;\
518+ js_new :: JSObjectRef -> JSValueRefRef -> JSValueRefRef -> IO JSValueRef
519+#elif defined(USE_WEBKIT)
422objCallAsConstructor function args exceptions = do
520objCallAsConstructor function args exceptions = do
423 gctxt <- ask
521 gctxt <- ask
424 rargs <- makeArgRefs args
522 rargs <- makeArgRefs args
425 liftIO $ withArrayLen rargs $ \ largs pargs ->
523 liftIO $ withArrayLen rargs $ \ largs pargs ->
426 jsobjectcallasconstructor gctxt function (fromIntegral largs) pargs exceptions
524 jsobjectcallasconstructor gctxt function (fromIntegral largs) pargs exceptions
526+objCallAsConstructor = undefined