on develop help sign in
Merge remote-tracking branch 'origin/develop' into aa-base-4.12

* origin/develop: (25 commits) Reindent Fix overriding mkDerivation Revert "reflex-dom-core: Allow superfluous nix arguments" reflex-dom-core: Allow superfluous nix arguments hydration: Use staticWhich to find chromium Update ChangeLog.md Update ChangeLog.md Loosen constraints version bounds. Simplify the Nix Make version number in nix and cabal match Bump reflex-platform for tests Move data-ssr from static builder to HydratableT Replace Android cabal flag with OS selector which works since nixpkgs 19.03 Test more in release.nix Remove unused files for hydra Revert "Remove a leftover "data-ssr" attribute" Update changelog Skip hydration for elements with data-ssr attribute Fixes for ghc 8.6 Update CONTRIBUTING.md ...

commitde9ac2d421b5c7ece50bca7afdce9107b2f8de51 authorAli Abrar <aliabrar@gmail.com> dateThu 14 Nov 2019, 11:17 (7 years ago) parent8214a675dca688
23 files changed+282−253
CONTRIBUTING.md+5 default.nix+51−5 dep/reflex-platform/default.nix+7 dep/reflex-platform/github.json+7 hydra.json−29 jobsets.nix−70 reflex-dom-core/ChangeLog.md+8−2 reflex-dom-core/default.nix−64 reflex-dom-core/reflex-dom-core.cabal+5−3 reflex-dom-core/src/Reflex/Dom/Builder/Hydratable.hs+116 reflex-dom-core/src/Reflex/Dom/Builder/Immediate.hs+12−5 reflex-dom-core/src/Reflex/Dom/Builder/InputDisabled.hs+6 reflex-dom-core/src/Reflex/Dom/Builder/Static.hs+1−1 reflex-dom-core/src/Reflex/Dom/Core.hs+1 reflex-dom-core/src/Reflex/Dom/Prerender.hs+7−2 reflex-dom-core/src/Reflex/Dom/Widget/Basic.hs+5−4 reflex-dom-core/src/Reflex/Dom/Widget/Resize.hs+4 reflex-dom-core/test/hlint.hs+1 reflex-dom-core/test/hydration.hs+11−5 reflex-dom/default.nix−38 reflex-dom/reflex-dom.cabal+3−8 reflex-platform.nix−8 release.nix+32−9
CONTRIBUTING.md+5
@@ -5,6 +5,7 @@ Contributions and issue reports are encouraged and appreciated!
55- [Opening Issues](#opening-issues)
66- [Submitting Changes](#submitting-changes)
77 - [Guidelines for Commit Messages](#guidelines-for-commit-messages)
8+ - [Guidelines for Pull Requests](#guidelines-for-pull-requests)
89 - [Code Quality](#code-quality)
910 - [Documentation](#documentation)
1011
@@ -30,6 +31,10 @@ One way to think about it is that your commit message should be able to complete
3031#### Body
3132For breaking changes, new features, refactors, or other major changes, the body of the commit message should describe the motivation behind the change in greater detail and may include references to the issue tracker. The body shouldn't repeat code/comments from the diff.
3233
34+### Guidelines for Pull Requests
35+
36+Wherever possible, pull requests should add a single feature or fix a single bug. Pull requests should not bundle several unrelated changes.
37+
3338### Code Quality
3439
3540#### Warnings
default.nix+51−5
@@ -1,7 +1,53 @@
1−haskellPackages: nixpkgs: {
2− reflex-dom = haskellPackages.callPackage ./reflex-dom {};
3− reflex-dom-core = haskellPackages.callPackage ./reflex-dom-core {
4− inherit (nixpkgs) iproute chromium;
5− };
1+haskellPackages: let
2+ pkgs = haskellPackages.callPackage ({ pkgs }: pkgs) {};
3+ inherit (pkgs) stdenv;
4+ haskellLib = pkgs.haskell.lib;
5+in {
6+ reflex-dom-core = let
7+ inherit (haskellPackages) ghc;
8+ noGcTest = stdenv.hostPlatform.system != "x86_64-linux"
9+ || stdenv.hostPlatform != stdenv.buildPlatform
10+ || (ghc.isGhcjs or false);
11+ in haskellLib.overrideCabal
12+ (haskellPackages.callCabal2nix "reflex-dom-core" ./reflex-dom-core { })
13+ (drv: {
14+ #TODO: Get hlint working for cross-compilation
15+ doCheck = stdenv.hostPlatform == stdenv.buildPlatform && !(ghc.isGhcjs or false);
16+
17+ # The headless browser run as part of the tests will exit without this
18+ preBuild = ''
19+ export HOME="$PWD"
20+ '';
21+
22+ # Show some output while running tests, so we might notice what's wrong
23+ testTarget = "--show-details=streaming";
24+
25+ testHaskellDepends = with haskellPackages; (drv.testHaskellDepends or []) ++ stdenv.lib.optionals (!noGcTest) [
26+ temporary
27+ jsaddle-warp
28+ process
29+ chrome-test-utils
30+ ];
31+
32+ testSystemDepends = with pkgs; (drv.testSystemDepends or []) ++ [
33+ selenium-server-standalone which
34+ ] ++ stdenv.lib.optionals (!noGcTest) [
35+ chromium
36+ pkgs.iproute
37+ ];
38+ } // stdenv.lib.optionalAttrs (!noGcTest) {
39+ # The headless browser run as part of gc tests would hang/crash without this
40+ preCheck = ''
41+ export FONTCONFIG_PATH=${pkgs.fontconfig.out}/etc/fonts
42+ '';
43+ });
44+ reflex-dom = haskellLib.overrideCabal
45+ (haskellPackages.callCabal2nix "reflex-dom" ./reflex-dom { })
46+ (drv: {
47+ # Hack until https://github.com/NixOS/cabal2nix/pull/432 lands
48+ libraryHaskellDepends = (drv.libraryHaskellDepends or []) ++ stdenv.lib.optionals (with stdenv.hostPlatform; isAndroid && is32bit) [
49+ haskellPackages.android-activity
50+ ];
51+ });
652 chrome-test-utils = haskellPackages.callCabal2nix "chrome-test-utils" ./chrome-test-utils {};
753}
dep/reflex-platform/default.nixnew file+7
@@ -0,0 +1,7 @@
1+# DO NOT HAND-EDIT THIS FILE
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.jsonnew file+7
@@ -0,0 +1,7 @@
1+{
2+ "owner": "reflex-frp",
3+ "repo": "reflex-platform",
4+ "branch": "develop",
5+ "rev": "338fc907e37d70e6469c529456f33221fb05ca1f",
6+ "sha256": "08gfhpp0pkvvi1wnlpcn6wmpzdjvy5z7dy1h66gp2w8b5cx8hx5h"
7+}
hydra.jsondeleted−29
@@ -1,29 +0,0 @@
1−{
2− "enabled": 1,
3− "hidden": true,
4− "description": "Jobsets",
5− "nixexprinput": "src",
6− "nixexprpath": "jobsets.nix",
7− "checkinterval": 300,
8− "schedulingshares": 100,
9− "enableemail": false,
10− "emailoverride": "",
11− "keepnr": 10,
12− "inputs": {
13− "src": {
14− "type": "git",
15− "value": "https://github.com/reflex-frp/reflex-dom.git develop",
16− "emailresponsible": false
17− },
18− "nixpkgs": {
19− "type": "git",
20− "value": "https://github.com/NixOS/nixpkgs-channels nixos-unstable",
21− "emailresponsible": false
22− },
23− "prs": {
24− "type": "githubpulls",
25− "value": "reflex-frp reflex-dom",
26− "emailresponsible": false
27− }
28− }
29−}
jobsets.nixdeleted−70
@@ -1,70 +0,0 @@
1−{ prs }:
2−
3−let
4− pkgs = (import ./reflex-platform.nix {}).nixpkgs;
5− mkFetchGithub = value: {
6− inherit value;
7− type = "git";
8− emailresponsible = false;
9− };
10−in
11−with pkgs.lib;
12−let
13− defaults = jobs: {
14− inherit (jobs) description;
15− enabled = 1;
16− hidden = false;
17− keepnr = 10;
18− schedulingshares = 100;
19− checkinterval = 120;
20− enableemail = false;
21− emailoverride = "";
22− nixexprinput = "reflex-dom";
23− nixexprpath = "release.nix";
24− inputs = jobs.inputs // {
25− nixpkgs = {
26− type = "git";
27− value = "https://github.com/NixOS/nixpkgs-channels nixos-unstable";
28− emailresponsible = false;
29− };
30− config = {
31− type = "nix";
32− value = "{ android_sdk.accept_license = true; }";
33− emailresponsible = false;
34− };
35− };
36− };
37− branchJobset = branch: defaults {
38− description = "reflex-dom-${branch}";
39− inputs = {
40− reflex-dom = {
41− value = "https://github.com/reflex-frp/reflex-dom ${branch}";
42− type = "git";
43− emailresponsible = false;
44− };
45− };
46− };
47− makePr = num: info: {
48− name = "reflex-dom-pr-${num}";
49− value = defaults {
50− description = "#${num}: ${info.title}";
51− inputs = {
52− reflex-dom = {
53− #NOTE: This should really use "pull/${num}/merge"; however, GitHub's
54− #status checks only operate on PR heads. This creates a race
55− #condition, which can currently only be solved by requiring PRs to be
56− #up to date before they're merged. See
57− #https://github.com/isaacs/github/issues/1002
58− value = "https://github.com/reflex-frp/reflex-dom pull/${num}/head";
59− type = "git";
60− emailresponsible = false;
61− };
62− };
63− };
64− };
65− processedPrs = mapAttrs' makePr (builtins.fromJSON (builtins.readFile prs));
66− jobsetsAttrs = processedPrs //
67− genAttrs ["develop"] branchJobset;
68−in {
69− jobsets = pkgs.writeText "spec.json" (builtins.toJSON jobsetsAttrs);
70−}
reflex-dom-core/ChangeLog.md+8−2
@@ -1,15 +1,21 @@
11# Revision history for reflex-dom-core
22
3+## Unreleased
4+
35## 0.5.2
46
57* Update to use new dependent-sum/map packages and drop dependency on `*Tag` classes (e.g., `ShowTag`).
68* Update version bounds of base, containers, and stm
7−* Update to use split these/semialign packages
9+* Update to use the newly split `these`/`semialign` packages. To use the pre-split `these` package, set the `split-these` flag to false.
10+* Reintroduce "data-ssr": elements without this attribute are skipped during
11+ hydration.
12+* Fix an issue in the hydration tests that prevented the test from finding the chromium executable
13+* Relax constraints on `dyn` and `widgetHold` to match the ones in `networkView` and `networkHold` respectively
814
915## 0.5.1
1016
1117* Added support for marking elements with a "data-skip-hydration" attribute, which will cause hydration to ignore and skip over them.
12−* Removed "data-ssr" attributes from statically rendered output.:q
18+* Removed "data-ssr" attributes from statically rendered output.
1319
1420## 0.5
1521
reflex-dom-core/default.nixdeleted−64
@@ -1,64 +0,0 @@
1−{ mkDerivation, aeson, base, bifunctors, bimap, blaze-builder
2−, bytestring, chrome-test-utils, constraints, constraints-extras, containers
3−, contravariant, data-default, dependent-map, dependent-sum
4−, dependent-sum-template, directory, exception-transformers
5−, exceptions, filepath, ghcjs-dom, hlint, hspec, hspec-webdriver, http-types, HUnit
6−, jsaddle, jsaddle-warp, keycode, lens, lifted-base
7−, monad-control, mtl, network, network-uri, primitive, process
8−, random, ref-tf, reflex, semigroups, silently, stdenv, stm
9−, template-haskell, temporary, text, these, transformers, unix, wai
10−, wai-websockets, warp, webdriver, websockets, zenc
11−, ghc, iproute, chromium, hashable, selenium-server-standalone, which, fontconfig
12−, semialign ? null
13−, splitThese ? (semialign != null)
14−}:
15−let addGcTestDepends = drv: if (stdenv.system != "x86_64-linux" || stdenv.hostPlatform != stdenv.buildPlatform || (ghc.isGhcjs or false)) then drv else drv // {
16− # The headless browser run as part of gc tests would hang/crash without this
17− preCheck = ''
18− export FONTCONFIG_PATH=${fontconfig.out}/etc/fonts
19− '';
20− testHaskellDepends = (drv.testHaskellDepends or []) ++ [
21− temporary
22− jsaddle-warp
23− process
24− chrome-test-utils
25− ];
26− testSystemDepends = (drv.testSystemDepends or []) ++ [ chromium iproute ];
27− };
28−in mkDerivation (addGcTestDepends {
29− pname = "reflex-dom-core";
30− version = "0.5.2";
31− src = ./.;
32− libraryHaskellDepends = [
33− aeson base bifunctors bimap blaze-builder bytestring constraints
34− containers contravariant data-default dependent-map dependent-sum
35− dependent-sum-template directory exception-transformers ghcjs-dom
36− jsaddle keycode lens monad-control mtl network-uri primitive random
37− ref-tf reflex semigroups stm template-haskell text these
38− transformers unix zenc
39− ] ++ (if ghc.isGhcjs or false then [ hashable ] else [])
40− ++ (if splitThese then [ semialign ] else []);
41−
42− #TODO: Get hlint working for cross-compilation
43− doCheck = stdenv.hostPlatform == stdenv.buildPlatform && !(ghc.isGhcjs or false);
44−
45− # The headless browser run as part of the tests will exit without this
46− preBuild = ''
47− export HOME="$PWD"
48− '';
49−
50− # Show some output while running tests, so we might notice what's wrong
51− testTarget = "--show-details=streaming";
52−
53− testSystemDepends = [ selenium-server-standalone which ];
54− testHaskellDepends = [
55− aeson base bytestring constraints constraints-extras containers
56− dependent-map dependent-sum dependent-sum-template directory
57− exceptions filepath ghcjs-dom hlint hspec hspec-webdriver http-types HUnit jsaddle
58− jsaddle-warp lens lifted-base network process random reflex
59− silently temporary text unix wai wai-websockets warp webdriver
60− websockets
61− ];
62− description = "Functional Reactive Web Apps with Reflex";
63− license = stdenv.lib.licenses.bsd3;
64−})
reflex-dom-core/reflex-dom-core.cabal+5−3
@@ -53,8 +53,8 @@ library
5353 bimap >= 0.3 && < 0.4,
5454 blaze-builder,
5555 bytestring == 0.10.*,
56− containers == 0.6.*,
57− constraints >= 0.9 && < 0.11,
56+ containers >= 0.6 && < 0.7,
57+ constraints >= 0.9 && < 0.12,
5858 contravariant >= 1.4 && < 1.6,
5959 data-default >= 0.5 && < 0.8,
6060 dependent-map >= 0.3 && < 0.4,
@@ -74,7 +74,7 @@ library
7474 ref-tf == 0.4.*,
7575 reflex >= 0.6.2,
7676 semigroups >= 0.16 && < 0.19,
77− stm == 2.5.*,
77+ stm >= 2.4 && < 2.6,
7878 text == 1.2.*,
7979 transformers >= 0.3 && < 0.6,
8080 network-uri >= 2.6.1 && < 2.7,
@@ -106,6 +106,7 @@ library
106106 Reflex.Dom.Builder.Class.Events
107107 Reflex.Dom.Builder.Immediate
108108 Reflex.Dom.Builder.InputDisabled
109+ Reflex.Dom.Builder.Hydratable
109110 Reflex.Dom.Builder.Static
110111 Reflex.Dom.Class
111112 Reflex.Dom.Core
@@ -200,6 +201,7 @@ test-suite hydration
200201 , warp
201202 , webdriver
202203 , websockets
204+ , which
203205 hs-source-dirs: test
204206 ghc-options: -rtsopts -with-rtsopts=-T -Wall -fwarn-tabs -funbox-strict-fields -O2 -ferror-spans
205207 ghc-prof-options: -fprof-auto -optP-DPROFILING
reflex-dom-core/src/Reflex/Dom/Builder/Hydratable.hsnew file+116
@@ -0,0 +1,116 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE FlexibleInstances #-}
3+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4+{-# LANGUAGE MultiParamTypeClasses #-}
5+{-# LANGUAGE OverloadedStrings #-}
6+{-# LANGUAGE StandaloneDeriving #-}
7+{-# LANGUAGE TypeFamilies #-}
8+{-# LANGUAGE UndecidableInstances #-}
9+module Reflex.Dom.Builder.Hydratable where
10+
11+import Control.Monad.Fix
12+import Control.Monad.Primitive
13+import Control.Monad.Ref
14+import Control.Monad.Trans
15+import Control.Monad.Trans.Control
16+import Data.Coerce
17+import qualified Data.Map as Map
18+import Foreign.JavaScript.TH
19+#ifndef ghcjs_HOST_OS
20+import GHCJS.DOM.Types (MonadJSM (..))
21+#endif
22+import Reflex
23+import Reflex.Dom.Builder.Class
24+import Reflex.Dom.Builder.Immediate (HasDocument (..))
25+import Reflex.Host.Class
26+
27+-- | A DomBuilder transformer that adds "data-ssr" to all elements such that the
28+-- hydration builder knows which bits of DOM were added by us, and which were
29+-- added by external scripts.
30+newtype HydratableT m a = HydratableT { runHydratableT :: m a } deriving (Functor, Applicative, Monad, MonadAtomicRef, MonadFix, MonadIO)
31+
32+#ifndef ghcjs_HOST_OS
33+instance MonadJSM m => MonadJSM (HydratableT m) where
34+ liftJSM' = HydratableT . liftJSM'
35+#endif
36+
37+deriving instance MonadSample t m => MonadSample t (HydratableT m)
38+deriving instance MonadHold t m => MonadHold t (HydratableT m)
39+
40+instance MonadTrans HydratableT where
41+ lift = HydratableT
42+
43+instance MonadTransControl HydratableT where
44+ type StT HydratableT a = a
45+ liftWith f = HydratableT $ f runHydratableT
46+ restoreT = HydratableT
47+
48+instance MonadRef m => MonadRef (HydratableT m) where
49+ type Ref (HydratableT m) = Ref m
50+ newRef = lift . newRef
51+ readRef = lift . readRef
52+ writeRef ref = lift . writeRef ref
53+
54+instance PerformEvent t m => PerformEvent t (HydratableT m) where
55+ type Performable (HydratableT m) = Performable m
56+ performEvent_ = lift . performEvent_
57+ performEvent = lift . performEvent
58+
59+instance PrimMonad m => PrimMonad (HydratableT m) where
60+ type PrimState (HydratableT m) = PrimState m
61+ primitive = lift . primitive
62+
63+makeHydratable :: Reflex t => ElementConfig er t m -> ElementConfig er t m
64+makeHydratable cfg = cfg
65+ { _elementConfig_initialAttributes = Map.insert "data-ssr" "" $ _elementConfig_initialAttributes cfg
66+ , _elementConfig_modifyAttributes = fmap (Map.delete "data-ssr") <$> _elementConfig_modifyAttributes cfg
67+ }
68+
69+instance PostBuild t m => PostBuild t (HydratableT m) where
70+ getPostBuild = lift getPostBuild
71+
72+deriving instance TriggerEvent t m => TriggerEvent t (HydratableT m)
73+
74+instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (HydratableT m) where
75+ newEventWithTrigger = lift . newEventWithTrigger
76+ newFanEventWithTrigger f = lift $ newFanEventWithTrigger f
77+
78+instance Adjustable t m => Adjustable t (HydratableT m) where
79+ runWithReplace a0 a' = HydratableT $ runWithReplace (coerce a0) (coerceEvent a')
80+ traverseDMapWithKeyWithAdjust f dm0 dm' = HydratableT $ traverseDMapWithKeyWithAdjust (\k v -> runHydratableT $ f k v) (coerce dm0) (coerceEvent dm')
81+ traverseDMapWithKeyWithAdjustWithMove f dm0 dm' = HydratableT $ traverseDMapWithKeyWithAdjustWithMove (\k v -> runHydratableT $ f k v) (coerce dm0) (coerceEvent dm')
82+ traverseIntMapWithKeyWithAdjust f m0 m' = HydratableT $ traverseIntMapWithKeyWithAdjust (\k v -> runHydratableT $ f k v) (coerce m0) (coerceEvent m')
83+
84+instance NotReady t m => NotReady t (HydratableT m) where
85+ notReadyUntil = lift . notReadyUntil
86+ notReady = lift notReady
87+
88+instance DomBuilder t m => DomBuilder t (HydratableT m) where
89+ type DomBuilderSpace (HydratableT m) = DomBuilderSpace m
90+ element t cfg = lift . element t (makeHydratable cfg) . runHydratableT
91+ inputElement cfg = lift $ inputElement $ cfg
92+ { _inputElementConfig_elementConfig = makeHydratable $ _inputElementConfig_elementConfig cfg
93+ }
94+ textAreaElement cfg = lift $ textAreaElement $ cfg
95+ { _textAreaElementConfig_elementConfig = makeHydratable $ _textAreaElementConfig_elementConfig cfg
96+ }
97+ selectElement cfg child = do
98+ let cfg' = cfg
99+ { _selectElementConfig_elementConfig = makeHydratable $ _selectElementConfig_elementConfig cfg
100+ }
101+ lift $ selectElement cfg' $ runHydratableT child
102+
103+instance HasDocument m => HasDocument (HydratableT m)
104+
105+instance HasJSContext m => HasJSContext (HydratableT m) where
106+ type JSContextPhantom (HydratableT m) = JSContextPhantom m
107+ askJSContext = lift askJSContext
108+
109+instance HasJS js m => HasJS js (HydratableT m) where
110+ type JSX (HydratableT m) = JSX m
111+ liftJS = lift . liftJS
112+
113+instance DomRenderHook t m => DomRenderHook t (HydratableT m) where
114+ withRenderHook f = HydratableT . withRenderHook f . runHydratableT
115+ requestDomAction = HydratableT . requestDomAction
116+ requestDomAction_ = HydratableT . requestDomAction_
reflex-dom-core/src/Reflex/Dom/Builder/Immediate.hs+12−5
@@ -765,10 +765,17 @@ hydrateElement elementTag cfg child = do
765765 result <- HydrationDomBuilderT $ lift $ runReaderT (unHydrationDomBuilderT child) env'
766766 wrapResult <- liftIO newEmptyMVar
767767 let skipAttr = "data-hydration-skip" :: DOM.JSString
768− hasSkipAttribute :: DOM.Element -> HydrationRunnerT t m Bool
769− hasSkipAttribute e = case cfg ^. namespace of
770− Nothing -> hasAttribute e skipAttr
771− Just ns -> hasAttributeNS e (Just ns) skipAttr
768+ ssrAttr = "data-ssr" :: DOM.JSString
769+ shouldSkip :: DOM.Element -> HydrationRunnerT t m Bool
770+ shouldSkip e = case cfg ^. namespace of
771+ Nothing -> do
772+ skip <- hasAttribute e skipAttr
773+ ssr <- hasAttribute e ssrAttr
774+ pure $ skip || not ssr
775+ Just ns -> do
776+ skip <- hasAttributeNS e (Just ns) skipAttr
777+ ssr <- hasAttributeNS e (Just ns) ssrAttr
778+ pure $ skip || not ssr
772779 childDom <- liftIO $ readIORef childDelayedRef
773780 let rawCfg = extractRawElementConfig cfg
774781 doc <- askDocument
@@ -783,7 +790,7 @@ hydrateElement elementTag cfg child = do
783790 pure e
784791 Just node -> DOM.castTo DOM.Element node >>= \case
785792 Nothing -> go (Just node) -- this node is not an element, skip
786− Just e -> hasSkipAttribute e >>= \case
793+ Just e -> shouldSkip e >>= \case
787794 True -> go (Just node) -- this element is explicitly marked for being skipped by hydration
788795 False -> do
789796 t <- Element.getTagName e
reflex-dom-core/src/Reflex/Dom/Builder/InputDisabled.hs+6
@@ -80,6 +80,7 @@ instance Adjustable t m => Adjustable t (InputDisabledT m) where
8080 runWithReplace a0 a' = InputDisabledT $ runWithReplace (coerce a0) (coerceEvent a')
8181 traverseDMapWithKeyWithAdjust f dm0 dm' = InputDisabledT $ traverseDMapWithKeyWithAdjust (\k v -> runInputDisabledT $ f k v) (coerce dm0) (coerceEvent dm')
8282 traverseDMapWithKeyWithAdjustWithMove f dm0 dm' = InputDisabledT $ traverseDMapWithKeyWithAdjustWithMove (\k v -> runInputDisabledT $ f k v) (coerce dm0) (coerceEvent dm')
83+ traverseIntMapWithKeyWithAdjust f m0 m' = InputDisabledT $ traverseIntMapWithKeyWithAdjust (\k v -> runInputDisabledT $ f k v) (coerce m0) (coerceEvent m')
8384
8485instance NotReady t m => NotReady t (InputDisabledT m) where
8586 notReadyUntil = lift . notReadyUntil
@@ -108,3 +109,8 @@ instance HasJSContext m => HasJSContext (InputDisabledT m) where
108109instance HasJS js m => HasJS js (InputDisabledT m) where
109110 type JSX (InputDisabledT m) = JSX m
110111 liftJS = lift . liftJS
112+
113+instance DomRenderHook t m => DomRenderHook t (InputDisabledT m) where
114+ withRenderHook f = InputDisabledT . withRenderHook f . runInputDisabledT
115+ requestDomAction = InputDisabledT . requestDomAction
116+ requestDomAction_ = InputDisabledT . requestDomAction_
reflex-dom-core/src/Reflex/Dom/Builder/Static.hs+1−1
@@ -288,7 +288,7 @@ instance SupportsStaticDomBuilder t m => DomBuilder t (StaticDomBuilderT t m) wh
288288 StaticDomBuilderT $ do
289289 let shouldEscape = elementTag `Set.notMember` noEscapeElements
290290 (result, innerHtml) <- lift $ lift $ runStaticDomBuilderT child $ StaticDomBuilderEnv shouldEscape Nothing
291− attrs0 <- foldDyn applyMap (Map.insert "data-ssr" "" $ cfg ^. initialAttributes) (cfg ^. modifyAttributes)
291+ attrs0 <- foldDyn applyMap (cfg ^. initialAttributes) (cfg ^. modifyAttributes)
292292 selectValue <- asks _staticDomBuilderEnv_selectValue
293293 let addSelectedAttr attrs sel = case Map.lookup "value" attrs of
294294 Just v | v == sel -> attrs <> Map.singleton "selected" ""
reflex-dom-core/src/Reflex/Dom/Core.hs+1
@@ -6,6 +6,7 @@ module Reflex.Dom.Core (module X) where
66
77import Reflex as X hiding (askEvents)
88import Reflex.Dom.Builder.Class as X
9+import Reflex.Dom.Builder.Hydratable as X
910import Reflex.Dom.Builder.Immediate as X
1011import Reflex.Dom.Builder.InputDisabled as X
1112import Reflex.Dom.Builder.Static as X
reflex-dom-core/src/Reflex/Dom/Prerender.hs+7−2
@@ -33,6 +33,7 @@ import Foreign.JavaScript.TH
3333import GHCJS.DOM.Types (MonadJSM)
3434import Reflex hiding (askEvents)
3535import Reflex.Dom.Builder.Class
36+import Reflex.Dom.Builder.Hydratable
3637import Reflex.Dom.Builder.Immediate
3738import Reflex.Dom.Builder.InputDisabled
3839import Reflex.Dom.Builder.Static
@@ -283,8 +284,12 @@ instance (Prerender js t m, Monad m, Reflex t, MonadFix m, Group q, Additive q,
283284 pure a
284285
285286instance (Prerender js t m, Monad m) => Prerender js t (InputDisabledT m) where
286− type Client (InputDisabledT m) = Client m
287− prerender (InputDisabledT server) client = InputDisabledT $ prerender server client
287+ type Client (InputDisabledT m) = InputDisabledT (Client m)
288+ prerender (InputDisabledT server) (InputDisabledT client) = InputDisabledT $ prerender server client
289+
290+instance (Prerender js t m, Monad m) => Prerender js t (HydratableT m) where
291+ type Client (HydratableT m) = HydratableT (Client m)
292+ prerender (HydratableT server) (HydratableT client) = HydratableT $ prerender server client
288293
289294instance (Prerender js t m, Monad m, ReflexHost t) => Prerender js t (PostBuildT t m) where
290295 type Client (PostBuildT t m) = PostBuildT t (Client m)
reflex-dom-core/src/Reflex/Dom/Widget/Basic.hs+5−4
@@ -60,6 +60,7 @@ module Reflex.Dom.Widget.Basic
6060 , partitionMapBySetLT
6161 ) where
6262
63+import Reflex.Adjustable.Class
6364import Reflex.Class
6465import Reflex.Collection
6566import Reflex.Dom.Builder.Class
@@ -146,21 +147,21 @@ button t = do
146147-- | Given a Dynamic of widget-creating actions, create a widget that is recreated whenever the Dynamic updates.
147148-- The returned Event of widget results occurs when the Dynamic does.
148149-- Note: Often, the type @a@ is an 'Event', in which case the return value is an Event-of-Events that would typically be flattened (via 'switchHold').
149−dyn :: (DomBuilder t m, PostBuild t m) => Dynamic t (m a) -> m (Event t a)
150+dyn :: (Adjustable t m, NotReady t m, PostBuild t m) => Dynamic t (m a) -> m (Event t a)
150151dyn = networkView
151152
152153-- | Like 'dyn' but discards result.
153−dyn_ :: (DomBuilder t m, PostBuild t m) => Dynamic t (m a) -> m ()
154+dyn_ :: (Adjustable t m, NotReady t m, PostBuild t m) => Dynamic t (m a) -> m ()
154155dyn_ = void . dyn
155156
156157-- | Given an initial widget and an Event of widget-creating actions, create a widget that is recreated whenever the Event fires.
157158-- The returned Dynamic of widget results occurs when the Event does.
158159-- Note: Often, the type 'a' is an Event, in which case the return value is a Dynamic-of-Events that would typically be flattened (via 'switchDyn').
159−widgetHold :: (DomBuilder t m, MonadHold t m) => m a -> Event t (m a) -> m (Dynamic t a)
160+widgetHold :: (Adjustable t m, MonadHold t m) => m a -> Event t (m a) -> m (Dynamic t a)
160161widgetHold = networkHold
161162
162163-- | Like 'widgetHold' but discards result.
163−widgetHold_ :: (DomBuilder t m, MonadHold t m) => m a -> Event t (m a) -> m ()
164+widgetHold_ :: (Adjustable t m, MonadHold t m) => m a -> Event t (m a) -> m ()
164165widgetHold_ z = void . widgetHold z
165166
166167-- | Create a DOM element
reflex-dom-core/src/Reflex/Dom/Widget/Resize.hs+4
@@ -33,6 +33,10 @@ import qualified GHCJS.DOM.Types as DOM
3333
3434-- | A widget that wraps the given widget in a div and fires an event when resized.
3535-- Adapted from @github.com\/marcj\/css-element-queries@
36+--
37+-- This function can cause strange scrollbars to appear in some circumstances.
38+-- These can be hidden with pseudo selectors, for example, in webkit browsers:
39+-- .wrapper *::-webkit-scrollbar { width: 0px; background: transparent; }
3640resizeDetector :: (MonadJSM m, DomBuilder t m, PostBuild t m, TriggerEvent t m, PerformEvent t m, MonadHold t m, DomBuilderSpace m ~ GhcjsDomSpace, MonadJSM (Performable m), MonadFix m) => m a -> m (Event t (), a)
3741resizeDetector = resizeDetectorWithStyle ""
3842
reflex-dom-core/test/hlint.hs+1
@@ -20,6 +20,7 @@ main = do
2020 , "--ignore=Unnecessary hiding" -- Interferes with cross-version compatibility
2121 , "--ignore=Use <$>"
2222 , "--ignore=Reduce duplication" --TODO: Re-enable this test
23+ , "--ignore=Use list comprehension"
2324 , "--cpp-define=USE_TEMPLATE_HASKELL"
2425 ]
2526 if null ideas then exitSuccess else exitFailure
reflex-dom-core/test/hydration.hs+11−5
@@ -54,6 +54,7 @@ import System.IO (stderr)
5454import System.IO.Silently
5555import System.IO.Temp
5656import System.Process
57+import System.Which (staticWhich)
5758import qualified Test.HUnit as HUnit (assertEqual, assertFailure)
5859import qualified Test.Hspec as H
5960import qualified Test.Hspec.Core.Spec as H
@@ -77,6 +78,9 @@ import qualified Test.WebDriver.Capabilities as WD
7778import Test.Util.ChromeFlags
7879import Test.Util.UnshareNetwork
7980
81+chromium :: FilePath
82+chromium = $(staticWhich "chromium")
83+
8084seleniumPort, jsaddlePort :: PortNumber
8185seleniumPort = 8000
8286jsaddlePort = 8001
@@ -128,7 +132,7 @@ main = do
128132 isHeadless <- (== Nothing) <$> lookupEnv "NO_HEADLESS"
129133 withSandboxedChromeFlags isHeadless $ \chromeFlags -> do
130134 withSeleniumServer $ \selenium -> do
131− browserPath <- liftIO $ T.strip . T.pack <$> readProcess "which" [ "chromium" ] ""
135+ let browserPath = T.strip $ T.pack chromium
132136 when (T.null browserPath) $ fail "No browser found"
133137 withDebugging <- isNothing <$> lookupEnv "NO_DEBUG"
134138 let wdConfig = WD.defaultConfig { WD.wdPort = fromIntegral $ _selenium_portNumber selenium }
@@ -1205,7 +1209,9 @@ tests withDebugging wdConfig caps _selenium = do
12051209 let preSwitchover = do
12061210 checkBodyText "before\ninner\nafter"
12071211 -- Two <p> tags should be present
1208− [p1, p2] <- WD.findElems (WD.ByTag "p")
1212+ (p1, p2) <- WD.findElems (WD.ByTag "p") >>= \case
1213+ [p1, p2] -> pure (p1, p2)
1214+ _ -> error "Unexpected number of `p` tags (expected 2)"
12091215 ol <- findElemWithRetry (WD.ByTag "ol")
12101216 shouldContainText "before" p1
12111217 shouldContainText "inner" ol
@@ -1349,9 +1355,9 @@ testWidgetDebug' withDebugging beforeJS afterSwitchover bodyWidget = do
13491355 el "body" $ do
13501356 bodyWidget
13511357 el "script" $ text $ TE.decodeUtf8 $ LBS.toStrict $ jsaddleJs False
1352− putStrLnDebug "rendering preSwitchover"
1353− ((), html) <- liftIO $ renderStatic staticApp
1354− putStrLnDebug "rendered preSwitchover"
1358+ putStrLnDebug "rendering static"
1359+ ((), html) <- liftIO $ renderStatic $ runHydratableT staticApp
1360+ putStrLnDebug "rendered static"
13551361 waitBeforeJS <- liftIO newEmptyMVar -- Empty until JS should be run
13561362 waitUntilSwitchover <- liftIO newEmptyMVar -- Empty until switchover
13571363 let entryPoint = do
reflex-dom/default.nixdeleted−38
@@ -1,38 +0,0 @@
1−{ mkDerivation, base, bytestring, jsaddle-webkit2gtk, jsaddle-wkwebview, jsaddle-warp, reflex
2−, reflex-dom-core, stdenv, text, ghc, hostPlatform, jsaddle-clib, android-activity ? null
3−, ghcBackend ? if hostPlatform.isDarwin then "wkwebview" else "webkit2gtk"
4−}:
5−assert (builtins.elem ghcBackend [ "warp" "webkit2gtk" "wkwebview" ]);
6−let isAndroid = hostPlatform.libc == "bionic";
7− ghcBackendPackage = {
8− webkit2gtk = jsaddle-webkit2gtk;
9− warp = jsaddle-warp;
10− wkwebview = jsaddle-wkwebview;
11− }.${ghcBackend};
12−in mkDerivation {
13− pname = "reflex-dom";
14− version = "0.5.2";
15− src = builtins.filterSource (path: type: !(builtins.elem (baseNameOf path) [ ".git" "dist" ])) ./.;
16− libraryHaskellDepends = [
17− base bytestring reflex reflex-dom-core text
18− ] ++ (if ghc.isGhcjs or false then [
19− ] else if hostPlatform.isiOS then [
20− jsaddle-wkwebview
21− ] else if isAndroid then [
22− jsaddle-clib
23− android-activity
24− ] else if hostPlatform.isMacOS then [
25− jsaddle-wkwebview
26− ghcBackendPackage
27− ] else [
28− ghcBackendPackage
29− ]);
30− configureFlags = if isAndroid then [
31− "-fandroid"
32− ] else if ghcBackend == "warp" then [
33− "-fuse-warp"
34− ] else [
35− ];
36− description = "Functional Reactive Web Apps with Reflex";
37− license = stdenv.lib.licenses.bsd3;
38−}
reflex-dom/reflex-dom.cabal+3−8
@@ -1,5 +1,5 @@
11Name: reflex-dom
2−Version: 0.5.2
2+Version: 0.5.2.0
33Synopsis: Functional Reactive Web Apps with Reflex
44Description:
55 Reflex-DOM is a Functional Reactive web framework based on the Reflex FRP engine.
@@ -41,14 +41,9 @@ flag build-examples
4141 default: False
4242 manual: True
4343
44−flag android
45− description: Build an Android app
46− default: False
47− manual: True
48−
4944library
5045 hs-source-dirs: src
51− if flag(android)
46+ if os(android)
5247 hs-source-dirs: src-android
5348 other-modules: Reflex.Dom.Android.MainWidget
5449 build-depends:
@@ -83,7 +78,7 @@ library
8378 build-depends:
8479 jsaddle-webkit2gtk
8580 else
86− if !flag(android)
81+ if !os(android)
8782 build-depends:
8883 jsaddle-webkit2gtk
8984
reflex-platform.nixdeleted−8
@@ -1,8 +0,0 @@
1−let
2− reflex-platform-src = (import <nixpkgs> {}).fetchFromGitHub {
3− owner = "reflex-frp";
4− repo = "reflex-platform";
5− rev = "384cd850f3adf1d404bced2424b5f6efb0f415f2";
6− sha256 = "1ws77prqx8khmp8j6br1ij4k2v4dlgv170r9fmg0p1jivfbn8y9d";
7− };
8−in import reflex-platform-src
release.nix+32−9
@@ -1,12 +1,35 @@
1−{ rp ? import ./reflex-platform.nix {}
1+{ reflex-platform-fun ? import ./dep/reflex-platform
22}:
3+
34let
4− inherit (rp.nixpkgs) lib;
5+ native-reflex-platform = reflex-platform-fun {};
6+ inherit (native-reflex-platform.nixpkgs) lib;
57 systems = ["x86_64-linux" "x86_64-darwin"];
6− compilers = ["ghc8_4" "ghc8_0" "ghcjs8_4" "ghcjs8_0"];
7−in lib.genAttrs systems (system:
8− lib.genAttrs compilers (ghc: let
9− reflex-platform = import ./reflex-platform.nix { inherit system; };
10− hsPkgs = reflex-platform.${ghc};
11− in { inherit (import ./. hsPkgs reflex-platform.nixpkgs) reflex-dom reflex-dom-core; })
12−)
8+
9+ perPlatform = lib.genAttrs systems (system: let
10+ reflex-platform = reflex-platform-fun { inherit system; };
11+ compilers = [
12+ "ghc"
13+ "ghcjs"
14+ ] ++ lib.optionals (reflex-platform.androidSupport) [
15+ "ghcAndroidAarch64"
16+ "ghcAndroidAarch32"
17+ ] ++ lib.optionals (reflex-platform.iosSupport) [
18+ "ghcIosAarch64"
19+ ];
20+ hsPkgs = lib.genAttrs compilers (ghc: let
21+ ghc' = reflex-platform.${ghc}.override {
22+ overrides = self: super: import ./. self;
23+ };
24+ in {
25+ inherit (ghc') reflex-dom reflex-dom-core;
26+ });
27+ in hsPkgs // {
28+ cache = reflex-platform.pinBuildInputs "reflex-dom-${system}"
29+ (lib.concatLists (map builtins.attrValues (builtins.attrValues hsPkgs)));
30+ });
31+
32+ metaCache = native-reflex-platform.pinBuildInputs "reflex-dom-everywhere"
33+ (map (a: a.cache) (builtins.attrValues perPlatform));
34+
35+in perPlatform // { inherit metaCache; }