on 8d034f2 help sign in
35 files changed+230−619
since splitsnapshots
unifiedsplit
.github/workflows/haskell.yml−47 LICENSE−12 README.md+9−9 cabal.project+1−10 cabal.project-nogtk−14 chrome-test-utils/LICENSE+1−1 chrome-test-utils/chrome-test-utils.cabal+1−1 chrome-test-utils/src/Test/Util/UnshareNetwork.hs+2−2 dep/reflex-platform/default.nix+6−1 dep/reflex-platform/github.json+3−4 dep/reflex-platform/thunk.nix−9 reflex-dom-core/ChangeLog.md−19 reflex-dom-core/LICENSE+1−1 reflex-dom-core/reflex-dom-core.cabal+13−29 reflex-dom-core/src/Reflex/Dom/Builder/Class.hs+1−10 reflex-dom-core/src/Reflex/Dom/Builder/Immediate.hs+7−16 reflex-dom-core/src/Reflex/Dom/Builder/Static.hs+2−2 reflex-dom-core/src/Reflex/Dom/Main.hs+10−38 reflex-dom-core/src/Reflex/Dom/Prerender.hs+3−6 reflex-dom-core/src/Reflex/Dom/Widget/Input.hs+3 reflex-dom-core/src/Reflex/Dom/Widget/Lazy.hs+1−1 reflex-dom-core/src/Reflex/Dom/Xhr/Foreign.hs+2−2 reflex-dom-core/test/gc.hs+1−1 reflex-dom-core/test/hlint.hs+1−1 reflex-dom-core/test/hydration.hs+29−36 reflex-dom-test-selenium/CHANGELOG.md−5 reflex-dom-test-selenium/LICENSE−12 reflex-dom-test-selenium/Setup.hs−2 reflex-dom-test-selenium/add-overrides.nix−20 reflex-dom-test-selenium/reflex-dom-test-selenium.cabal−41 reflex-dom-test-selenium/src/Reflex/Dom/Test/Selenium.hs−249 reflex-dom/ChangeLog.md−8 reflex-dom/LICENSE+1−1 reflex-dom/reflex-dom.cabal+5−9 test/prebuild.hs+127
.github/workflows/haskell.ymldeleted−47
@@ -1,47 +0,0 @@
1−name: github-action
2−
3−on: [push, pull_request]
4−
5−jobs:
6− build:
7− strategy:
8− matrix:
9− ghc: ['8.4.4', '8.6.5', '8.8.4', '8.10.2']
10− os: ['ubuntu-latest', 'macos-latest']
11− exclude:
12− # There are some linker warnings in 802 on darwin that
13− # cause compilation to fail
14− # See https://github.com/NixOS/nixpkgs/issues/25139
15− - ghc: '8.0.2'
16− os: 'macos-latest'
17− runs-on: ${{ matrix.os }}
18−
19− name: GHC ${{ matrix.ghc }} on ${{ matrix.os }}
20− steps:
21− - uses: actions/checkout@v2
22− - uses: actions/setup-haskell@v1
23− with:
24− ghc-version: ${{ matrix.ghc }}
25− - name: Cache
26− uses: actions/cache@v1
27− env:
28− cache-name: cache-cabal
29− with:
30− path: ~/.cabal
31− key: ${{ runner.os }}-${{ matrix.ghc }}-build-${{ env.cache-name }}-${{ hashFiles('**/*.cabal') }}-${{ hashFiles('**/cabal.project') }}
32− restore-keys: |
33− ${{ runner.os }}-${{ matrix.ghc }}-build-${{ env.cache-name }}-
34− ${{ runner.os }}-${{ matrix.ghc }}-build-
35− ${{ runner.os }}-${{ matrix.ghc }}-
36− ${{ runner.os }}
37−
38− - name: Set up cabal project file to avoid webkit2gtk
39− run: cp cabal.project-nogtk cabal.project
40− - name: Install dependencies
41− run: |
42− cabal update
43− cabal build --only-dependencies --enable-tests --enable-benchmarks all
44− - name: Build
45− run: cabal build --enable-tests --enable-benchmarks all
46− - name: Run tests
47− run: cabal test all
LICENSEdeleted−12
@@ -1,12 +0,0 @@
1−Copyright (c) 2020, Obsidian Systems LLC
2−All rights reserved.
3−
4−Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5−
6−1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7−
8−2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9−
10−3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11−
12−THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
README.md+9−9
@@ -1,21 +1,21 @@
11## [Reflex-DOM](https://reflex-frp.org)
22
3−[![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/reflex-dom.svg)](https://hackage.haskell.org/package/reflex-dom) [![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/reflex-dom/badge)](https://matrix.hackage.haskell.org/#/package/reflex-dom) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/reflex-frp/reflex-dom/blob/master/LICENSE)
3+[![Hackage](https://img.shields.io/hackage/v/reflex-dom.svg)](http://hackage.haskell.org/package/reflex-dom)
44
5−Web applications without callbacks or side-effects. Reflex-DOM brings the power of [Functional Reactive Programming (FRP)](https://wiki.haskell.org/Functional_Reactive_Programming) to the web. Build [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML) and other [Document Object Model (DOM)](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) data with a pure functional interface.
5+### A Framework for Functional Reactive Web Apps in Haskell
66
7−Reflex-DOM is a framework for building web applications in [Haskell](https://www.haskell.org/), based on the [Functional Reactive Programming](https://wiki.haskell.org/Functional_Reactive_Programming) library [Reflex](https://github.com/reflex-frp/reflex).
7+Reflex-DOM is a framework for building web applications in Haskell, based on the [Functional Reactive Programming](https://wiki.haskell.org/Functional_Reactive_Programming) library [Reflex](https://github.com/reflex-frp/reflex).
8+
9+A summary of Reflex-DOM functions is available in the [quick reference](Quickref.md).
810
911**Visit https://reflex-frp.org/ for more information, tutorials, documentation and [examples](https://examples.reflex-frp.org/).**
1012
1113### Additional resources
14+[Get started with Reflex](https://github.com/reflex-frp/reflex-platform)
15+
16+[/r/reflexfrp](https://www.reddit.com/r/reflexfrp)
1217
13−* [Official Website](https://reflex-frp.org/)
14−* [Quick Reference](Quickref.md)
15−* [Obelisk](https://github.com/obsidiansystems/obelisk#obelisk): A framework built on Reflex and Reflex-DOM for functional reactive web and mobile applications, with batteries included.
16−* [Get started with Reflex](https://github.com/reflex-frp/reflex-platform)
17−* [/r/reflexfrp](https://www.reddit.com/r/reflexfrp)
18−* [irc.freenode.net #reflex-frp](http://webchat.freenode.net?channels=%23reflex-frp&uio=d4)
18+[irc.freenode.net #reflex-frp](http://webchat.freenode.net?channels=%23reflex-frp&uio=d4)
1919
2020### Hacking
2121
cabal.project+1−10
@@ -1,10 +1 @@
1−packages:
2− reflex-dom-core/
3− reflex-dom/
4− chrome-test-utils/
5− reflex-dom-test-selenium/
6−
7−source-repository-package
8− type: git
9− location: https://github.com/dfordivam/hspec-webdriver-clone
10− tag: 0d748b7bb7cd74dce0a55a1ec86b01dbb8a71cd8
1+packages: reflex-dom-core, reflex-dom
cabal.project-nogtkdeleted−14
@@ -1,14 +0,0 @@
1−packages:
2− reflex-dom-core/
3− reflex-dom/
4−
5−package reflex-dom-core
6− flags: -hydration-tests -gc-tests
7−
8−package reflex-dom
9− flags: +use-warp -webkit2gtk
10−
11−source-repository-package
12− type: git
13− location: https://github.com/dfordivam/hspec-webdriver-clone
14− tag: 0d748b7bb7cd74dce0a55a1ec86b01dbb8a71cd8
chrome-test-utils/LICENSE+1−1
@@ -1,4 +1,4 @@
1−Copyright (c) 2020, Obsidian Systems LLC
1+Copyright (c) 2019, Obsidian Systems LLC
22All rights reserved.
33
44Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
chrome-test-utils/chrome-test-utils.cabal+1−1
@@ -1,5 +1,5 @@
11Name: chrome-test-utils
2−Version: 0.5
2+Version: 0.4
33Synopsis: Utilities to write headless Chromium tests
44License: BSD3
55License-file: LICENSE
chrome-test-utils/src/Test/Util/UnshareNetwork.hs+2−2
@@ -4,8 +4,8 @@ import System.Linux.Namespaces
44import System.Posix
55import System.Process
66
7−unshareNetwork :: IO ()
8−unshareNetwork = do
7+unshareNetork :: IO ()
8+unshareNetork = do
99 uid <- getEffectiveUserID
1010 unshare [User, Network]
1111 writeUserMappings Nothing [UserMapping 0 uid 1]
dep/reflex-platform/default.nix+6−1
@@ -1,2 +1,7 @@
11# DO NOT HAND-EDIT THIS FILE
2−import (import ./thunk.nix)
2+import ((import <nixpkgs> {}).fetchFromGitHub (
3+ let json = builtins.fromJSON (builtins.readFile ./github.json);
4+ in { inherit (json) owner repo rev sha256;
5+ private = json.private or false;
6+ }
7+))
dep/reflex-platform/github.json+3−4
@@ -1,8 +1,7 @@
11{
22 "owner": "reflex-frp",
33 "repo": "reflex-platform",
4− "branch": "aa-bump-some",
5− "private": false,
6− "rev": "fd5acecb50474f795734db9fb924cc3b2fd2b508",
7− "sha256": "0wsdd67g42klsf9n3pxb3pndjdz36nzf8gp7pfm8j6nyyy2qribk"
4+ "branch": "master",
5+ "rev": "510b990d0b11f0626afbec5fe8575b5b2395391b",
6+ "sha256": "09cmahsbxr0963wq171c7j139iyzz49hramr4v9nsf684wcwkngv"
87}
dep/reflex-platform/thunk.nixdeleted−9
@@ -1,9 +0,0 @@
1−# DO NOT HAND-EDIT THIS FILE
2−let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
3− if !fetchSubmodules && !private then builtins.fetchTarball {
4− url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
5− } else (import <nixpkgs> {}).fetchFromGitHub {
6− inherit owner repo rev sha256 fetchSubmodules private;
7− };
8− json = builtins.fromJSON (builtins.readFile ./github.json);
9−in fetch json
reflex-dom-core/ChangeLog.md−19
@@ -1,24 +1,5 @@
11# Revision history for reflex-dom-core
22
3−## 0.6.2.1
4−
5−* Fix hlint complaints with newer GHC.
6−
7−## 0.6.2.0
8−
9−* ([#400](https://github.com/reflex-frp/reflex-dom/pull/400/files)) Set value of input elements in static renderer
10−
11−## 0.6.1.0
12−
13−* Bump version bounds
14−* Update for new dependent-map and dependent-sum version (after the "some" package split)
15−* Add `MonadAtomicRef` instance for `UnrunnableT`
16−* Fix ([#467](https://github.com/reflex-frp/reflex-dom/issues/467)): Prevent multiple firings of XHR response event
17−* Updates for GHC 8.10
18−* Move `HasSetValue` from Reflex.Dom.Widget.Input to Reflex.Dom.Builder.Class and add an instance for `TextAreaElementConfig`
19−* Add `now` to the `MonadHold` instance for `UnrunnableT`
20−
21−
223## 0.6.0.0
234
245* ([#375](https://github.com/reflex-frp/reflex-dom/pull/375)) **(Breaking change)** Expose resized dimensions from `resizeDetector`, `resizeDetectorWithStyle`, and `resizeDetectorWithAttrs` from `Reflex.Dom.Widget.Resize`.
reflex-dom-core/LICENSE+1−1
@@ -1,4 +1,4 @@
1−Copyright (c) 2020, Obsidian Systems LLC
1+Copyright (c) 2015, Obsidian Systems LLC
22All rights reserved.
33
44Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
reflex-dom-core/reflex-dom-core.cabal+13−29
@@ -1,12 +1,8 @@
11cabal-version: 1.24
22Name: reflex-dom-core
3−Version: 0.6.2.1
3+Version: 0.6.0.0
44Synopsis: Functional Reactive Web Apps with Reflex
55Description:
6− Web applications without callbacks or side-effects.
7− Reflex-DOM brings the power of functional reactive programming (FRP) to the web.
8− Build HTML and other Document Object Model (DOM) data with a pure functional interface.
9− .
106 Reflex-DOM is a Functional Reactive web framework based on the Reflex FRP engine: <https://reflex-frp.org/>.
117 .
128 The @reflex-dom@ package is a small wrapper around the @reflex-dom-core@ package. It pulls in the
@@ -54,32 +50,22 @@ flag split-these
5450 manual: False
5551 default: True
5652
57−flag hydration-tests
58− description: Whether to run the hydration tests (currently only available on linux)
59− default: True
60− manual: True
61−
62−flag gc-tests
63− description: Whether to run the gc tests (currently only available on linux)
64− default: True
65− manual: True
66−
6753library
6854 hs-source-dirs: src
6955 build-depends:
70− aeson >= 0.8 && < 1.6,
71− base >= 4.7 && < 4.15,
56+ aeson >= 0.8 && < 1.5,
57+ base >= 4.7 && < 4.14,
7258 bifunctors >= 4.2 && < 6,
73− bimap >= 0.3 && < 0.5,
59+ bimap >= 0.3 && < 0.4,
7460 blaze-builder >= 0.4.1 && < 0.5,
7561 bytestring == 0.10.*,
7662 case-insensitive < 1.3,
7763 containers >= 0.6 && < 0.7,
78− constraints >= 0.9 && < 0.13,
64+ constraints >= 0.9 && < 0.12,
7965 contravariant >= 1.4 && < 1.6,
8066 data-default >= 0.5 && < 0.8,
81− dependent-map >= 0.3 && < 0.5,
82− dependent-sum >= 0.6 && < 0.8,
67+ dependent-map >= 0.3 && < 0.4,
68+ dependent-sum >= 0.6 && < 0.7,
8369 dependent-sum-template >= 0.1 && < 0.2,
8470 directory >= 1.2 && < 1.4,
8571 exception-transformers == 0.4.*,
@@ -93,7 +79,7 @@ library
9379 primitive >= 0.5 && < 0.8,
9480 random >= 1.1 && < 1.2,
9581 ref-tf == 0.4.*,
96− reflex >= 0.8 && < 0.9,
82+ reflex >= 0.6.2 && < 0.8,
9783 semigroups >= 0.16 && < 0.20,
9884 stm >= 2.4 && < 2.6,
9985 text == 1.2.*,
@@ -114,7 +100,7 @@ library
114100 if flag(split-these)
115101 build-depends:
116102 semialign >= 1 && < 1.2,
117− these >= 1 && < 1.2
103+ these >= 1 && < 1.1
118104 else
119105 build-depends:
120106 these >= 0.4 && < 0.9
@@ -169,16 +155,14 @@ library
169155 if flag(use-template-haskell)
170156 build-depends:
171157 dependent-sum-template >= 0.1 && < 0.2,
172− template-haskell >= 2.12.0 && < 2.17
158+ template-haskell >= 2.12.0 && < 2.16
173159 other-extensions: TemplateHaskell
174160 cpp-options: -DUSE_TEMPLATE_HASKELL
175161 other-modules:
176162 Reflex.Dom.Builder.Class.TH
177163
178164test-suite hlint
179− build-depends:
180− base,
181− hlint >= 2.0 && < 4.0
165+ build-depends: base, hlint
182166 hs-source-dirs: test
183167 main-is: hlint.hs
184168 type: exitcode-stdio-1.0
@@ -230,7 +214,7 @@ test-suite hydration
230214 main-is: hydration.hs
231215 type: exitcode-stdio-1.0
232216 default-language: Haskell98
233− if !os(linux) || !arch(x86_64) || flag(profile-reflex) || !flag(hydration-tests)
217+ if !os(linux) || !arch(x86_64) || flag(profile-reflex)
234218 buildable: False
235219
236220-- broken test on base 4.11 & ghc 8.4.3
@@ -250,7 +234,7 @@ test-suite gc
250234 main-is: gc.hs
251235 type: exitcode-stdio-1.0
252236 default-language: Haskell98
253− if !os(linux) || !arch(x86_64) || !flag(gc-tests)
237+ if !os(linux) || !arch(x86_64)
254238 buildable: False
255239
256240source-repository head
reflex-dom-core/src/Reflex/Dom/Builder/Class.hs+1−10
@@ -9,12 +9,11 @@
99{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1010#if !MIN_VERSION_base(4,9,0)
1111{-# LANGUAGE ImpredicativeTypes #-}
12−#else
13−{-# LANGUAGE Rank2Types #-} -- Implied by ImpredicativeTypes
1412#endif
1513{-# LANGUAGE LambdaCase #-}
1614{-# LANGUAGE OverloadedStrings #-}
1715{-# LANGUAGE PolyKinds #-}
16+{-# LANGUAGE Rank2Types #-}
1817{-# LANGUAGE RecursiveDo #-}
1918{-# LANGUAGE ScopedTypeVariables #-}
2019{-# LANGUAGE StandaloneDeriving #-}
@@ -745,11 +744,3 @@ instance HasDocument m => HasDocument (DynamicWriterT t w m)
745744instance HasDocument m => HasDocument (PostBuildT t m)
746745instance HasDocument m => HasDocument (RequesterT t request response m)
747746instance HasDocument m => HasDocument (QueryT t q m)
748−
749−class HasSetValue a where
750− type SetValue a :: *
751− setValue :: Lens' a (SetValue a)
752−
753−instance Reflex t => HasSetValue (TextAreaElementConfig er t m) where
754− type SetValue (TextAreaElementConfig er t m) = Event t Text
755− setValue = textAreaElementConfig_setValue
reflex-dom-core/src/Reflex/Dom/Builder/Immediate.hs+7−16
@@ -2,6 +2,7 @@
22{-# LANGUAGE CPP #-}
33{-# LANGUAGE ConstraintKinds #-}
44{-# LANGUAGE DataKinds #-}
5+{-# LANGUAGE DeriveFunctor #-}
56{-# LANGUAGE DeriveTraversable #-}
67{-# LANGUAGE EmptyDataDecls #-}
78{-# LANGUAGE FlexibleContexts #-}
@@ -10,6 +11,7 @@
1011{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1112{-# LANGUAGE LambdaCase #-}
1213{-# LANGUAGE MultiParamTypeClasses #-}
14+{-# LANGUAGE MultiWayIf #-}
1315{-# LANGUAGE OverloadedStrings #-}
1416{-# LANGUAGE PatternGuards #-}
1517{-# LANGUAGE PolyKinds #-}
@@ -48,7 +50,6 @@ module Reflex.Dom.Builder.Immediate
4850 , HydrationMode (..)
4951 , HydrationRunnerT (..)
5052 , runHydrationRunnerT
51− , runHydrationRunnerTWithFailure
5253 , ImmediateDomBuilderT
5354 , runHydrationDomBuilderT
5455 , getHydrationMode
@@ -135,13 +136,11 @@ import Data.Functor.Compose
135136import Data.Functor.Constant
136137import Data.Functor.Misc
137138import Data.Functor.Product
138−import Data.GADT.Compare (GCompare)
139139import Data.IORef
140140import Data.IntMap.Strict (IntMap)
141141import Data.Maybe
142142import Data.Monoid ((<>))
143143import Data.Some (Some(..))
144−import Data.GADT.Compare (GCompare)
145144import Data.String (IsString)
146145import Data.Text (Text)
147146import Foreign.JavaScript.Internal.Utils
@@ -292,23 +291,15 @@ localRunner (HydrationRunnerT m) s parent = do
292291
293292{-# INLINABLE runHydrationRunnerT #-}
294293runHydrationRunnerT
295− :: (MonadRef m, Ref m ~ IORef, Monad m, PerformEvent t m, MonadFix m, MonadReflexCreateTrigger t m, MonadJSM m, MonadJSM (Performable m))
296− => HydrationRunnerT t m a -> Maybe Node -> Node -> Chan [DSum (EventTriggerRef t) TriggerInvocation] -> m a
297−runHydrationRunnerT m = runHydrationRunnerTWithFailure m (pure ())
298−
299−{-# INLINABLE runHydrationRunnerTWithFailure #-}
300−runHydrationRunnerTWithFailure
301294 :: (MonadRef m, Ref m ~ IORef, Monad m, PerformEvent t m, MonadFix m, MonadReflexCreateTrigger t m, MonadJSM m, MonadJSM (Performable m))
302295 => HydrationRunnerT t m a -> IO () -> Maybe Node -> Node -> Chan [DSum (EventTriggerRef t) TriggerInvocation] -> m a
303−runHydrationRunnerTWithFailure (HydrationRunnerT m) onFailure s parent events = flip runDomRenderHookT events $ flip runReaderT parent $ do
296+runHydrationRunnerT (HydrationRunnerT m) onFailure s parent events = flip runDomRenderHookT events $ flip runReaderT parent $ do
304297 (a, s') <- runStateT m (HydrationState s False)
305298 traverse_ removeSubsequentNodes $ _hydrationState_previousNode s'
306299 when (_hydrationState_failed s') $ liftIO $ putStrLn "reflex-dom warning: hydration failed: the DOM was not as expected at switchover time. This may be due to invalid HTML which the browser has altered upon parsing, some external JS altering the DOM, or the page being served from an outdated cache."
307300 when (_hydrationState_failed s') $ liftIO onFailure
308301 pure a
309302
310−
311−
312303instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (HydrationRunnerT t m) where
313304 {-# INLINABLE newEventWithTrigger #-}
314305 newEventWithTrigger = lift . newEventWithTrigger
@@ -1672,7 +1663,7 @@ instance (Adjustable t m, MonadJSM m, MonadHold t m, MonadFix m, PrimMonad m, Ra
16721663
16731664{-# INLINABLE traverseDMapWithKeyWithAdjust' #-}
16741665traverseDMapWithKeyWithAdjust'
1675− :: forall s t m (k :: * -> *) v v'. (Adjustable t m, MonadHold t m, MonadFix m, MonadJSM m, PrimMonad m, GCompare k, RawDocument (DomBuilderSpace (HydrationDomBuilderT s t m)) ~ Document)
1666+ :: forall s t m (k :: * -> *) v v'. (Adjustable t m, MonadHold t m, MonadFix m, MonadJSM m, PrimMonad m, DMap.GCompare k, RawDocument (DomBuilderSpace (HydrationDomBuilderT s t m)) ~ Document)
16761667 => (forall a. k a -> v a -> HydrationDomBuilderT s t m (v' a))
16771668 -> DMap k v
16781669 -> Event t (PatchDMap k v)
@@ -1792,7 +1783,7 @@ hoistTraverseWithKeyWithAdjust
17921783 ::
17931784 ( Adjustable t m
17941785 , MonadHold t m
1795− , GCompare k
1786+ , DMap.GCompare k
17961787 , MonadIO m
17971788 , MonadJSM m
17981789 , PrimMonad m
@@ -1876,14 +1867,14 @@ hoistTraverseWithKeyWithAdjust base mapPatch updateChildUnreadiness applyDomUpda
18761867 getHydrationMode >>= \case
18771868 HydrationMode_Hydrating -> addHydrationStepWithSetup (holdIncremental children0 children') $ \children -> do
18781869 dm :: DMap k (Compose (TraverseChild t m (Some k)) v') <- sample $ currentIncremental children
1879− phs <- sequenceA $ weakenDMapWith (either _traverseChildHydration_delayed (pure . _traverseChildImmediate_placeholder) . _traverseChild_mode . getCompose) dm
1870+ phs <- traverse id $ weakenDMapWith (either _traverseChildHydration_delayed (pure . _traverseChildImmediate_placeholder) . _traverseChild_mode . getCompose) dm
18801871 liftIO $ writeIORef placeholders $! phs
18811872 insertAfterPreviousNode lastPlaceholder
18821873 HydrationMode_Immediate -> do
18831874 let activate i = do
18841875 append $ toNode $ _traverseChildImmediate_fragment i
18851876 pure $ _traverseChildImmediate_placeholder i
1886− phs <- sequenceA $ weakenDMapWith (either (error "impossible") activate . _traverseChild_mode . getCompose) children0
1877+ phs <- traverse id $ weakenDMapWith (either (error "impossible") activate . _traverseChild_mode . getCompose) children0
18871878 liftIO $ writeIORef placeholders $! phs
18881879 append $ toNode lastPlaceholder
18891880 requestDomAction_ $ ffor children' $ \p -> do
reflex-dom-core/src/Reflex/Dom/Builder/Static.hs+2−2
@@ -274,7 +274,7 @@ instance SupportsStaticDomBuilder t m => DomBuilder t (StaticDomBuilderT t m) wh
274274 --TODO: Do not escape quotation marks; see https://stackoverflow.com/questions/25612166/what-characters-must-be-escaped-in-html-5
275275 shouldEscape <- asks _staticDomBuilderEnv_shouldEscape
276276 let escape = if shouldEscape then fromHtmlEscapedText else byteString . encodeUtf8
277− (modify . (:)) . (\c -> "<!--" <> c <> "-->") =<< case mSetContents of
277+ modify . (:) =<< (\c -> "<!--" <> c <> "-->") <$> case mSetContents of
278278 Nothing -> return (pure (escape initialContents))
279279 Just setContents -> hold (escape initialContents) $ fmapCheap escape setContents --Only because it doesn't get optimized when profiling is on
280280 return $ CommentNode ()
@@ -324,7 +324,7 @@ instance SupportsStaticDomBuilder t m => DomBuilder t (StaticDomBuilderT t m) wh
324324 setUpdatedChecked updatedAttrs = case _inputElementConfig_setChecked cfg of
325325 Nothing -> updatedAttrs
326326 Just e -> (Map.singleton "checked" (Just "checked") <$ e) <> updatedAttrs
327− adjustedConfig = _inputElementConfig_elementConfig cfg
327+ adjustedConfig = (_inputElementConfig_elementConfig cfg)
328328 & elementConfig_initialAttributes %~ setInitialValue . setInitialChecked
329329 & elementConfig_modifyAttributes %~ setUpdatedValue . setUpdatedChecked
330330 (e, _result) <- element "input" adjustedConfig $ return ()
reflex-dom-core/src/Reflex/Dom/Main.hs+10−38
@@ -5,6 +5,7 @@
55{-# LANGUAGE GADTs #-}
66{-# LANGUAGE MultiParamTypeClasses #-}
77{-# LANGUAGE NoMonomorphismRestriction #-}
8+{-# LANGUAGE PatternSynonyms #-}
89{-# LANGUAGE RankNTypes #-}
910{-# LANGUAGE RecursiveDo #-}
1011{-# LANGUAGE ScopedTypeVariables #-}
@@ -63,41 +64,22 @@ mainHydrationWidgetWithHead = mainHydrationWidgetWithHead'
6364{-# INLINABLE mainHydrationWidgetWithHead' #-}
6465-- | Warning: `mainHydrationWidgetWithHead'` is provided only as performance tweak. It is expected to disappear in future releases.
6566mainHydrationWidgetWithHead' :: HydrationWidget () () -> HydrationWidget () () -> JSM ()
66−mainHydrationWidgetWithHead' = mainHydrationWidgetWithSwitchoverAction' (pure ())
67+mainHydrationWidgetWithHead' = mainHydrationWidgetWithSwitchoverAction' (pure ()) (pure ())
6768
6869{-# INLINE mainHydrationWidgetWithSwitchoverAction #-}
69−mainHydrationWidgetWithSwitchoverAction :: JSM () -> (forall x. HydrationWidget x ()) -> (forall x. HydrationWidget x ()) -> JSM ()
70+mainHydrationWidgetWithSwitchoverAction :: IO () -> JSM () -> (forall x. HydrationWidget x ()) -> (forall x. HydrationWidget x ()) -> JSM ()
7071mainHydrationWidgetWithSwitchoverAction = mainHydrationWidgetWithSwitchoverAction'
7172
7273{-# INLINABLE mainHydrationWidgetWithSwitchoverAction' #-}
7374-- | Warning: `mainHydrationWidgetWithSwitchoverAction'` is provided only as performance tweak. It is expected to disappear in future releases.
74−mainHydrationWidgetWithSwitchoverAction' :: JSM () -> HydrationWidget () () -> HydrationWidget () () -> JSM ()
75−mainHydrationWidgetWithSwitchoverAction' = mainHydrationWidgetWithSwitchoverActionWithFailure' (pure ())
76−
77−
78−{-# INLINABLE mainHydrationWidgetWithSwitchoverActionWithFailure' #-}
79−-- | Warning: `mainHydrationWidgetWithSwitchoverActionWithFaiilure'` is provided only as performance tweak. It is expected to disappear in future releases.
80−mainHydrationWidgetWithSwitchoverActionWithFailure' :: IO () -> JSM () -> HydrationWidget () () -> HydrationWidget () () -> JSM ()
81−mainHydrationWidgetWithSwitchoverActionWithFailure' onFailure switchoverAction head' body = do
82− runHydrationWidgetWithHeadAndBodyWithFailure onFailure switchoverAction $ \appendHead appendBody -> do
75+mainHydrationWidgetWithSwitchoverAction' :: IO () -> JSM () -> HydrationWidget () () -> HydrationWidget () () -> JSM ()
76+mainHydrationWidgetWithSwitchoverAction' onFailure switchoverAction head' body = do
77+ runHydrationWidgetWithHeadAndBody onFailure switchoverAction $ \appendHead appendBody -> do
8378 appendHead head'
8479 appendBody body
8580
8681{-# INLINABLE attachHydrationWidget #-}
8782attachHydrationWidget
88− :: JSM ()
89− -> JSContextSingleton ()
90− -> ( Event DomTimeline ()
91− -> IORef HydrationMode
92− -> Maybe (IORef [(Node, HydrationRunnerT DomTimeline (DomCoreWidget ()) ())])
93− -> EventChannel
94− -> PerformEventT DomTimeline DomHost (a, IORef (Maybe (EventTrigger DomTimeline ())))
95− )
96− -> IO (a, FireCommand DomTimeline DomHost)
97−attachHydrationWidget = attachHydrationWidgetWithFailure (pure ())
98−
99−{-# INLINABLE attachHydrationWidgetWithFailure #-}
100−attachHydrationWidgetWithFailure
10183 :: IO ()
10284 -> JSM ()
10385 -> JSContextSingleton ()
@@ -108,7 +90,7 @@ attachHydrationWidgetWithFailure
10890 -> PerformEventT DomTimeline DomHost (a, IORef (Maybe (EventTrigger DomTimeline ())))
10991 )
11092 -> IO (a, FireCommand DomTimeline DomHost)
111−attachHydrationWidgetWithFailure onFailure switchoverAction jsSing w = do
93+attachHydrationWidget onFailure switchoverAction jsSing w = do
11294 hydrationMode <- liftIO $ newIORef HydrationMode_Hydrating
11395 rootNodesRef <- liftIO $ newIORef []
11496 events <- newChan
@@ -124,7 +106,7 @@ attachHydrationWidgetWithFailure onFailure switchoverAction jsSing w = do
124106 rootNodes <- liftIO $ readIORef rootNodesRef
125107 let delayedAction = do
126108 for_ (reverse rootNodes) $ \(rootNode, runner) -> do
127− let hydrate = runHydrationRunnerTWithFailure runner onFailure Nothing rootNode events
109+ let hydrate = runHydrationRunnerT runner onFailure Nothing rootNode events
128110 void $ runWithJSContextSingleton (runPostBuildT hydrate never) jsSing
129111 liftIO $ writeIORef hydrationMode HydrationMode_Immediate
130112 runWithJSContextSingleton (DOM.liftJSM switchoverAction) jsSing
@@ -139,16 +121,6 @@ type DomCoreWidget x = PostBuildT DomTimeline (WithJSContextSingleton x (Perform
139121
140122{-# INLINABLE runHydrationWidgetWithHeadAndBody #-}
141123runHydrationWidgetWithHeadAndBody
142− :: JSM ()
143− -> ( (forall c. HydrationWidget () c -> FloatingWidget () c) -- "Append to head" --TODO: test invoking this more than once
144− -> (forall c. HydrationWidget () c -> FloatingWidget () c) -- "Append to body" --TODO: test invoking this more than once
145− -> FloatingWidget () ()
146− )
147− -> JSM ()
148−runHydrationWidgetWithHeadAndBody = runHydrationWidgetWithHeadAndBodyWithFailure (pure ())
149−
150−{-# INLINABLE runHydrationWidgetWithHeadAndBodyWithFailure #-}
151−runHydrationWidgetWithHeadAndBodyWithFailure
152124 :: IO ()
153125 -> JSM ()
154126 -> ( (forall c. HydrationWidget () c -> FloatingWidget () c) -- "Append to head" --TODO: test invoking this more than once
@@ -156,11 +128,11 @@ runHydrationWidgetWithHeadAndBodyWithFailure
156128 -> FloatingWidget () ()
157129 )
158130 -> JSM ()
159−runHydrationWidgetWithHeadAndBodyWithFailure onFailure switchoverAction app = withJSContextSingletonMono $ \jsSing -> do
131+runHydrationWidgetWithHeadAndBody onFailure switchoverAction app = withJSContextSingletonMono $ \jsSing -> do
160132 globalDoc <- currentDocumentUnchecked
161133 headElement <- getHeadUnchecked globalDoc
162134 bodyElement <- getBodyUnchecked globalDoc
163− (events, fc) <- liftIO . attachHydrationWidgetWithFailure onFailure switchoverAction jsSing $ \switchover hydrationMode hydrationResult events -> do
135+ (events, fc) <- liftIO . attachHydrationWidget onFailure switchoverAction jsSing $ \switchover hydrationMode hydrationResult events -> do
164136 (postBuild, postBuildTriggerRef) <- newEventWithTriggerRef
165137 let hydrateDom :: DOM.Node -> HydrationWidget () c -> FloatingWidget () c
166138 hydrateDom n w = do
reflex-dom-core/src/Reflex/Dom/Prerender.hs+3−6
@@ -24,7 +24,7 @@ module Reflex.Dom.Prerender
2424
2525import Control.Monad.Primitive (PrimMonad(..))
2626import Control.Monad.Reader
27−import Control.Monad.Ref (MonadRef(..), MonadAtomicRef(..))
27+import Control.Monad.Ref (MonadRef(..))
2828import Data.IORef (IORef, newIORef)
2929import Data.Semigroup (Semigroup)
3030import Data.Text (Text)
@@ -165,8 +165,6 @@ instance Monad m => MonadRef (UnrunnableT js t m) where
165165 newRef _ = unrunnable
166166 readRef _ = unrunnable
167167 writeRef _ _ = unrunnable
168−instance Monad m => MonadAtomicRef (UnrunnableT js t m) where
169− atomicModifyRef _ _ = unrunnable
170168instance Monad m => HasDocument (UnrunnableT js t m) where
171169 askDocument = unrunnable
172170instance Monad m => HasJSContext (UnrunnableT js t m) where
@@ -205,13 +203,12 @@ instance Monad m => MonadReflexCreateTrigger t (UnrunnableT js t m) where
205203 newFanEventWithTrigger _ = unrunnable
206204instance Monad m => MonadFix (UnrunnableT js t m) where
207205 mfix _ = unrunnable
208−instance (Monad m, MonadHold t m) => MonadHold t (UnrunnableT js t m) where
206+instance Monad m => MonadHold t (UnrunnableT js t m) where
209207 hold _ _ = unrunnable
210208 holdDyn _ _ = unrunnable
211209 holdIncremental _ _ = unrunnable
212210 buildDynamic _ _ = unrunnable
213211 headE _ = unrunnable
214− now = unrunnable
215212instance Monad m => MonadSample t (UnrunnableT js t m) where
216213 sample _ = unrunnable
217214instance Monad m => MonadIO (UnrunnableT js t m) where
@@ -229,7 +226,7 @@ instance (Reflex t, Monad m) => DomRenderHook t (UnrunnableT js t m) where
229226 withRenderHook _ _ = unrunnable
230227 requestDomAction _ = unrunnable
231228 requestDomAction_ _ = unrunnable
232−instance (Reflex t, Monad m, MonadHold t m) => Prerender JS' t (UnrunnableT js t m) where
229+instance (Reflex t, Monad m) => Prerender JS' t (UnrunnableT js t m) where
233230 type Client (UnrunnableT js t m) = UnrunnableT js t m
234231 prerender _ _ = unrunnable
235232
reflex-dom-core/src/Reflex/Dom/Widget/Input.hs+3
@@ -629,6 +629,9 @@ instance HasAttributes (FileInputConfig t) where
629629 type Attrs (FileInputConfig t) = Dynamic t (Map Text Text)
630630 attributes = fileInputConfig_attributes
631631
632+class HasSetValue a where
633+ type SetValue a :: *
634+ setValue :: Lens' a (SetValue a)
632635
633636instance HasSetValue (TextAreaConfig t) where
634637 type SetValue (TextAreaConfig t) = Event t Text
reflex-dom-core/src/Reflex/Dom/Widget/Lazy.hs+1−1
@@ -117,7 +117,7 @@ virtualList heightPx rowPx maxIndex i0 setI keyToIndex items0 itemsUpdate itemBu
117117 "overflow" =: "hidden" <>
118118 "position" =: "relative"
119119 mkRow k = toStyleAttr $ "height" =: (T.pack (show rowPx) <> "px") <>
120− "top" =: (<> "px") (T.pack $ show $ keyToIndex k * rowPx) <>
120+ "top" =: ((<>"px") $ T.pack $ show $ keyToIndex k * rowPx) <>
121121 "position" =: "absolute" <>
122122 "width" =: "100%"
123123 findWindow sizeIncrement windowSize startingPosition =
reflex-dom-core/src/Reflex/Dom/Xhr/Foreign.hs+2−2
@@ -15,7 +15,7 @@ import Data.Text (Text)
1515import Data.ByteString (ByteString)
1616import Foreign.JavaScript.Utils (bsFromMutableArrayBuffer, bsToArrayBuffer)
1717import GHCJS.DOM.Enums
18−import GHCJS.DOM.EventM (EventM, on, onSync)
18+import GHCJS.DOM.EventM (EventM, on)
1919import GHCJS.DOM.EventTarget (dispatchEvent)
2020import GHCJS.DOM.Types (MonadJSM, ToJSString, FormData, Document, Blob (..), ArrayBuffer (..), JSVal, JSM, IsEvent, XMLHttpRequestProgressEvent, ProgressEvent, Event, XMLHttpRequestUpload, FromJSString, ArrayBufferView (..), liftJSM, castTo)
2121import GHCJS.DOM.XMLHttpRequest
@@ -114,7 +114,7 @@ xmlHttpRequestOntimeout :: XMLHttpRequest -> EventM XMLHttpRequest ProgressEvent
114114xmlHttpRequestOntimeout = (`on` timeout)
115115
116116xmlHttpRequestOnreadystatechange :: XMLHttpRequest -> EventM XMLHttpRequest Event () -> JSM (JSM ())
117−xmlHttpRequestOnreadystatechange = (`onSync` readyStateChange)
117+xmlHttpRequestOnreadystatechange = (`on` readyStateChange)
118118
119119xmlHttpRequestSetTimeout :: MonadJSM m => XMLHttpRequest -> Word -> m ()
120120xmlHttpRequestSetTimeout = setTimeout
reflex-dom-core/test/gc.hs+1−1
@@ -47,7 +47,7 @@ failureLimit = 0
4747
4848main :: IO ()
4949main = do
50− handle (\(_ :: IOError) -> return ()) $ unshareNetwork -- If we run into an exception with sandboxing, just don't bother
50+ handle (\(_ :: IOError) -> return ()) $ unshareNetork -- If we run into an exception with sandboxing, just don't bother
5151 withSandboxedChromeFlags True $ \chromeFlags -> do
5252 mainThread <- myThreadId
5353 browserProcess <- spawnCommand $ mconcat
reflex-dom-core/test/hlint.hs+1−1
@@ -1,4 +1,4 @@
1−import Language.Haskell.HLint (hlint)
1+import Language.Haskell.HLint3 (hlint)
22import System.Exit (exitFailure, exitSuccess)
33
44main :: IO ()
reflex-dom-core/test/hydration.hs+29−36
@@ -20,14 +20,6 @@
2020
2121{-# OPTIONS_GHC -fno-warn-orphans #-}
2222
23−-- Notice to those working on this test suite:
24−-- It doesn't appear to be possible to use --match to run a particular test, in
25−-- this situation the test may hang before reaching our code. This seems to
26−-- happen when the test is not the first test in the block. As a workaround, you
27−-- can just comment out the other tests. Also, using `xit` will cause the same
28−-- issue. `xit` tests must be the last tests in the session, or the session will
29−-- hang in the following test.
30−
3123import Prelude hiding (fail)
3224import Control.Concurrent
3325import qualified Control.Concurrent.Async as Async
@@ -145,7 +137,7 @@ deriving instance MonadFail WD
145137
146138main :: IO ()
147139main = do
148− unshareNetwork
140+ unshareNetork
149141 isHeadless <- (== Nothing) <$> lookupEnv "NO_HEADLESS"
150142 withSandboxedChromeFlags isHeadless $ \chromeFlags -> do
151143 withSeleniumServer $ \selenium -> do
@@ -154,13 +146,13 @@ main = do
154146 withDebugging <- isNothing <$> lookupEnv "NO_DEBUG"
155147 let wdConfig = WD.defaultConfig { WD.wdPort = fromIntegral $ _selenium_portNumber selenium }
156148 chromeCaps' = WD.getCaps $ chromeConfig browserPath chromeFlags
157− hspec (tests withDebugging wdConfig [(chromeCaps', "chrome")] selenium) `finally` _selenium_stopServer selenium
149+ hspec (tests withDebugging wdConfig [chromeCaps'] selenium) `finally` _selenium_stopServer selenium
158150
159−tests :: Bool -> WD.WDConfig -> [(Capabilities, String)] -> Selenium -> Spec
151+tests :: Bool -> WD.WDConfig -> [Capabilities] -> Selenium -> Spec
160152tests withDebugging wdConfig caps _selenium = do
161153 let putStrLnDebug :: MonadIO m => Text -> m ()
162154 putStrLnDebug m = when withDebugging $ liftIO $ putStrLn $ T.unpack m
163− session' t = sessionWith wdConfig t . using caps
155+ session' = sessionWith wdConfig "" . using (map (,"") caps)
164156 runWD m = runWDOptions (WdOptions False) $ do
165157 putStrLnDebug "before"
166158 r <- m
@@ -172,7 +164,7 @@ tests withDebugging wdConfig caps _selenium = do
172164 testWidget = testWidgetDebug True withDebugging
173165 testWidget' :: WD a -> (a -> WD b) -> (forall m js. TestWidget js (SpiderTimeline Global) m => m ()) -> WD b
174166 testWidget' = testWidgetDebug' True withDebugging
175− session' "text" $ do
167+ describe "text" $ session' $ do
176168 it "works" $ runWD $ do
177169 testWidgetStatic (checkBodyText "hello world") $ do
178170 text "hello world"
@@ -233,7 +225,7 @@ tests withDebugging wdConfig caps _selenium = do
233225 click <- button ""
234226 void $ textNode $ TextNodeConfig "initial" $ Just $ "after" <$ click
235227
236− session' "element" $ do
228+ describe "element" $ session' $ do
237229 it "works with domEvent Click" $ runWD $ do
238230 clickedRef <- liftIO $ newRef False
239231 testWidget' (findElemWithRetry $ WD.ByTag "div") WD.click $ do
@@ -297,8 +289,8 @@ tests withDebugging wdConfig caps _selenium = do
297289 let click = domEvent Click e
298290 return ()
299291
300− session' "inputElement" $ do
301− describe "static renderer" $ do
292+ describe "inputElement" $ do
293+ describe "static renderer" $ session' $ do
302294 it "sets value attribute" $ runWD $ do
303295 let checkStatic = do
304296 e <- findElemWithRetry $ WD.ByTag "input"
@@ -355,7 +347,7 @@ tests withDebugging wdConfig caps _selenium = do
355347 & inputElementConfig_initialChecked .~ False
356348 & inputElementConfig_setChecked .~ (True <$ pb)
357349 pure ()
358− describe "hydration" $ do
350+ describe "hydration" $ session' $ do
359351 it "doesn't wipe user input when switching over" $ runWD $ do
360352 inputRef <- newRef ("hello " :: Text)
361353 testWidget'
@@ -593,7 +585,8 @@ tests withDebugging wdConfig caps _selenium = do
593585 el "p" $ dynText $ _inputElement_value e
594586 performEvent_ $ consRef valRef <$> updated (_inputElement_value e)
595587 performEvent_ $ consRef inputRef <$> _inputElement_input e
596− describe "hydration/immediate" $ do
588+
589+ describe "hydration/immediate" $ session' $ do
597590 it "captures user input after switchover" $ runWD $ do
598591 inputRef :: IORef Text <- newRef ""
599592 let checkValue = do
@@ -673,8 +666,8 @@ tests withDebugging wdConfig caps _selenium = do
673666 names <- liftJSM $ traverse File.getName fs
674667 liftIO $ writeRef filesRef names
675668
676− session' "textAreaElement" $ do
677− describe "static renderer" $ do
669+ describe "textAreaElement" $ do
670+ describe "static renderer" $ session' $ do
678671 it "sets value attribute" $ runWD $ do
679672 let checkStatic = do
680673 e <- findElemWithRetry $ WD.ByTag "textarea"
@@ -697,7 +690,7 @@ tests withDebugging wdConfig caps _selenium = do
697690 & textAreaElementConfig_initialValue .~ "test"
698691 & textAreaElementConfig_setValue .~ ("test-updated" <$ pb)
699692 pure ()
700− describe "hydration" $ do
693+ describe "hydration" $ session' $ do
701694 it "doesn't wipe user input when switching over" $ runWD $ do
702695 inputRef <- newRef ("" :: Text)
703696 testWidget'
@@ -846,7 +839,7 @@ tests withDebugging wdConfig caps _selenium = do
846839 e <- textAreaElement $ def & textAreaElementConfig_setValue .~ ("pb" <$ pb)
847840 el "p" $ dynText $ _textAreaElement_value e
848841
849− describe "hydration/immediate" $ do
842+ describe "hydration/immediate" $ session' $ do
850843 it "captures user input after switchover" $ runWD $ do
851844 inputRef :: IORef Text <- newRef ""
852845 let checkValue = do
@@ -888,13 +881,13 @@ tests withDebugging wdConfig caps _selenium = do
888881 performEvent_ $ liftIO . writeRef valueByUIRef <$> _textAreaElement_input e
889882 performEvent_ $ liftIO . writeRef valueRef <$> updated (value e)
890883
891− session' "selectElement" $ do
884+ describe "selectElement" $ do
892885 let options :: DomBuilder t m => m ()
893886 options = do
894887 elAttr "option" ("value" =: "one" <> "id" =: "one") $ text "one"
895888 elAttr "option" ("value" =: "two" <> "id" =: "two") $ text "two"
896889 elAttr "option" ("value" =: "three" <> "id" =: "three") $ text "three"
897− describe "hydration" $ do
890+ describe "hydration" $ session' $ do
898891 it "sets initial value correctly" $ runWD $ do
899892 inputRef <- newRef ("" :: Text)
900893 let setup = do
@@ -968,7 +961,7 @@ tests withDebugging wdConfig caps _selenium = do
968961 performEvent_ $ liftIO . writeRef valueByUIRef <$> _selectElement_change e
969962 performEvent_ $ liftIO . writeRef valueRef <$> updated (_selectElement_value e)
970963
971− describe "hydration/immediate" $ do
964+ describe "hydration/immediate" $ session' $ do
972965 it "captures user input after switchover" $ runWD $ do
973966 inputRef :: IORef Text <- newRef ""
974967 let checkValue = do
@@ -1014,7 +1007,7 @@ tests withDebugging wdConfig caps _selenium = do
10141007 performEvent_ $ liftIO . writeRef valueByUIRef <$> _selectElement_change e
10151008 performEvent_ $ liftIO . writeRef valueRef <$> updated (_selectElement_value e)
10161009
1017− session' "prerender" $ do
1010+ describe "prerender" $ session' $ do
10181011 it "works in simple case" $ runWD $ do
10191012 testWidget (checkBodyText "One") (checkBodyText "Two") $ do
10201013 prerender_ (text "One") (text "Two")
@@ -1083,7 +1076,7 @@ tests withDebugging wdConfig caps _selenium = do
10831076 prerender_ (pure ()) (liftIO $ trigger "Client")
10841077 textNode $ TextNodeConfig "Initial" $ Just e
10851078
1086− session' "namespaces" $ do
1079+ describe "namespaces" $ session' $ do
10871080 it "dyn can be nested in namespaced widget" $ runWD $ do
10881081 testWidget (pure ()) (checkTextInTag "svg" "one") $ do
10891082 let svgRootCfg = def
@@ -1092,7 +1085,7 @@ tests withDebugging wdConfig caps _selenium = do
10921085 void $ element "svg" svgRootCfg $ do
10931086 dyn_ $ text "one" <$ pure ()
10941087
1095− session' "runWithReplace" $ do
1088+ describe "runWithReplace" $ session' $ do
10961089 it "works" $ runWD $ do
10971090 replaceChan :: Chan Text <- liftIO newChan
10981091 let setup = findElemWithRetry $ WD.ByTag "div"
@@ -1290,7 +1283,7 @@ tests withDebugging wdConfig caps _selenium = do
12901283 _ <- runWithReplace (text "inner1") $ el "p" (text "inner2") <$ replace
12911284 text "|after"
12921285
1293− session' "traverseDMapWithKeyWithAdjust" $ do
1286+ describe "traverseDMapWithKeyWithAdjust" $ session' $ do
12941287 let widget :: DomBuilder t m => DKey a -> Identity a -> m (Identity a)
12951288 widget k (Identity v) = elAttr "li" ("id" =: textKey k) $ do
12961289 elClass "span" "key" $ text $ textKey k
@@ -1393,7 +1386,7 @@ tests withDebugging wdConfig caps _selenium = do
13931386 (dmap, _evt) <- traverseDMapWithKeyWithAdjust widget keyMap $ leftmost [postBuildPatch <$ pb, replace]
13941387 liftIO $ dmap `H.shouldBe` keyMap
13951388
1396− session' "traverseIntMapWithKeyWithAdjust" $ do
1389+ describe "traverseIntMapWithKeyWithAdjust" $ session' $ do
13971390 let textKeyInt k = "key" <> T.pack (show k)
13981391 intMap = IntMap.fromList
13991392 [ (1, "one")
@@ -1500,7 +1493,7 @@ tests withDebugging wdConfig caps _selenium = do
15001493 (dmap, _evt) <- traverseIntMapWithKeyWithAdjust widget intMap $ leftmost [postBuildPatch <$ pb, replace]
15011494 liftIO $ dmap `H.shouldBe` intMap
15021495
1503− session' "traverseDMapWithKeyWithAdjustWithMove" $ do
1496+ describe "traverseDMapWithKeyWithAdjustWithMove" $ session' $ do
15041497 let widget :: DomBuilder t m => Key2 a -> Identity a -> m (Identity a)
15051498 widget k (Identity v) = elAttr "li" ("id" =: textKey2 k) $ do
15061499 elClass "span" "key" $ text $ textKey2 k
@@ -1580,8 +1573,8 @@ tests withDebugging wdConfig caps _selenium = do
15801573 (dmap, _evt) <- traverseDMapWithKeyWithAdjustWithMove widget initMap =<< triggerEventWithChan chan
15811574 liftIO $ assertEqual "DMap" initMap dmap
15821575
1583− session' "hydrating invalid HTML" $ do
1584− xit "can hydrate list in paragraph" $ runWD $ do
1576+ describe "hydrating invalid HTML" $ session' $ do
1577+ it "can hydrate list in paragraph" $ runWD $ do
15851578 let preSwitchover = do
15861579 checkBodyText "before\ninner\nafter"
15871580 -- Two <p> tags should be present
@@ -1610,7 +1603,7 @@ tests withDebugging wdConfig caps _selenium = do
16101603 -- TODO: This test presupposes the exact set of labels that "dropdown" places in the "value" fields to distinguish options.
16111604 -- This dependence on internal implementation details is undesirable in a test case, but seems fairly tricky to avoid.
16121605 -- It seems expedient for the time being to expect this test case to be updated, should those implementation details ever change.
1613− session' "dropdown" $ do
1606+ describe "dropdown" $ session' $ do
16141607 let doTest expectedOpts (initialValue :: Text) = do
16151608 let doCheck = do
16161609 es <- findElemsWithRetry $ WD.ByTag "option"
@@ -1767,7 +1760,7 @@ testWidgetDebug' hardFailure withDebugging beforeJS afterSwitchover bodyWidget =
17671760 ((), html) <- liftIO $ renderStatic $ runHydratableT staticApp
17681761 putStrLnDebug "rendered static"
17691762 waitBeforeJS <- liftIO newEmptyMVar -- Empty until JS should be run
1770− onFailure <- if hardFailure then (`throwTo` HydrationFailedException) <$> liftIO myThreadId else pure $ pure ()
1763+ onFailure <- if hardFailure then (\tid -> throwTo tid HydrationFailedException) <$> liftIO myThreadId else pure $ pure ()
17711764 waitUntilSwitchover <- liftIO newEmptyMVar -- Empty until switchover
17721765 let entryPoint = do
17731766 putStrLnDebug "taking waitBeforeJS"
@@ -1779,7 +1772,7 @@ testWidgetDebug' hardFailure withDebugging beforeJS afterSwitchover bodyWidget =
17791772 liftIO $ putMVar waitUntilSwitchover ()
17801773 putStrLnDebug "put waitUntilSwitchover"
17811774 putStrLnDebug "running mainHydrationWidgetWithSwitchoverAction"
1782− mainHydrationWidgetWithSwitchoverActionWithFailure' onFailure switchOverAction blank bodyWidget
1775+ mainHydrationWidgetWithSwitchoverAction onFailure switchOverAction blank bodyWidget
17831776 putStrLnDebug "syncPoint after mainHydrationWidgetWithSwitchoverAction"
17841777 syncPoint
17851778 application <- liftIO $ jsaddleOr defaultConnectionOptions entryPoint $ \_ sendResponse -> do
reflex-dom-test-selenium/CHANGELOG.mddeleted−5
@@ -1,5 +0,0 @@
1−# Revision history for reflex-dom-core-selenium
2−
3−## 0.1.0.0 -- YYYY-mm-dd
4−
5−* First version. Released on an unsuspecting world.
reflex-dom-test-selenium/LICENSEdeleted−12
@@ -1,12 +0,0 @@
1−Copyright (c) 2020, Obsidian Systems LLC
2−All rights reserved.
3−
4−Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5−
6−1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7−
8−2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9−
10−3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11−
12−THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
reflex-dom-test-selenium/Setup.hsdeleted−2
@@ -1,2 +0,0 @@
1−import Distribution.Simple
2−main = defaultMain
reflex-dom-test-selenium/add-overrides.nixdeleted−20
@@ -1,20 +0,0 @@
1−{ nixpkgs }: testPackage:
2− nixpkgs.haskell.lib.overrideCabal testPackage
3− (drv: {
4−
5− # The headless browser run as part of the tests will exit without this
6− preBuild = ''
7− export HOME="$PWD"
8− '';
9−
10− testSystemDepends = with nixpkgs; (drv.testSystemDepends or []) ++ [
11− selenium-server-standalone which
12− chromium
13− nixpkgs.iproute
14− ];
15−
16− # The headless browser run as part of gc tests would hang/crash without this
17− preCheck = ''
18− export FONTCONFIG_PATH=${nixpkgs.fontconfig.out}/etc/fonts
19− '';
20− })
reflex-dom-test-selenium/reflex-dom-test-selenium.cabaldeleted−41
@@ -1,41 +0,0 @@
1−cabal-version: 1.24
2−Name: reflex-dom-test-selenium
3−Version: 0.0.0.1
4−Synopsis: Testing framework for selenium tests
5−Description:
6−License: BSD3
7−License-file: LICENSE
8−Author: Ryan Trinkle
9−Maintainer: ryan.trinkle@gmail.com
10−Stability: Experimental
11−Category: FRP, Web, GUI, HTML, Javascript, Reactive, Reactivity, User Interfaces, User-interface
12−Build-type: Simple
13−
14−library
15− hs-source-dirs: src
16− build-depends:
17− async,
18− base >= 4.7 && < 4.15,
19− bytestring == 0.10.*,
20− chrome-test-utils,
21− exceptions,
22− hspec-core,
23− hspec-webdriver >= 1.2.1,
24− http-types,
25− jsaddle >= 0.9.0.0 && < 0.10,
26− jsaddle-warp,
27− network,
28− process,
29− reflex-dom-core,
30− silently,
31− text == 1.2.*,
32− wai,
33− warp,
34− webdriver,
35− websockets
36−
37− exposed-modules:
38− Reflex.Dom.Test.Selenium
39−
40− default-language: Haskell98
41− ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -O2 -ferror-spans -fspecialise-aggressively
reflex-dom-test-selenium/src/Reflex/Dom/Test/Selenium.hsdeleted−249
@@ -1,249 +0,0 @@
1−{-# LANGUAGE ConstraintKinds #-}
2−{-# LANGUAGE FlexibleContexts #-}
3−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4−{-# LANGUAGE OverloadedStrings #-}
5−{-# LANGUAGE RankNTypes #-}
6−{-# LANGUAGE ScopedTypeVariables #-}
7−{-# LANGUAGE StandaloneDeriving #-}
8−{-# LANGUAGE TemplateHaskell #-}
9−
10−{-# OPTIONS_GHC -fno-warn-orphans #-}
11−
12−-- | Utilities for testing reflex-dom widgets with Selenium.
13−--
14−-- Any uses of the 'testWidget' functions will start a jsaddle warp server and
15−-- serve the given widget in an otherwise empty page. Webdriver commands can run
16−-- on the statically rendered page, and on the hydrated page.
17−module Reflex.Dom.Test.Selenium
18− ( TestWidget
19− , TestWidgetConfig (..)
20− , testWidget, testWidget', testWidgetStatic, testWidgetHydrated
21− , withSeleniumSpec
22− , embedSpec
23− , SeleniumSetupConfig (..)
24− ) where
25−
26−import Control.Concurrent (threadDelay, newEmptyMVar, takeMVar, putMVar)
27−import Control.Exception (throwIO)
28−import Control.Monad (when)
29−import Control.Monad.Catch (MonadMask, handle)
30−import Control.Monad.Fix (MonadFix)
31−import Control.Monad.IO.Class (MonadIO, liftIO)
32−import Data.Text (Text)
33−import Language.Javascript.JSaddle
34−import Language.Javascript.JSaddle.Warp
35−import Network.HTTP.Types (status200)
36−import Network.Socket (PortNumber)
37−import Network.Wai (responseLBS)
38−import Network.WebSockets (defaultConnectionOptions)
39−import Reflex.Dom.Core
40−import System.IO (stderr)
41−import System.IO.Silently (hSilence)
42−import System.Process (std_in, std_out, std_err, createProcess, proc, StdStream (..), terminateProcess)
43−import Test.Hspec.WebDriver (Spec, SpecWith, WdTestSession, sessionWith, using)
44−import Test.Util.ChromeFlags
45−import Test.Util.UnshareNetwork
46−import Test.WebDriver (WD)
47−
48−import qualified Control.Concurrent.Async as Async
49−import qualified Data.ByteString.Lazy as LBS
50−import qualified Data.Text as T
51−import qualified Data.Text.Encoding as TE
52−import qualified Network.Wai.Handler.Warp as Warp
53−import qualified Test.Hspec.Core.Spec as Hspec
54−import qualified Test.WebDriver as WD
55−import qualified Test.WebDriver.Capabilities as WD
56−
57−deriving instance MonadMask WD
58−
59−data SeleniumSetupConfig = SeleniumSetupConfig
60− { _seleniumSetupConfig_chromiumPath :: FilePath
61− -- ^ Path to the chromium executable
62− , _seleniumSetupConfig_headless :: Bool
63− -- ^ True means that the browser is invoked in headless mode, False means that
64− -- the user can see the interaction happening on the browser (useful for debugging).
65− , _seleniumSetupConfig_seleniumPort :: PortNumber
66− -- ^ The port number used by selenium
67− }
68−
69−-- | Setup a selenium server and use it to run some hspec tests.
70−--
71−-- withSeleniumSpec config $ \runSession -> hspec $ do
72−-- describe "tests using webdriver session" $ runSession $ do
73−-- webdriver tests here
74−withSeleniumSpec :: SeleniumSetupConfig -> ((forall multi. SpecWith (WdTestSession multi) -> Spec) -> IO a) -> IO a
75−withSeleniumSpec config runSpec = do
76− liftIO $ handle (\(_ :: IOError) -> return ()) $ unshareNetork -- If we run into an exception with sandboxing, just don't bother
77− withSandboxedChromeFlags (_seleniumSetupConfig_headless config) $ \chromeFlags -> do
78− withSeleniumServer (_seleniumSetupConfig_seleniumPort config) $ do
79− let browserPath = T.strip $ T.pack $ _seleniumSetupConfig_chromiumPath config
80− when (T.null browserPath) $ fail "No browser found"
81− let wdConfig = WD.defaultConfig { WD.wdPort = fromIntegral $ _seleniumSetupConfig_seleniumPort config }
82− chromeCaps' = WD.getCaps $ chromeConfig browserPath chromeFlags
83− runSpec $ sessionWith wdConfig "" . using [(chromeCaps', "chrome")]
84−
85−startSeleniumServer :: PortNumber -> IO (IO ())
86−startSeleniumServer port = do
87− (_,_,_,ph) <- createProcess $ (proc "selenium-server" ["-port", show port])
88− { std_in = NoStream
89− , std_out = NoStream
90− , std_err = NoStream
91− }
92− return $ terminateProcess ph
93−
94−withSeleniumServer :: PortNumber -> IO a -> IO a
95−withSeleniumServer port f = bracket (startSeleniumServer port) id $ \_ -> do
96− threadDelay $ 1000 * 1000 * 2 -- TODO poll or wait on a a signal to block on
97− f
98−
99−chromeConfig :: Text -> [Text] -> WD.WDConfig
100−chromeConfig fp flags =
101− WD.useBrowser
102− (WD.chrome { WD.chromeBinary = Just $ T.unpack fp, WD.chromeOptions = T.unpack <$> flags })
103− WD.defaultConfig
104−
105−--------------------------------------------------------------------------------
106−-- Function to test widgets
107−--------------------------------------------------------------------------------
108−
109−-- | The environment in which your widgets can be tested
110−type TestWidget js t m =
111− (DomBuilder t m, MonadHold t m, PostBuild t m
112− , Prerender js t m, PerformEvent t m, TriggerEvent t m
113− , MonadFix m, MonadIO (Performable m), MonadIO m)
114−
115−-- | Configuration of individual tests
116−data TestWidgetConfig = TestWidgetConfig
117− { _testWidgetConfig_debug :: Bool
118− -- ^ If this flag is set to True, during the test we will emit debug messages
119− , _testWidgetConfig_headWidget :: (forall m js. TestWidget js (SpiderTimeline Global) m => m ())
120− -- ^ We can add widgets here that will be included in the head of the page
121− -- (useful for example to include external js libraries in the tests)
122− , _testWidgetConfig_jsaddlePort :: PortNumber
123− -- ^ Port used by the jsaddle server
124− }
125−
126−-- | Test a widget by running some webdriver commands before and after
127−-- hydration.
128−testWidget
129− :: TestWidgetConfig
130− -> WD a
131− -- ^ Webdriver commands to run before the JS runs (i.e. on the statically rendered page)
132− -> WD b
133− -- ^ Webdriver commands to run after hydration switchover
134− -> (forall m js. TestWidget js (SpiderTimeline Global) m => m ())
135− -- ^ Widget we are testing (contents of body)
136− -> WD b
137−testWidget cfg before after widget = testWidget' cfg before (const after) widget
138−
139−-- | Test a widget by running some webdriver commands before hydration (on the
140−-- statically rendered page).
141−testWidgetStatic
142− :: TestWidgetConfig
143− -> WD a
144− -- ^ Webdriver commands to run before the JS runs (i.e. on the statically rendered page)
145− -> (forall m js. TestWidget js (SpiderTimeline Global) m => m ())
146− -- ^ Widget we are testing (contents of body)
147− -> WD a
148−testWidgetStatic cfg before widget = testWidget' cfg before pure widget
149−
150−-- | Test a widget by running some webdriver commands after hydration.
151−testWidgetHydrated
152− :: TestWidgetConfig
153− -> WD b
154− -- ^ Webdriver commands to run after hydration switchover
155− -> (forall m js. TestWidget js (SpiderTimeline Global) m => m ())
156− -- ^ Widget we are testing (contents of body)
157− -> WD b
158−testWidgetHydrated cfg after widget = testWidget' cfg (pure ()) (const after) widget
159−
160−-- | Test a widget by running some webdriver commands before and after
161−-- hydration. Like 'testWidget', but you can use the result of the webdriver
162−-- commands from before hydration in the post hydration test.
163−testWidget'
164− :: TestWidgetConfig
165− -> WD a
166− -- ^ Webdriver commands to run before the JS runs (i.e. on the statically rendered page)
167− -> (a -> WD b)
168− -- ^ Webdriver commands to run after hydration switchover
169− -> (forall m js. TestWidget js (SpiderTimeline Global) m => m ())
170− -- ^ Widget we are testing (contents of body)
171− -> WD b
172−testWidget' (TestWidgetConfig withDebugging headWidget jsaddlePort) beforeJS afterSwitchover bodyWidget = do
173− let putStrLnDebug :: MonadIO m => Text -> m ()
174− putStrLnDebug m = when withDebugging $ liftIO $ putStrLn $ T.unpack m
175− staticApp = do
176− el "head" $ headWidget
177− el "body" $ do
178− bodyWidget
179− el "script" $ text $ TE.decodeUtf8 $ LBS.toStrict $ jsaddleJs False
180− putStrLnDebug "rendering static"
181− ((), html) <- liftIO $ renderStatic $ runHydratableT staticApp
182− putStrLnDebug "rendered static"
183− waitBeforeJS <- liftIO newEmptyMVar -- Empty until JS should be run
184− waitUntilSwitchover <- liftIO newEmptyMVar -- Empty until switchover
185− let entryPoint = do
186− putStrLnDebug "taking waitBeforeJS"
187− liftIO $ takeMVar waitBeforeJS
188− let switchOverAction = do
189− putStrLnDebug "switchover syncPoint"
190− syncPoint
191− putStrLnDebug "putting waitUntilSwitchover"
192− liftIO $ putMVar waitUntilSwitchover ()
193− putStrLnDebug "put waitUntilSwitchover"
194− putStrLnDebug "running mainHydrationWidgetWithSwitchoverAction"
195− mainHydrationWidgetWithSwitchoverAction switchOverAction blank bodyWidget
196− putStrLnDebug "syncPoint after mainHydrationWidgetWithSwitchoverAction"
197− syncPoint
198− application <- liftIO $ jsaddleOr defaultConnectionOptions entryPoint $ \_ sendResponse -> do
199− putStrLnDebug "sending response"
200− r <- sendResponse $ responseLBS status200 [] $ "<!doctype html>\n" <> LBS.fromStrict html
201− putStrLnDebug "sent response"
202− return r
203− waitJSaddle <- liftIO newEmptyMVar
204− let settings = foldr ($) Warp.defaultSettings
205− [ Warp.setPort $ fromIntegral $ toInteger jsaddlePort
206− , Warp.setBeforeMainLoop $ do
207− putStrLnDebug "putting waitJSaddle"
208− putMVar waitJSaddle ()
209− putStrLnDebug "put waitJSaddle"
210− ]
211− -- hSilence to get rid of ConnectionClosed logs
212− silenceIfNotDebugging = if withDebugging then id else hSilence [stderr]
213− jsaddleWarp = silenceIfNotDebugging $ Warp.runSettings settings application
214− withAsync' jsaddleWarp $ do
215− putStrLnDebug "taking waitJSaddle"
216− liftIO $ takeMVar waitJSaddle
217− putStrLnDebug "opening page"
218− WD.openPage $ "http://localhost:" <> show jsaddlePort
219− putStrLnDebug "running beforeJS"
220− a <- beforeJS
221− putStrLnDebug "putting waitBeforeJS"
222− liftIO $ putMVar waitBeforeJS ()
223− putStrLnDebug "taking waitUntilSwitchover"
224− liftIO $ takeMVar waitUntilSwitchover
225− putStrLnDebug "running afterSwitchover"
226− afterSwitchover a
227−
228−--------------------------------------------------------------------------------
229−-- Utilities
230−--------------------------------------------------------------------------------
231−
232−-- | Embed a different spec type by evaluating it directly.
233−embedSpec :: (Hspec.Example a, MonadIO m) => Hspec.Arg a -> a -> m ()
234−embedSpec arg spec = liftIO $ do
235− Hspec.Result _info status <- Hspec.evaluateExample
236− spec
237− Hspec.defaultParams
238− (\actionWith -> actionWith arg)
239− (\_ -> pure ())
240− case status of
241− Hspec.Success -> pure ()
242− Hspec.Pending _ _ -> pure () -- should not happen
243− failure -> throwIO failure
244−
245−withAsync' :: (MonadIO m, MonadMask m) => IO a -> m b -> m b
246−withAsync' f g = bracket
247− (liftIO $ Async.async f)
248− (liftIO . Async.uninterruptibleCancel)
249− (const g)
reflex-dom/ChangeLog.md−8
@@ -1,13 +1,5 @@
11# Revision history for reflex-dom
22
3−## 0.6.1.0-r1
4−
5−* Loosen reflex-dom-core version bounds
6−
7−## 0.6.1.0
8−
9−* Update for new dependent-map and dependent-sum (after the "some" package split)
10−
113## 0.6.0.0
124
135* ([#379](https://github.com/reflex-frp/reflex-dom/pull/379)) Re-export all modules from `reflex-dom-core`. The newly re-exported modules are:
reflex-dom/LICENSE+1−1
@@ -1,4 +1,4 @@
1−Copyright (c) 2020, Obsidian Systems LLC
1+Copyright (c) 2015, Obsidian Systems LLC
22All rights reserved.
33
44Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
reflex-dom/reflex-dom.cabal+5−9
@@ -1,12 +1,8 @@
11cabal-version: 1.24
22Name: reflex-dom
3−Version: 0.6.1.0
3+Version: 0.6.0.0
44Synopsis: Functional Reactive Web Apps with Reflex
55Description:
6− Web applications without callbacks or side-effects.
7− Reflex-DOM brings the power of functional reactive programming (FRP) to the web.
8− Build HTML and other Document Object Model (DOM) data with a pure functional interface.
9− .
106 Reflex-DOM is a Functional Reactive web framework based on the Reflex FRP engine: <https://reflex-frp.org/>.
117 .
128 The @reflex-dom@ package is a small wrapper around the @reflex-dom-core@ package. It pulls in the
@@ -61,7 +57,7 @@ library
6157 hs-source-dirs: src-android
6258 other-modules: Reflex.Dom.Android.MainWidget
6359 build-depends:
64− aeson >= 1.4 && < 1.6,
60+ aeson >= 1.4 && < 1.5,
6561 android-activity == 0.1.*,
6662 data-default == 0.7.*,
6763 jsaddle >= 0.9.6 && < 0.10
@@ -71,10 +67,10 @@ library
7167 cpp-options: -DANDROID
7268 build-tools: hsc2hs
7369 build-depends:
74− base >= 4.7 && < 4.15,
70+ base >= 4.7 && < 4.14,
7571 bytestring == 0.10.*,
76− reflex >= 0.8 && < 0.9,
77− reflex-dom-core >= 0.6.1.0 && <0.7,
72+ reflex >= 0.6.2 && < 0.8,
73+ reflex-dom-core == 0.6.0.0,
7874 text == 1.2.*
7975 if !impl(ghcjs)
8076 if flag(use-warp) && (os(linux) || os(osx))
test/prebuild.hsnew file+127
@@ -0,0 +1,127 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE ScopedTypeVariables #-}
4+{-# LANGUAGE TypeFamilies #-}
5+{-# LANGUAGE LambdaCase #-}
6+{-# LANGUAGE FlexibleInstances #-}
7+{-# LANGUAGE MultiParamTypeClasses #-}
8+import Control.Monad
9+import Control.Monad.Identity
10+import Control.Monad.Trans
11+import Reflex.Dom
12+import qualified Data.Text as T
13+import Control.Concurrent
14+
15+import Control.Monad.State.Strict
16+import Data.Functor.Misc
17+import Data.Monoid
18+import Data.Word
19+import qualified Data.Map as Map
20+import qualified Data.Dependent.Map as DMap
21+import Data.Dependent.Sum
22+import qualified Reflex.Patch.DMapWithMove as PatchDMapWithMove
23+
24+main :: IO ()
25+main = mainWidget w
26+
27+w :: forall t m. (MonadWidget t m, DomRenderHook t m, MountableDomBuilder t m) => m ()
28+w = do
29+ let slow :: forall m'. (MonadWidget t m', DomRenderHook t m') => m' ()
30+ {-
31+ performEventChain = do
32+ postBuild <- delay 0 =<< getPostBuild
33+ rec let maxN = 10000
34+ n = leftmost [0 <$ postBuild, ffilter (<=maxN) $ succ <$> n']
35+ n' <- performEvent $ return <$> n
36+ pausedUntil $ ffilter (==maxN) n'
37+ _ <- widgetHold (text "Starting") $ text . T.pack . show <$> n
38+ return ()
39+ -}
40+-- {- Many dyns
41+ slow = elAttr "div" ("style" =: "position:relative;width:256px;height:256px") $ go maxDepth
42+ where maxDepth = 6 :: Int
43+ go 0 = blank
44+ go n = void $ dyn $ pure $ do
45+ let bgcolor = "rgba(0,0,0," <> T.pack (show (1 - (fromIntegral n / fromIntegral maxDepth) :: Double)) <> ")"
46+ s pos = pos <> ";position:absolute;border:1px solid white;background-color:" <> bgcolor
47+ elAttr "div" ("style" =: s "left:0;right:50%;top:0;bottom:50%") $ go $ pred n
48+ elAttr "div" ("style" =: s "left:50%;right:0;top:0;bottom:50%") $ go $ pred n
49+ elAttr "div" ("style" =: s "left:50%;right:0;top:50%;bottom:0") $ go $ pred n
50+ elAttr "div" ("style" =: s "left:0;right:50%;top:50%;bottom:0") $ go $ pred n
51+-- -}
52+ {- Many elDynAttrs
53+ slow = do
54+ let size = 64
55+ replicateM_ size $ elAttr "div" ("style" =: ("height:4px;width:" <> T.pack (show (size*4)) <> "px;line-height:0;background-color:gray")) $ do
56+ replicateM_ size $ elDynAttr "div" (pure $ "style" =: "display:inline-block;width:4px;height:4px;background-color:black") blank
57+ -}
58+ {- Many dynTexts
59+ slow = el "table" $ do
60+ let size = 64
61+ replicateM_ size $ el "tr" $ do
62+ replicateM_ size $ el "td" $ do
63+ dynText $ pure "."
64+ -}
65+ {- Many simultaneous performEvents
66+ slow = do
67+ postBuild <- getPostBuild
68+ replicateM_ ((2 :: Int) ^ (14 :: Int)) $ performEvent_ $ return () <$ postBuild
69+ done <- performEvent $ return () <$ postBuild
70+ _ <- widgetHold (text "Doing performEvent") $ text "Done" <$ done
71+ return ()
72+ -}
73+ {-
74+ slow = do
75+ postBuild <- getPostBuild
76+ postBuild' <- performEvent . (return () <$) =<< performEvent . (return () <$) =<< getPostBuild
77+ let f x = Map.fromList [(n, x) | n <- [1 :: Int .. 4096]]
78+ listHoldWithKey (f False) (f (Just True) <$ postBuild') $ \k -> \case
79+ False -> do
80+ text "X "
81+ notReadyUntil =<< getPostBuild
82+ True -> do
83+ text ". "
84+ return ()
85+ -}
86+ {-
87+ slow = do
88+ let f :: forall a. EitherTag () () a -> Const2 () () a -> m' (Const2 () () a)
89+ f _ (Const2 ()) = do
90+ notReadyUntil =<< delay 0.5 =<< getPostBuild
91+ text "Done"
92+ return $ Const2 ()
93+ postBuild <- getPostBuild
94+ traverseDMapWithKeyWithAdjustWithMove f (DMap.singleton LeftTag $ Const2 ()) $ (PatchDMapWithMove.moveDMapKey LeftTag RightTag) <$ postBuild
95+ return ()
96+ -}
97+ {-
98+ slow = do
99+ let h x = do
100+ liftIO $ putStrLn "render hook"
101+ result <- x
102+ liftIO $ putStrLn "render hook done"
103+ return result
104+ f :: forall a. Const2 () () a -> Identity a -> m' (Identity a)
105+ f (Const2 ()) (Identity ()) = do
106+ liftIO $ putStrLn "f"
107+ widgetHold notReady . (blank <$) =<< delay 0.1 =<< getPostBuild
108+ liftIO $ putStrLn "f done"
109+ return $ Identity ()
110+ withRenderHook h $ do
111+ postBuild <- getPostBuild
112+ _ <- traverseDMapWithKeyWithAdjust f mempty $ PatchDMap (DMap.singleton (Const2 () :: Const2 () () ()) (ComposeMaybe $ Just $ Identity ())) <$ postBuild
113+ return ()
114+ -}
115+ el "div" $ do
116+ draw <- button "Draw"
117+ widgetHold blank $ ffor draw $ \_ -> do
118+ _ <- untilReady (text "Loading...") slow
119+ return ()
120+ return ()
121+
122+#ifdef EXPERIMENTAL_DEPENDENT_SUM_INSTANCES
123+instance {-# INCOHERENT #-} (Show (f a), Show (f b)) => ShowTag (EitherTag a b) f where
124+ showTagToShow e _ = case e of
125+ LeftTag -> id
126+ RightTag -> id
127+#endif