packages feed

threepenny-gui 0.6.0.3 → 0.6.0.4

raw patch · 6 files changed

+91/−49 lines, 6 filesdep ~aesondep ~vector

Dependency ranges changed: aeson, vector

Files

CHANGELOG.md view
@@ -1,5 +1,15 @@ ## Changelog for the `threepenny-gui` package +**0.6.0.4** -- Maintenance release.++* Elements that have become unreachable, for instance because they have been removed from the DOM and are no longer reachable in the Haskell code, will be garbage collected again. Fix [#109][], [#113][].+* Adjust dependencies.+* Add `<meta>` tag to indicate UTF8 encoding in html file. [#116][]++  [#113]: https://github.com/HeinrichApfelmus/threepenny-gui/issues/113+  [#109]: https://github.com/HeinrichApfelmus/threepenny-gui/issues/109+  [#116]: https://github.com/HeinrichApfelmus/threepenny-gui/issues/116+ **0.6.0.3** -- Maintenance release.  * Temporary fix for #109, which was causing event handlers to be discarded. Unfortunately, this means that elements are currently not garbage collected after they have been removed from the DOM tree.
js/index.html view
@@ -1,5 +1,6 @@ <!doctype html> <head>+  <meta charset="UTF-8">   <title></title>   <link rel="stylesheet" type="text/css" href="haskell.css"/>   <script src="haskell.js"></script>
src/Graphics/UI/Threepenny/Core.hs view
@@ -361,7 +361,7 @@ instance Widget Element where     getElement = id --- | Convience synonym for 'return' to make elements work well with 'set'.+-- | Convenience synonym for 'return' to make elements work well with 'set'. -- Also works on 'Widget's. -- -- Example usage.@@ -371,6 +371,6 @@ element :: MonadIO m => Widget w => w -> m Element element = return . getElement --- | Convience synonym for 'return' to make widgets work well with 'set'.+-- | Convenience synonym for 'return' to make widgets work well with 'set'. widget  :: Widget w => w -> UI w widget  = return
src/Graphics/UI/Threepenny/Internal.hs view
@@ -3,19 +3,19 @@     -- * Synopsis     -- | Internal core:     -- 'UI' monad, integrating FRP and JavaScript FFI. garbage collection-   +     -- * Documentation     Window, disconnect,     startGUI,-    +     UI, runUI, liftIOLater, askWindow,-    +     FFI, FromJS, ToJS, JSFunction, JSObject, ffi,     runFunction, callFunction, ffiExport, debug,-    +     Element, fromJSObject, getWindow,     mkElementNamespace, mkElement, delete, appendChild, clearChildren,-    +     EventData, domEvent, unsafeFromJSON,     ) where @@ -41,7 +41,10 @@ data Window = Window     { jsWindow    :: JS.Window  -- JavaScript window     , eDisconnect :: E.Event () -- event that happens when client disconnects-    , wEvents     :: Foreign.Vendor Events -- events associated to 'Element's+    , wEvents     :: Foreign.Vendor Events+                     -- events associated to 'Element's+    , wChildren   :: Foreign.Vendor ()+                     -- children reachable from 'Element's     }  -- | Start server for GUI sessions.@@ -55,11 +58,13 @@     JS.onDisconnect w $ handleDisconnect ()      -- make window-    wEvents <- Foreign.newVendor+    wEvents   <- Foreign.newVendor+    wChildren <- Foreign.newVendor     let window = Window             { jsWindow    = w             , eDisconnect = eDisconnect             , wEvents     = wEvents+            , wChildren   = wChildren             }      -- run initialization@@ -78,9 +83,14 @@ ------------------------------------------------------------------------------} type Events = String -> E.Event JSON.Value +-- Reachability information for children of an 'Element'.+-- The children of an element are always reachable from this RemotePtr.+type Children = Foreign.RemotePtr ()+ data Element = Element     { toJSObject  :: JS.JSObject -- corresponding JavaScript object     , elEvents    :: Events      -- FRP event mapping+    , elChildren  :: Children    -- The children of this element     , elWindow    :: Window      -- Window in which the element was created     } deriving (Typeable) @@ -90,6 +100,30 @@ getWindow :: Element -> IO Window getWindow = return . elWindow +-- | Lookup or create reachability information for the children of+-- an element that is represented by a JavaScript object.+getChildren :: JS.JSObject -> Window -> IO Children+getChildren el window@Window{ wChildren = wChildren } =+    Foreign.withRemotePtr el $ \coupon _ -> do+        mptr <- Foreign.lookup coupon wChildren+        case mptr of+            Nothing -> do+                -- Create new pointer for reachability information.+                ptr <- Foreign.newRemotePtr coupon () wChildren+                Foreign.addReachable el ptr+                return ptr+            Just p  ->+                -- Return existing information+                return p++-- | Convert JavaScript object into an Element by attaching relevant information.+-- The JavaScript object may still be subject to garbage collection.+fromJSObject0 :: JS.JSObject -> Window -> IO Element+fromJSObject0 el window = do+    events   <- getEvents   el window+    children <- getChildren el window+    return $ Element el events children window+ -- | Convert JavaScript object into an element. -- -- FIXME: For the purpose of garbage collection, this element@@ -99,8 +133,7 @@     window <- askWindow     liftIO $ do         Foreign.addReachable (JS.root $ jsWindow window) el-        events <- getEvents el window-        return $ Element el events window+        fromJSObject0 el window  -- | Add lazy FRP events to a JavaScript object. addEvents :: JS.JSObject -> Window -> IO Events@@ -122,7 +155,7 @@      return events --- | Lookup or create lazy events for an a JavaScript object.+-- | Lookup or create lazy events for a JavaScript object. getEvents :: JS.JSObject -> Window -> IO Events getEvents el window@Window{ wEvents = wEvents } = do     Foreign.withRemotePtr el $ \coupon _ -> do@@ -166,8 +199,7 @@         el <- JS.callFunction w $ case namespace of             Nothing -> ffi "document.createElement(%1)" tag             Just ns -> ffi "document.createElementNS(%1,%2)" ns tag-        events <- getEvents el window-        return $ Element el events window+        fromJSObject0 el window  -- | Delete the given element. delete :: Element -> UI ()@@ -177,21 +209,20 @@  -- | Remove all child elements. clearChildren :: Element -> UI ()-clearChildren (Element el _ _) = liftJSWindow $ \w -> do+clearChildren element = liftJSWindow $ \w -> do+    let el = toJSObject element     Foreign.withRemotePtr el $ \_ _ -> do-        -- FIXME: Not all reachable foreign pointers are actually elements!-        --        Some may also be event handlers and so on!-        --        Temporarily disable garbage collection.-        -- Foreign.clearReachable el+        -- Previous children are no longer reachable from this element         JS.runFunction w $ ffi "$(%1).contents().detach()" el+        Foreign.clearReachable (elChildren element)  -- | Append a child element. appendChild :: Element -> Element -> UI ()-appendChild (Element eParent _ _) (Element eChild _ _) = liftJSWindow $ \w -> do+appendChild parent child = liftJSWindow $ \w -> do     -- FIXME: We have to stop the child being reachable from its     -- /previous/ parent.-    Foreign.addReachable eParent eChild-    JS.runFunction w $ ffi "$(%1).append($(%2))" eParent eChild+    Foreign.addReachable (elChildren parent) (toJSObject child)+    JS.runFunction w $ ffi "$(%1).append($(%2))" (toJSObject parent) (toJSObject child)   {-----------------------------------------------------------------------------@@ -236,7 +267,7 @@     liftIO = UI . liftIO  instance MonadFix UI where-    mfix f = UI $ mfix (unUI . f)  +    mfix f = UI $ mfix (unUI . f)  -- | Execute an 'UI' action in a particular browser window. -- Also runs all scheduled 'IO' actions.
src/Reactive/Threepenny.hs view
@@ -2,23 +2,23 @@ module Reactive.Threepenny (     -- * Synopsis     -- | Functional reactive programming.-    +     -- * Types     -- $intro     Event, Behavior,-    +     -- * IO     -- | Functions to connect events to the outside world.     Handler, newEvent, register,     currentValue,-    +     -- * Core Combinators     -- | Minimal set of combinators for programming with 'Event' and 'Behavior'.     module Control.Applicative,     never, filterJust, unionWith,     accumE, apply, stepper,     -- $classes-    +     -- * Derived Combinators     -- | Additional combinators that make programming     -- with 'Event' and 'Behavior' convenient.@@ -34,10 +34,10 @@      -- * Additional Notes     -- $recursion-    +     -- * Tidings     Tidings, tidings, facts, rumors,-    +     -- * Internal     -- | Functions reserved for special circumstances.     -- Do not use unless you know what you're doing.@@ -119,10 +119,10 @@  -- | Register an event 'Handler' for an 'Event'. -- All registered handlers will be called whenever the event occurs.--- +-- -- When registering an event handler, you will also be given an action -- that unregisters this handler again.--- +-- -- > do unregisterMyHandler <- register event myHandler -- -- FIXME: Unregistering event handlers does not work yet.@@ -134,7 +134,7 @@  -- | Register an event 'Handler' for a 'Behavior'. -- All registered handlers will be called whenever the behavior changes.--- +-- -- However, note that this is only an approximation, -- as behaviors may change continuously. -- Consequently, handlers should be idempotent.@@ -164,7 +164,7 @@  -- | Return all event occurrences that are 'Just' values, discard the rest. -- Think of it as--- +-- -- > filterJust es = [(time,a) | (time,Just a) <- es] filterJust e = E $ liftMemo1 Prim.filterJustP (unE e) @@ -182,7 +182,7 @@  -- | Apply a time-varying function to a stream of events. -- Think of it as--- +-- -- > apply bf ex = [(time, bf time x) | (time, x) <- ex] apply :: Behavior (a -> b) -> Event a -> Event b apply  f x        = E $ liftMemo1 (\p -> Prim.applyP (latch f) p) (unE x)@@ -203,7 +203,7 @@ -- -- > accumB "x" [(time1,(++"y")),(time2,(++"z"))] -- >    = stepper "x" [(time1,"xy"),(time2,"xyz")]--- +-- -- Note that the value of the behavior changes \"slightly after\" -- the events occur. This allows for recursive definitions. accumB :: MonadIO m => a -> Event (a -> a) -> m (Behavior a)@@ -213,13 +213,13 @@     return $ B l1 (E $ fromPure p2)  --- | Construct a time-varying function from an initial value and +-- | Construct a time-varying function from an initial value and -- a stream of new values. Think of it as -- -- > stepper x0 ex = return $ \time -> -- >     last (x0 : [x | (timex,x) <- ex, timex < time])--- --- Note that the smaller-than-sign in the comparision @timex < time@ means +--+-- Note that the smaller-than-sign in the comparision @timex < time@ means -- that the value of the behavior changes \"slightly after\" -- the event occurrences. This allows for recursive definitions. stepper :: MonadIO m => a -> Event a -> m (Behavior a)@@ -278,7 +278,7 @@ >     b <- accumB $ (+1) <$ e2  Bad:- + > mdo >     b <- accumB $ (+1) <$ e2          -- actions executed here could depend ... >     let e2 = apply (const <$> b) e1   -- ... on this value@@ -320,7 +320,7 @@ -- | Apply a list of functions in succession. -- Useful in conjunction with 'unions'. ----- > concatenate [f,g,h] = f . g . h +-- > concatenate [f,g,h] = f . g . h concatenate :: [a -> a] -> (a -> a) concatenate = foldr (.) id @@ -380,9 +380,9 @@     (e1,fire) <- newEvent     e2 <- accumE 0 $ (+) <$> e1     _  <- register e2 print-    +     return fire-    + test_recursion1 :: IO (IO ()) test_recursion1 = mdo     (e1, fire) <- newEvent@@ -390,7 +390,7 @@         e2 = apply (const <$> b) e1     b  <- accumB 0 $ (+1) <$ e2     _  <- register e2 print-    +     return $ fire ()  
threepenny-gui.cabal view
@@ -1,5 +1,5 @@ Name:                threepenny-gui-Version:             0.6.0.3+Version:             0.6.0.4 Synopsis:            GUI framework that uses the web browser as a display. Description:     Threepenny-GUI is a GUI framework that uses the web browser as a display.@@ -81,7 +81,7 @@                     ,Graphics.UI.Threepenny.JQuery                     ,Graphics.UI.Threepenny.SVG                     ,Graphics.UI.Threepenny.SVG.Attributes-                    ,Graphics.UI.Threepenny.SVG.Elements +                    ,Graphics.UI.Threepenny.SVG.Elements                     ,Graphics.UI.Threepenny.Timer                     ,Graphics.UI.Threepenny.Widgets                     ,Reactive.Threepenny@@ -103,8 +103,8 @@   if flag(rebug)       cpp-options:  -DREBUG       ghc-options:  -O2 -threaded-  build-depends:     base                   >= 4.3   && < 4.9-                    ,aeson                  >= 0.7   && < 0.9+  build-depends:     base                   >= 4.6   && < 4.9+                    ,aeson                  >= 0.7   && < 0.11                     ,async                  == 2.0.*                     ,bytestring             >= 0.9.2 && < 0.11                     ,containers             >= 0.4.2 && < 0.6@@ -123,12 +123,12 @@                     ,websockets             >= 0.8    && < 0.10                     ,websockets-snap        >= 0.8    && < 0.10                     ,vault                  == 0.3.*-                    ,vector                 >= 0.10   && < 0.11+                    ,vector                 >= 0.10   && < 0.12   if flag(network-uri)       build-depends: network-uri            >= 2.6    && < 2.7   else       build-depends: network                >= 2.3.0  && < 2.6-                    + Executable threepenny-examples-bartab     if flag(buildExamples)         cpp-options:       -DCABAL