on master help sign in
Fix JSVal finalizer issue. Fix #29
commit8227b4c3aad379145f8934726cfa700e40ed5316 authorHamish Mackenzie <Hamish.K.Mackenzie@googlemail.com> dateFri 11 Aug 2017, 23:48 (9 years ago) parentd4e1706
18 files changed+136−84
jsaddle-warp/default.nix+1−1 jsaddle-warp/jsaddle-warp.cabal+4−4 jsaddle-webkit2gtk/default.nix+1−1 jsaddle-webkit2gtk/jsaddle-webkit2gtk.cabal+8−7 jsaddle-webkit2gtk/src/Language/Javascript/JSaddle/WebKitGTK.hs+1−3 jsaddle-wkwebview/default.nix+1−1 jsaddle-wkwebview/jsaddle-wkwebview.cabal+2−2 jsaddle/default.nix+1−1 jsaddle/jsaddle.cabal+3−3 jsaddle/src-ghc/GHCJS/Foreign/Internal.hs+12−10 jsaddle/src-ghc/GHCJS/Prim/Internal.hs+5−3 jsaddle/src-ghc/GHCJS/Types.hs+5−3 jsaddle/src/Language/Javascript/JSaddle/Native/Internal.hs+39−24 jsaddle/src/Language/Javascript/JSaddle/Object.hs+14−4 jsaddle/src/Language/Javascript/JSaddle/Run.hs+31−12 jsaddle/src/Language/Javascript/JSaddle/Run/Files.hs+1−1 jsaddle/src/Language/Javascript/JSaddle/Types.hs+2−1 jsaddle/src/Language/Javascript/JSaddle/Value.hs+5−3
jsaddle-warp/default.nix+1−1
@@ -6,7 +6,7 @@
66}:
77mkDerivation {
88 pname = "jsaddle-warp";
9− version = "0.9.2.0";
9+ version = "0.9.4.0";
1010 src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".git" "dist" ])) ./.;
1111 libraryHaskellDepends = [
1212 aeson base bytestring containers foreign-store http-types jsaddle
jsaddle-warp/jsaddle-warp.cabal+4−4
@@ -1,5 +1,5 @@
11name: jsaddle-warp
2−version: 0.9.3.0
2+version: 0.9.4.0
33cabal-version: >=1.10
44build-type: Simple
55license: MIT
@@ -30,10 +30,10 @@ library
3030 containers >=0.5.6.2 && <0.6,
3131 foreign-store >=0.2 && <0.3,
3232 http-types >=0.8.6 && <0.10,
33− jsaddle >=0.9.2.0 && <0.10,
33+ jsaddle >=0.9.4.0 && <0.10,
3434 stm >=2.4.4 && <2.5,
3535 text >=1.2.1.3 && <1.3,
36− time >=1.5.0.1 && <1.8,
36+ time >=1.5.0.1 && <1.9,
3737 transformers >=0.4.2.0 && <0.6,
3838 wai >=3.0.3.0 && <3.3,
3939 wai-websockets >=3.0.0.6 && <3.1,
@@ -67,7 +67,7 @@ test-suite test-tool
6767 network -any,
6868 ref-tf -any,
6969 primitive -any,
70− process >=1.2.3.0 && <1.5,
70+ process >=1.2.3.0 && <1.7,
7171 stm -any,
7272 text -any,
7373 time -any,
jsaddle-webkit2gtk/default.nix+1−1
@@ -4,7 +4,7 @@
44}:
55mkDerivation {
66 pname = "jsaddle-webkit2gtk";
7− version = "0.9.0.0";
7+ version = "0.9.4.0";
88 src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".git" "dist" ])) ./.;
99 libraryHaskellDepends = [
1010 aeson base bytestring directory gi-gio gi-glib gi-gtk
jsaddle-webkit2gtk/jsaddle-webkit2gtk.cabal+8−7
@@ -1,5 +1,5 @@
11name: jsaddle-webkit2gtk
2−version: 0.9.0.0
2+version: 0.9.4.0
33cabal-version: >=1.10
44build-type: Simple
55license: MIT
@@ -30,13 +30,14 @@ library
3030 base <5,
3131 bytestring >=0.10.6.0 && <0.11,
3232 directory >=1.0.0.2 && <1.4,
33− gi-glib >=2.0.6 && <2.1,
34− gi-gio >=2.0.6 && <2.1,
35− gi-gtk >=3.0.6 && <3.1,
36− gi-webkit2 >=4.0.6 && <4.1,
37− gi-javascriptcore >=4.0.6 && <4.1,
33+ gi-glib >=2.0.14 && <2.1,
34+ gi-gio >=2.0.14 && <2.1,
35+ gi-gtk >=3.0.17 && <3.1,
36+ gi-webkit2 >=4.0.14 && <4.1,
37+ gi-javascriptcore >=4.0.14 && <4.1,
3838 haskell-gi-base >=0.20 && <0.21,
39− jsaddle >=0.9.0.0 && <0.10,
39+ haskell-gi-overloading ==0.0.*,
40+ jsaddle >=0.9.4.0 && <0.10,
4041 text >=1.2.1.3 && <1.3,
4142 webkit2gtk3-javascriptcore >=0.14.0.0 && <0.15
4243 if !os(windows)
jsaddle-webkit2gtk/src/Language/Javascript/JSaddle/WebKitGTK.hs+1−3
@@ -206,9 +206,7 @@ jsaddleJs = ghcjsHelpers <> mconcat
206206 , initState
207207 , "\nreturn function(batch) {\n"
208208 , runBatch (\a -> "window.webkit.messageHandlers.jsaddle.postMessage(JSON.stringify(" <> a <> "));\n")
209− Nothing
210− -- TODO fix https://github.com/haskell-gi/haskell-gi/issues/97 then use
211− -- (Just (\a -> "JSON.parse(window.prompt(\"JSaddleSync\", JSON.stringify(" <> a <> ")))"))
209+ (Just (\a -> "JSON.parse(window.prompt(\"JSaddleSync\", JSON.stringify(" <> a <> ")))"))
212210 , "};\n"
213211 , "})()"
214212 ]
jsaddle-wkwebview/default.nix+1−1
@@ -4,7 +4,7 @@
44
55mkDerivation {
66 pname = "jsaddle-wkwebview";
7− version = "0.9.0.0";
7+ version = "0.9.4.0";
88 src = ./.;
99 libraryHaskellDepends = [ aeson base bytestring jsaddle data-default ];
1010 libraryDarwinFrameworkDepends = with buildPackages; if hostPlatform.useiOSCross or false then [
jsaddle-wkwebview/jsaddle-wkwebview.cabal+2−2
@@ -1,5 +1,5 @@
11name: jsaddle-wkwebview
2−version: 0.9.0.0
2+version: 0.9.4.0
33cabal-version: >=1.10
44build-type: Simple
55license: MIT
@@ -30,7 +30,7 @@ library
3030 aeson >=0.8.0.2 && <1.3,
3131 base <5,
3232 bytestring >=0.10.6.0 && <0.11,
33− jsaddle >= 0.9.0.0 && <0.10,
33+ jsaddle >= 0.9.4.0 && <0.10,
3434 data-default,
3535 containers
3636 default-language: Haskell2010
jsaddle/default.nix+1−1
@@ -5,7 +5,7 @@
55}:
66mkDerivation {
77 pname = "jsaddle";
8− version = "0.9.2.1";
8+ version = "0.9.4.0";
99 src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".git" "dist" ])) ./.;
1010 libraryHaskellDepends = [
1111 aeson attoparsec base base64-bytestring bytestring containers
jsaddle/jsaddle.cabal+3−3
@@ -1,5 +1,5 @@
11name: jsaddle
2−version: 0.9.3.0
2+version: 0.9.4.0
33cabal-version: >=1.10
44build-type: Simple
55license: MIT
@@ -41,12 +41,12 @@ library
4141 filepath >=1.4.0.0 && <1.5,
4242 ghc-prim,
4343 http-types >=0.8.6 && <0.10,
44− process >=1.2.3.0 && <1.5,
44+ process >=1.2.3.0 && <1.7,
4545 random >= 1.1 && < 1.2,
4646 ref-tf >=0.4.0.1 && <0.5,
4747 scientific >=0.3 && <0.4,
4848 stm >=2.4.4 && <2.5,
49− time >=1.5.0.1 && <1.8,
49+ time >=1.5.0.1 && <1.9,
5050 unordered-containers >=0.2 && <0.3,
5151 vector >=0.10 && <0.13
5252 exposed-modules:
jsaddle/src-ghc/GHCJS/Foreign/Internal.hs+12−10
@@ -27,26 +27,28 @@ import Language.Javascript.JSaddle.Native.Internal
2727 (valueToBool)
2828import Data.Typeable (Typeable)
2929import GHCJS.Prim (isNull, isUndefined)
30+import System.IO.Unsafe (unsafePerformIO)
31+import Data.IORef (newIORef)
3032
3133jsTrue :: JSVal
32−jsTrue = JSVal 3
33−{-# INLINE jsTrue #-}
34+jsTrue = JSVal . unsafePerformIO $ newIORef 3
35+{-# NOINLINE jsTrue #-}
3436
3537jsFalse :: JSVal
36−jsFalse = JSVal 2
37−{-# INLINE jsFalse #-}
38+jsFalse = JSVal . unsafePerformIO $ newIORef 2
39+{-# NOINLINE jsFalse #-}
3840
3941jsNull :: JSVal
40−jsNull = JSVal 0
41−{-# INLINE jsNull #-}
42+jsNull = JSVal . unsafePerformIO $ newIORef 0
43+{-# NOINLINE jsNull #-}
4244
4345toJSBool :: Bool -> JSVal
44−toJSBool b = JSVal $ if b then 3 else 2
45−{-# INLINE toJSBool #-}
46+toJSBool b = JSVal . unsafePerformIO . newIORef $ if b then 3 else 2
47+{-# NOINLINE toJSBool #-}
4648
4749jsUndefined :: JSVal
48−jsUndefined = JSVal 1
49−{-# INLINE jsUndefined #-}
50+jsUndefined = JSVal . unsafePerformIO $ newIORef 1
51+{-# NOINLINE jsUndefined #-}
5052
5153isTruthy :: JSVal -> GHCJSPure Bool
5254isTruthy = GHCJSPure . valueToBool
jsaddle/src-ghc/GHCJS/Prim/Internal.hs+5−3
@@ -17,6 +17,8 @@ import Unsafe.Coerce (unsafeCoerce)
1717import Data.Aeson (ToJSON(..), FromJSON(..))
1818
1919import qualified GHC.Exception as Ex
20+import Data.IORef (newIORef, IORef)
21+import System.IO.Unsafe (unsafePerformIO)
2022
2123-- A reference to a particular JavaScript value inside the JavaScript context
2224type JSValueRef = Int64
@@ -25,7 +27,7 @@ type JSValueRef = Int64
2527 JSVal is a boxed type that can be used as FFI
2628 argument or result.
2729-}
28−newtype JSVal = JSVal JSValueRef deriving(Show, ToJSON, FromJSON)
30+newtype JSVal = JSVal (IORef JSValueRef)
2931
3032instance NFData JSVal where
3133 rnf x = x `seq` ()
@@ -49,8 +51,8 @@ mkJSException ref =
4951 return (JSException (unsafeCoerce ref) "")
5052
5153jsNull :: JSVal
52−jsNull = JSVal 0
53−{-# INLINE jsNull #-}
54+jsNull = JSVal . unsafePerformIO $ newIORef 0
55+{-# NOINLINE jsNull #-}
5456
5557{- | If a synchronous thread tries to do something that can only
5658 be done asynchronously, and the thread is set up to not
jsaddle/src-ghc/GHCJS/Types.hs+5−3
@@ -27,19 +27,21 @@ import GHC.Int
2727import GHC.Types
2828import GHC.Prim
2929import GHC.Ptr
30+import GHC.IORef
31+import GHC.IO.Unsafe (unsafePerformIO)
3032
3133import Control.DeepSeq
3234import Unsafe.Coerce
3335
34−type Ref# = Int64
36+type Ref# = IORef Int64
3537
3638mkRef :: Ref# -> JSVal
3739mkRef = JSVal
3840{-# INLINE mkRef #-}
3941
4042nullRef :: JSVal
41−nullRef = JSVal 0
42−{-# INLINE nullRef #-}
43+nullRef = JSVal . unsafePerformIO $ newIORef 0
44+{-# NOINLINE nullRef #-}
4345
4446--toPtr :: JSVal -> Ptr a
4547--toPtr (JSVal x) = unsafeCoerce (Ptr' x 0#)
jsaddle/src/Language/Javascript/JSaddle/Native/Internal.hs+39−24
@@ -1,3 +1,6 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE MagicHash #-}
3+{-# LANGUAGE UnboxedTuples #-}
14-----------------------------------------------------------------------------
25--
36-- Module : Language.Javascript.JSaddle.Native
@@ -45,7 +48,6 @@ module Language.Javascript.JSaddle.Native.Internal (
4548) where
4649
4750import Control.Monad.IO.Class (MonadIO(..))
48−import Control.Monad.Primitive (touch)
4951
5052import Data.Aeson (Value)
5153
@@ -57,30 +59,34 @@ import Language.Javascript.JSaddle.Monad (askJSM)
5759import Language.Javascript.JSaddle.Run
5860 (Command(..), Result(..), sendCommand,
5961 sendAsyncCommand, sendLazyCommand, wrapJSVal)
62+import GHC.IORef (IORef(..), readIORef)
63+import GHC.STRef (STRef(..))
64+import GHC.IO (IO(..))
65+import GHC.Base (touch#)
6066
6167wrapJSString :: MonadIO m => JSStringReceived -> m JSString
6268wrapJSString (JSStringReceived ref) = return $ JSString ref
6369
70+touchIORef :: IORef a -> IO ()
71+touchIORef (IORef (STRef r#)) = IO $ \s -> case touch# r# s of s' -> (# s', () #)
72+
6473withJSVal :: MonadIO m => JSVal -> (JSValueForSend -> m a) -> m a
6574withJSVal (JSVal ref) f = do
66− result <- f (JSValueForSend ref)
67− liftIO $ touch ref
75+ result <- (f . JSValueForSend) =<< liftIO (readIORef ref)
76+ liftIO $ touchIORef ref
6877 return result
6978
7079withJSVals :: MonadIO m => [JSVal] -> ([JSValueForSend] -> m a) -> m a
7180withJSVals v f =
72− do result <- f (map (\(JSVal ref) -> JSValueForSend ref) v)
73− liftIO $ mapM_ touch v
81+ do result <- f =<< mapM (\(JSVal ref) -> liftIO $ JSValueForSend <$> readIORef ref) v
82+ liftIO $ mapM_ (\(JSVal ref) -> touchIORef ref) v
7483 return result
7584
7685withObject :: MonadIO m => Object -> (JSObjectForSend -> m a) -> m a
7786withObject (Object o) f = withJSVal o (f . JSObjectForSend)
7887
7988withJSString :: MonadIO m => JSString -> (JSStringForSend -> m a) -> m a
80−withJSString v@(JSString ref) f =
81− do result <- f (JSStringForSend ref)
82− liftIO $ touch v
83− return result
89+withJSString (JSString ref) f = f (JSStringForSend ref)
8490
8591setPropertyByName :: JSString -> JSVal -> Object -> JSM ()
8692setPropertyByName name val this =
@@ -166,13 +172,14 @@ deRefVal value = withJSVal value $ sendCommand . DeRefVal
166172{-# INLINE deRefVal #-}
167173
168174valueToBool :: JSVal -> JSM Bool
169−valueToBool (JSVal 0) = return False -- null
170−valueToBool (JSVal 1) = return False -- undefined
171−valueToBool (JSVal 2) = return False -- false
172−valueToBool (JSVal 3) = return True -- true
173−valueToBool v = withJSVal v $ \rval -> do
174− ~(ValueToBoolResult result) <- sendCommand (ValueToBool rval)
175− return result
175+valueToBool v@(JSVal ref) = liftIO (readIORef ref) >>= \case
176+ 0 -> return False -- null
177+ 1 -> return False -- undefined
178+ 2 -> return False -- false
179+ 3 -> return True -- true
180+ _ -> withJSVal v $ \rval -> do
181+ ~(ValueToBoolResult result) <- sendCommand (ValueToBool rval)
182+ return result
176183{-# INLINE valueToBool #-}
177184
178185valueToNumber :: JSVal -> JSM Double
@@ -201,17 +208,25 @@ valueToJSONValue value = withJSVal value $ \rval -> do
201208{-# INLINE valueToJSONValue #-}
202209
203210isNull :: JSVal -> JSM Bool
204−isNull (JSVal 0) = return True
205−isNull v = withJSVal v $ \rval -> do
206− ~(IsNullResult result) <- sendCommand $ IsNull rval
207− return result
211+isNull v@(JSVal ref) = liftIO (readIORef ref) >>= \case
212+ 0 -> return True -- null
213+ 1 -> return False -- undefined
214+ 2 -> return False -- false
215+ 3 -> return False -- true
216+ _ -> withJSVal v $ \rval -> do
217+ ~(IsNullResult result) <- sendCommand $ IsNull rval
218+ return result
208219{-# INLINE isNull #-}
209220
210221isUndefined :: JSVal -> JSM Bool
211−isUndefined (JSVal 1) = return True
212−isUndefined v = withJSVal v $ \rval -> do
213− ~(IsUndefinedResult result) <- sendCommand $ IsUndefined rval
214− return result
222+isUndefined v@(JSVal ref) = liftIO (readIORef ref) >>= \case
223+ 0 -> return False -- null
224+ 1 -> return True -- undefined
225+ 2 -> return False -- false
226+ 3 -> return False -- true
227+ _ -> withJSVal v $ \rval -> do
228+ ~(IsUndefinedResult result) <- sendCommand $ IsUndefined rval
229+ return result
215230{-# INLINE isUndefined #-}
216231
217232strictEqual :: JSVal -> JSVal -> JSM Bool
jsaddle/src/Language/Javascript/JSaddle/Object.hs+14−4
@@ -132,6 +132,8 @@ import Language.Javascript.JSaddle.Arguments (MakeArgs(..))
132132import Control.Monad.IO.Class (MonadIO(..))
133133import Language.Javascript.JSaddle.Properties
134134import Control.Lens (IndexPreservingGetter, to)
135+import Data.IORef (newIORef, readIORef)
136+import System.IO.Unsafe (unsafePerformIO)
135137
136138-- $setup
137139-- >>> import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
@@ -482,8 +484,16 @@ freeFunction :: Function -> JSM ()
482484freeFunction (Function callback _) = liftIO $
483485 releaseCallback callback
484486#else
485−freeFunction (Function (Object (JSVal objectRef))) =
486− sendAsyncCommand (FreeCallback (JSValueForSend objectRef))
487+freeFunction (Function (Object (JSVal objectRef))) = do
488+ -- By now the callback should ideally have been removed from whatever
489+ -- events it was added to.
490+ -- In case a call to the callback is still pending (perhaps just being sent
491+ -- on the JS side) we use FreeCallback to queue the callback to be freed when
492+ -- the next batch of results comes back fro JS.
493+ -- We are not using withJSVal to keep JS value "alive" because FreeCallback
494+ -- does not use the it.
495+ n <- liftIO $ readIORef objectRef
496+ sendAsyncCommand (FreeCallback (JSValueForSend n))
487497#endif
488498
489499instance ToJSVal Function where
@@ -522,7 +532,7 @@ global = js_window
522532foreign import javascript unsafe "$r = window"
523533 js_window :: Object
524534#else
525−global = Object (JSVal 4)
535+global = Object . JSVal . unsafePerformIO $ newIORef 4
526536#endif
527537
528538-- | Get a list containing the property names present on a given object
@@ -603,5 +613,5 @@ nullObject :: Object
603613#ifdef ghcjs_HOST_OS
604614nullObject = Object nullRef
605615#else
606−nullObject = Object (JSVal 0)
616+nullObject = Object . JSVal . unsafePerformIO $ newIORef 0
607617#endif
jsaddle/src/Language/Javascript/JSaddle/Run.hs+31−12
@@ -65,13 +65,14 @@ import qualified Data.Text as T (unpack, pack)
6565import qualified Data.Map as M (lookup, delete, insert, empty, size)
6666import qualified Data.Set as S (empty, member, insert, delete)
6767import Data.Time.Clock (getCurrentTime,diffUTCTime)
68−import Data.IORef (newIORef, atomicWriteIORef, readIORef)
68+import Data.IORef
69+ (mkWeakIORef, newIORef, atomicWriteIORef, readIORef)
6970
7071import Language.Javascript.JSaddle.Types
7172 (Command(..), AsyncCommand(..), Result(..), BatchResults(..), Results(..), JSContextRef(..), JSVal(..),
7273 Object(..), JSValueReceived(..), JSM(..), Batch(..), JSValueForSend(..))
7374import Language.Javascript.JSaddle.Exception (JSException(..))
74−import Control.DeepSeq (deepseq)
75+import Control.DeepSeq (force, deepseq)
7576import GHC.Stats (getGCStatsEnabled, getGCStats, GCStats(..))
7677import Data.Foldable (forM_)
7778#endif
@@ -165,6 +166,7 @@ runJavaScript sendBatch entryPoint = do
165166 finalizerThreads' <- newMVar S.empty
166167 animationFrameHandlers' <- newMVar []
167168 loggingEnabled <- newIORef False
169+ liveRefs' <- newMVar S.empty
168170 let ctx = JSContextRef {
169171 contextId = contextId'
170172 , startTime = startTime'
@@ -173,14 +175,19 @@ runJavaScript sendBatch entryPoint = do
173175 atomically $ writeTChan commandChan (Right (cmd, result))
174176 unsafeInterleaveIO $
175177 takeMVar result >>= \case
176− (ThrowJSValue (JSValueReceived v)) -> throwIO $ JSException (JSVal v)
178+ (ThrowJSValue v) -> do
179+ jsval <- wrapJSVal' ctx v
180+ throwIO $ JSException jsval
177181 r -> return r
178182 , doSendAsyncCommand = \cmd -> cmd `deepseq` atomically (writeTChan commandChan $ Left cmd)
179− , addCallback = \(Object (JSVal val)) cb -> atomically $ modifyTVar' callbacks (M.insert val cb)
183+ , addCallback = \(Object (JSVal ioref)) cb -> do
184+ val <- readIORef ioref
185+ atomically $ modifyTVar' callbacks (M.insert val cb)
180186 , nextRef = nextRef'
181187 , doEnableLogging = atomicWriteIORef loggingEnabled
182188 , finalizerThreads = finalizerThreads'
183189 , animationFrameHandlers = animationFrameHandlers'
190+ , liveRefs = liveRefs'
184191 }
185192 processResults :: Bool -> Results -> IO ()
186193 processResults syncCallbacks = \case
@@ -282,17 +289,29 @@ addThreadFinalizer :: ThreadId -> IO () -> IO ()
282289addThreadFinalizer t@(ThreadId t#) (IO finalizer) =
283290 IO $ \s -> case mkWeak# t# t finalizer s of { (# s1, _ #) -> (# s1, () #) }
284291
292+
285293wrapJSVal :: JSValueReceived -> JSM JSVal
286−wrapJSVal (JSValueReceived ref) = do
287− -- TODO make sure this ref has not already been wrapped (perhaps only in debug version)
288− let result = JSVal ref
289− when (ref >= 5 || ref < 0) $ do
290− ctx <- JSM ask
291− liftIO . addFinalizer ref $ do
294+wrapJSVal v = do
295+ ctx <- JSM ask
296+ liftIO $ wrapJSVal' ctx v
297+
298+wrapJSVal' :: JSContextRef -> JSValueReceived -> IO JSVal
299+wrapJSVal' ctx (JSValueReceived n) = do
300+ ref <- liftIO $ newIORef n
301+ when (n >= 5 || n < 0) $
302+#ifdef JSADDLE_CHECK_WRAPJSVAL
303+ do lr <- takeMVar $ liveRefs ctx
304+ if n `S.member` lr
305+ then do
306+ putStrLn $ "JS Value Ref " <> show n <> " already wrapped"
307+ putMVar (liveRefs ctx) lr
308+ else putMVar (liveRefs ctx) =<< evaluate (S.insert n lr)
309+#endif
310+ void . mkWeakIORef ref $ do
292311 ft <- takeMVar $ finalizerThreads ctx
293312 t <- myThreadId
294313 let tname = T.pack $ show t
295− doSendAsyncCommand ctx $ FreeRef tname $ JSValueForSend ref
314+ doSendAsyncCommand ctx $ FreeRef tname $ JSValueForSend n
296315 if tname `S.member` ft
297316 then putMVar (finalizerThreads ctx) ft
298317 else do
@@ -300,5 +319,5 @@ wrapJSVal (JSValueReceived ref) = do
300319 modifyMVar (finalizerThreads ctx) $ \s -> return (S.delete tname s, ())
301320 doSendAsyncCommand ctx $ FreeRefs tname
302321 putMVar (finalizerThreads ctx) =<< evaluate (S.insert tname ft)
303− return result
322+ return (JSVal ref)
304323#endif
jsaddle/src/Language/Javascript/JSaddle/Run/Files.hs+1−1
@@ -244,7 +244,7 @@ runBatch send sendSync = "\
244244 \ (v === true ) ? [3, \"\"] :\n\
245245 \ (typeof v === \"number\") ? [-1, v.toString()] :\n\
246246 \ (typeof v === \"string\") ? [-2, v]\n\
247− \ : [n, \"\"];\n\
247+ \ : [-3, \"\"];\n\
248248 \ results.push({\"tag\": \"DeRefValResult\", \"contents\": c});\n\
249249 \ break;\n\
250250 \ case \"IsNull\":\n\
jsaddle/src/Language/Javascript/JSaddle/Types.hs+2−1
@@ -141,6 +141,7 @@ data JSContextRef = JSContextRef {
141141 , doEnableLogging :: Bool -> IO ()
142142 , finalizerThreads :: MVar (Set Text)
143143 , animationFrameHandlers :: MVar [Double -> JSM ()]
144+ , liveRefs :: MVar (Set Int64)
144145}
145146#endif
146147
@@ -339,7 +340,7 @@ type MutableJSArray = SomeJSArray Mutable
339340type STJSArray s = SomeJSArray (STMutable s)
340341
341342-- | See 'JavaScript.Object.Internal.Object'
342−newtype Object = Object JSVal deriving(Show, ToJSON, FromJSON)
343+newtype Object = Object JSVal
343344
344345-- | See 'GHCJS.Nullable.Nullable'
345346newtype Nullable a = Nullable a
jsaddle/src/Language/Javascript/JSaddle/Value.hs+5−3
@@ -618,15 +618,17 @@ foreign import javascript unsafe "$r = ($1 === undefined)?0:\
618618 (typeof $1===\"string\")?4:\
619619 (typeof $1===\"object\")?5:-1;" jsrefGetType :: JSVal -> Int
620620#else
621−deRefVal value = toJSVal value >>= N.deRefVal >>= \result -> return $
622− case result of
621+deRefVal value = do
622+ v <- toJSVal value
623+ result <- N.deRefVal v
624+ return $ case result of
623625 DeRefValResult 0 _ -> ValNull
624626 DeRefValResult 1 _ -> ValUndefined
625627 DeRefValResult 2 _ -> ValBool False
626628 DeRefValResult 3 _ -> ValBool True
627629 DeRefValResult (-1) s -> ValNumber (read (T.unpack s))
628630 DeRefValResult (-2) s -> ValString s
629− DeRefValResult ref _ -> ValObject (Object (JSVal ref))
631+ DeRefValResult (-3) _ -> ValObject (Object v)
630632 _ -> error "Unexpected result dereferencing JSaddle value"
631633#endif
632634