2{-# LANGUAGE LambdaCase #-}
3{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE ForeignFunctionInterface #-}
6{-# LANGUAGE JavaScriptFFI #-}
12 , getFastWeakTicketValue
13 , getFastWeakTicketWeak
18 --TODO: Move these elsewhere
31import Control.Exception (evaluate)
32import System.IO.Unsafe
38newtype FastWeakTicket a = FastWeakTicket JSVal
40newtype FastWeak a = FastWeak JSVal
42-- Just designed to mirror JSVal, so that we can unsafeCoerce between the two
43data Val a = Val { unVal :: a }
45-- | Coerce a JSVal that represents the heap object of a value of type 'a' into a value of type 'a'
46unsafeFromRawJSVal :: JSVal -> a
47unsafeFromRawJSVal v = unVal (unsafeCoerce v)
49unsafeToRawJSVal :: a -> JSVal
50unsafeToRawJSVal v = unsafeCoerce (Val v)
52data FastWeakTicket a = FastWeakTicket
53 { _fastWeakTicket_val :: !a
54 , _fastWeakTicket_weak :: {-# UNPACK #-} !(Weak a)
57type FastWeak a = Weak a
60-- This needs to be in IO so we know that we've relinquished the ticket
61getFastWeakTicketValue :: FastWeakTicket a -> IO a
63getFastWeakTicketValue t = do
65 return $ unsafeFromRawJSVal v
67foreign import javascript unsafe "$r = $1.val;" js_ticketVal :: FastWeakTicket a -> IO JSVal
69getFastWeakTicketValue = return . _fastWeakTicket_val
72getFastWeakValue :: FastWeak a -> IO (Maybe a)
74getFastWeakValue w = do
77 True -> return Nothing
78 False -> return $ Just $ unsafeFromRawJSVal r
80foreign import javascript unsafe "$1 === null" js_isNull :: JSVal -> Bool
82foreign import javascript unsafe "$r = ($1.ticket === null) ? null : $1.ticket.val;" js_weakVal :: FastWeak a -> IO JSVal
84getFastWeakValue = deRefWeak
87getFastWeakTicket :: forall a. FastWeak a -> IO (Maybe (FastWeakTicket a))
89getFastWeakTicket w = do
92 True -> return Nothing
93 False -> return $ Just $ FastWeakTicket r
95foreign import javascript unsafe "$r = $1.ticket;" js_weakTicket :: FastWeak a -> IO JSVal
97getFastWeakTicket w = do
99 Nothing -> return Nothing
100 Just v -> return $ Just $ FastWeakTicket
101 { _fastWeakTicket_val = v
102 , _fastWeakTicket_weak = w
106-- 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
107mkFastWeakTicket :: a -> IO (FastWeakTicket a)
108#ifdef GHCJS_FAST_WEAK
109mkFastWeakTicket v = js_fastWeakTicket (unsafeToRawJSVal v)
111foreign import javascript unsafe "$r = new h$FastWeakTicket($1);" js_fastWeakTicket :: JSVal -> IO (FastWeakTicket a)
113mkFastWeakTicket v = do
115 w <- mkWeakPtr v' Nothing
116 return $ FastWeakTicket
117 { _fastWeakTicket_val = v'
118 , _fastWeakTicket_weak = w
122-- Needs IO so that it can force the value - otherwise, could end up with a reference to the Ticket, which would retain the value
123#ifdef GHCJS_FAST_WEAK
124foreign import javascript unsafe "$r = $1.weak;" getFastWeakTicketWeak :: FastWeakTicket a -> IO (FastWeak a)
126getFastWeakTicketWeak :: FastWeakTicket a -> IO (FastWeak a)
127getFastWeakTicketWeak = return . _fastWeakTicket_weak
130-- | A weak reference that is always empty
131emptyFastWeak :: FastWeak a
132emptyFastWeak = unsafeCoerce w
133 where w :: FastWeak Any
134#ifdef GHCJS_FAST_WEAK
137 w = unsafePerformIO $ do
138 w' <- mkWeakPtr undefined Nothing
142{-# NOINLINE emptyFastWeak #-}
144#ifdef GHCJS_FAST_WEAK
145foreign import javascript unsafe "$r = new h$FastWeak(null);" js_emptyWeak :: FastWeak Any
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list