@@ -1,11 +1,12 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2{-# LANGUAGE ForeignFunctionInterface #-}
3{-# LANGUAGE ForeignFunctionInterface #-}
3{-# LANGUAGE JavaScriptFFI #-}
4{-# LANGUAGE JavaScriptFFI #-}
4−{-# LANGUAGE MagicHash #-}
5+#endif
5module Reflex.FastWeak
6module Reflex.FastWeak
6 ( FastWeakTicket
7 ( FastWeakTicket
8− , fastWeakTicket
9+ , mkFastWeakTicket
9 , fastWeakTicketValue
10 , fastWeakTicketValue
10 , getFastWeakTicketWeak
11 , getFastWeakTicketWeak
11 , getFastWeakValue
12 , getFastWeakValue
@@ -15,21 +16,26 @@ module Reflex.FastWeak
15import GHCJS.Types
16import GHCJS.Types
16import Unsafe.Coerce
17import Unsafe.Coerce
19+import Control.Exception (evaluate)
20+import System.Mem.Weak
21#ifdef ghcjs_HOST_OS
24#ifdef ghcjs_HOST_OS
22−type Ref = JSVal
25+newtype FastWeakTicket a = FastWeakTicket JSVal
27−newtype FastWeakTicket a = FastWeakTicket Ref
29−newtype FastWeak a = FastWeak Ref
27+newtype FastWeak a = FastWeak JSVal
31-- Just designed to mirror JSVal, so that we can unsafeCoerce between the two
29-- Just designed to mirror JSVal, so that we can unsafeCoerce between the two
32data Val a = Val { unVal :: a }
30data Val a = Val { unVal :: a }
32+data FastWeakTicket a = FastWeakTicket
33+ { _fastWeakTicket_val :: !a
34+ , _fastWeakTicket_weak :: {-# UNPACK #-} !(Weak a)
37+type FastWeak a = Weak a
34-- Do we have a concern about accidentally retaining the ticket here?
40-- Do we have a concern about accidentally retaining the ticket here?
35fastWeakTicketValue :: FastWeakTicket a -> a
41fastWeakTicketValue :: FastWeakTicket a -> a
@@ -38,7 +44,7 @@ fastWeakTicketValue t = unVal (unsafeCoerce (js_ticketVal t))
39foreign import javascript unsafe "$r = $1.val;" js_ticketVal :: FastWeakTicket a -> JSVal
45foreign import javascript unsafe "$r = $1.val;" js_ticketVal :: FastWeakTicket a -> JSVal
41−fastWeakTicketValue = error "fastWeakTicketValue not implemented"
47+fastWeakTicketValue = _fastWeakTicket_val
44getFastWeakValue :: FastWeak a -> IO (Maybe a)
50getFastWeakValue :: FastWeak a -> IO (Maybe a)
@@ -53,17 +59,23 @@ foreign import javascript unsafe "$1 === null" js_isNull :: JSVal -> Bool
54foreign import javascript unsafe "$r = ($1.ticket === null) ? null : $1.ticket.val;" js_weakVal :: FastWeak a -> IO JSVal
60foreign import javascript unsafe "$r = ($1.ticket === null) ? null : $1.ticket.val;" js_weakVal :: FastWeak a -> IO JSVal
56−getFastWeakValue = error "getFastWeakValue not implemented"
62+getFastWeakValue = deRefWeak
59-- I think it's fine if this is lazy - it'll retain the 'a', but so would the output; we just need to make sure it's forced before we start relying on the associated FastWeak to actually be weak
65-- I think it's fine if this is lazy - it'll retain the 'a', but so would the output; we just need to make sure it's forced before we start relying on the associated FastWeak to actually be weak
60−fastWeakTicket :: a -> FastWeakTicket a
66+mkFastWeakTicket :: a -> IO (FastWeakTicket a)
61#ifdef ghcjs_HOST_OS
67#ifdef ghcjs_HOST_OS
62−fastWeakTicket v = js_fastWeakTicket (unsafeCoerce (Val v))
68+mkFastWeakTicket v = js_fastWeakTicket (unsafeCoerce (Val v))
64−foreign import javascript unsafe "$r = new h$FastWeakTicket($1);" js_fastWeakTicket :: JSVal -> FastWeakTicket a
70+foreign import javascript unsafe "$r = new h$FastWeakTicket($1);" js_fastWeakTicket :: JSVal -> IO (FastWeakTicket a)
66−fastWeakTicket = error "fastWeakTicket not implemented"
72+mkFastWeakTicket v = do
74+ w <- mkWeakPtr v' Nothing
75+ return $ FastWeakTicket
76+ { _fastWeakTicket_val = v'
77+ , _fastWeakTicket_weak = w
69-- Needs IO so that it can force the value - otherwise, could end up with a reference to the Ticket, which would retain the value
81-- Needs IO so that it can force the value - otherwise, could end up with a reference to the Ticket, which would retain the value
@@ -71,5 +83,5 @@ fastWeakTicket = error "fastWeakTicket not implemented"
71foreign import javascript unsafe "$r = $1.weak;" getFastWeakTicketWeak :: FastWeakTicket a -> IO (FastWeak a)
83foreign import javascript unsafe "$r = $1.weak;" getFastWeakTicketWeak :: FastWeakTicket a -> IO (FastWeak a)
73getFastWeakTicketWeak :: FastWeakTicket a -> IO (FastWeak a)
85getFastWeakTicketWeak :: FastWeakTicket a -> IO (FastWeak a)
74−getFastWeakTicketWeak = error "fastWeakTicketWeak not implemented"
86+getFastWeakTicketWeak = return . _fastWeakTicket_weak