on develop help sign in
Merge branch 'develop' into ae-relax-constraints
commit7eb1ef692050beb24058140d9e53fed9dfaee515 authorAli Abrar <aliabrar@gmail.com> dateWed 13 Nov 2019, 20:20 (7 years ago) parent0e21a81f473579
22 files changed+282−250
CONTRIBUTING.md+5 default.nix+57−5 dep/reflex-platform/default.nix+7 dep/reflex-platform/github.json+7 hydra.json−29 jobsets.nix−70 reflex-dom-core/ChangeLog.md+5−3 reflex-dom-core/default.nix−63 reflex-dom-core/reflex-dom-core.cabal+8−5 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/Resize.hs+4 reflex-dom-core/test/hlint.hs+1 reflex-dom-core/test/hydration.hs+9−3 reflex-dom/default.nix−38 reflex-dom/reflex-dom.cabal+4−9 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+57−5
@@ -1,7 +1,59 @@
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 = haskellPackages.callPackage
7+ ({ temporary, jsaddle-warp, process, chrome-test-utils
8+ , selenium-server-standalone, which, fontconfig, chromium, pkgs
9+ }: let
10+ inherit (haskellPackages) ghc;
11+ noGcTest = stdenv.hostPlatform.system != "x86_64-linux"
12+ || stdenv.hostPlatform != stdenv.buildPlatform
13+ || (ghc.isGhcjs or false);
14+ in haskellLib.overrideCabal
15+ (haskellPackages.callCabal2nix "reflex-dom-core" ./reflex-dom-core { })
16+ (drv: {
17+ #TODO: Get hlint working for cross-compilation
18+ doCheck = stdenv.hostPlatform == stdenv.buildPlatform && !(ghc.isGhcjs or false);
19+
20+ # The headless browser run as part of the tests will exit without this
21+ preBuild = ''
22+ export HOME="$PWD"
23+ '';
24+
25+ # Show some output while running tests, so we might notice what's wrong
26+ testTarget = "--show-details=streaming";
27+
28+ testHaskellDepends = (drv.testHaskellDepends or []) ++ stdenv.lib.optionals (!noGcTest) [
29+ temporary
30+ jsaddle-warp
31+ process
32+ chrome-test-utils
33+ ];
34+
35+ testSystemDepends = (drv.testSystemDepends or []) ++ [
36+ selenium-server-standalone which
37+ ] ++ stdenv.lib.optionals (!noGcTest) [
38+ chromium
39+ pkgs.iproute
40+ ];
41+ } // stdenv.lib.optionalAttrs (!noGcTest) {
42+ # The headless browser run as part of gc tests would hang/crash without this
43+ preCheck = ''
44+ export FONTCONFIG_PATH=${fontconfig.out}/etc/fonts
45+ '';
46+ }))
47+ {};
48+ reflex-dom = haskellPackages.callPackage
49+ ({ android-activity }: haskellLib.overrideCabal
50+ (haskellPackages.callCabal2nix "reflex-dom" ./reflex-dom { })
51+ (drv: {
52+ # Hack until https://github.com/NixOS/cabal2nix/pull/432 lands
53+ libraryHaskellDepends = (drv.libraryHaskellDepends or []) ++ stdenv.lib.optionals (with stdenv.hostPlatform; isAndroid && is32bit) [
54+ android-activity
55+ ];
56+ }))
57+ {};
658 chrome-test-utils = haskellPackages.callCabal2nix "chrome-test-utils" ./chrome-test-utils {};
759}
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+5−3
@@ -2,16 +2,18 @@
22
33## Unreleased
44
5−* Relax constraints on `dyn` and `widgetHold` to match the ones in `networkView` and `networkHold` respectively
6−
75## 0.5.2
86
97* Update to use new dependent-sum/map packages and drop dependency on `*Tag` classes (e.g., `ShowTag`).
8+* Reintroduce "data-ssr": elements without this attribute are skipped during
9+ hydration.
10+* Fix an issue in the hydration tests that prevented the test from finding the chromium executable
11+* Relax constraints on `dyn` and `widgetHold` to match the ones in `networkView` and `networkHold` respectively
1012
1113## 0.5.1
1214
1315* Added support for marking elements with a "data-skip-hydration" attribute, which will cause hydration to ignore and skip over them.
14−* Removed "data-ssr" attributes from statically rendered output.:q
16+* Removed "data-ssr" attributes from statically rendered output.
1517
1618## 0.5
1719
reflex-dom-core/default.nixdeleted−63
@@ -1,63 +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−}:
13−let addGcTestDepends = drv: if (stdenv.system != "x86_64-linux" || stdenv.hostPlatform != stdenv.buildPlatform || (ghc.isGhcjs or false)) then drv else drv // {
14− # The headless browser run as part of gc tests would hang/crash without this
15− preCheck = ''
16− export FONTCONFIG_PATH=${fontconfig.out}/etc/fonts
17− '';
18− testHaskellDepends = (drv.testHaskellDepends or []) ++ [
19− temporary
20− jsaddle-warp
21− process
22− chrome-test-utils
23− ];
24− testSystemDepends = (drv.testSystemDepends or []) ++ [ chromium iproute ];
25− };
26−in mkDerivation (addGcTestDepends {
27− pname = "reflex-dom-core";
28− version = "0.5.2";
29− src = ./.;
30− libraryHaskellDepends = [
31− aeson base bifunctors bimap blaze-builder bytestring constraints
32− containers contravariant data-default dependent-map dependent-sum
33− dependent-sum-template directory exception-transformers ghcjs-dom
34− jsaddle keycode lens monad-control mtl network-uri primitive random
35− ref-tf reflex semigroups stm template-haskell text these
36− transformers unix zenc
37− ] ++ (if ghc.isGhcjs or false then [
38− hashable
39− ] else []);
40−
41− #TODO: Get hlint working for cross-compilation
42− doCheck = stdenv.hostPlatform == stdenv.buildPlatform && !(ghc.isGhcjs or false);
43−
44− # The headless browser run as part of the tests will exit without this
45− preBuild = ''
46− export HOME="$PWD"
47− '';
48−
49− # Show some output while running tests, so we might notice what's wrong
50− testTarget = "--show-details=streaming";
51−
52− testSystemDepends = [ selenium-server-standalone which ];
53− testHaskellDepends = [
54− aeson base bytestring constraints constraints-extras containers
55− dependent-map dependent-sum dependent-sum-template directory
56− exceptions filepath ghcjs-dom hlint hspec hspec-webdriver http-types HUnit jsaddle
57− jsaddle-warp lens lifted-base network process random reflex
58− silently temporary text unix wai wai-websockets warp webdriver
59− websockets
60− ];
61− description = "Functional Reactive Web Apps with Reflex";
62− license = stdenv.lib.licenses.bsd3;
63−})
reflex-dom-core/reflex-dom-core.cabal+8−5
@@ -43,13 +43,13 @@ library
4343 hs-source-dirs: src
4444 build-depends:
4545 aeson >= 0.8 && < 1.5,
46− base >= 4.7 && < 4.12,
46+ base >= 4.7 && < 4.13,
4747 bifunctors >= 4.2 && < 6,
4848 bimap >= 0.3 && < 0.4,
4949 blaze-builder,
5050 bytestring == 0.10.*,
51− containers == 0.5.*,
52− constraints >= 0.9 && < 0.11,
51+ containers >= 0.5 && < 0.7,
52+ constraints >= 0.9 && < 0.12,
5353 contravariant >= 1.4 && < 1.6,
5454 data-default >= 0.5 && < 0.8,
5555 dependent-map >= 0.3 && < 0.4,
@@ -68,10 +68,11 @@ library
6868 random,
6969 ref-tf == 0.4.*,
7070 reflex >= 0.6.2,
71+ semialign == 1.*,
7172 semigroups >= 0.16 && < 0.19,
72− stm == 2.4.*,
73+ stm >= 2.4 && < 2.6,
7374 text == 1.2.*,
74− these >= 0.4 && < 0.8,
75+ these >= 0.4 && < 1.1,
7576 transformers >= 0.3 && < 0.6,
7677 network-uri >= 2.6.1 && < 2.7,
7778 zenc == 0.1.*
@@ -94,6 +95,7 @@ library
9495 Reflex.Dom.Builder.Class.Events
9596 Reflex.Dom.Builder.Immediate
9697 Reflex.Dom.Builder.InputDisabled
98+ Reflex.Dom.Builder.Hydratable
9799 Reflex.Dom.Builder.Static
98100 Reflex.Dom.Class
99101 Reflex.Dom.Core
@@ -188,6 +190,7 @@ test-suite hydration
188190 , warp
189191 , webdriver
190192 , websockets
193+ , which
191194 hs-source-dirs: test
192195 ghc-options: -rtsopts -with-rtsopts=-T -Wall -fwarn-tabs -funbox-strict-fields -O2 -ferror-spans
193196 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/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
@@ -19,6 +19,7 @@ main = do
1919 , "--ignore=Unnecessary hiding" -- Interferes with cross-version compatibility
2020 , "--ignore=Use <$>"
2121 , "--ignore=Reduce duplication" --TODO: Re-enable this test
22+ , "--ignore=Use list comprehension"
2223 , "--cpp-define=USE_TEMPLATE_HASKELL"
2324 ]
2425 if null ideas then exitSuccess else exitFailure
reflex-dom-core/test/hydration.hs+9−3
@@ -52,6 +52,7 @@ import System.IO (stderr)
5252import System.IO.Silently
5353import System.IO.Temp
5454import System.Process
55+import System.Which (staticWhich)
5556import qualified Test.HUnit as HUnit (assertEqual, assertFailure)
5657import qualified Test.Hspec as H
5758import qualified Test.Hspec.Core.Spec as H
@@ -74,6 +75,9 @@ import qualified Test.WebDriver.Capabilities as WD
7475import Test.Util.ChromeFlags
7576import Test.Util.UnshareNetwork
7677
78+chromium :: FilePath
79+chromium = $(staticWhich "chromium")
80+
7781seleniumPort, jsaddlePort :: PortNumber
7882seleniumPort = 8000
7983jsaddlePort = 8001
@@ -123,7 +127,7 @@ main = do
123127 isHeadless <- (== Nothing) <$> lookupEnv "NO_HEADLESS"
124128 withSandboxedChromeFlags isHeadless $ \chromeFlags -> do
125129 withSeleniumServer $ \selenium -> do
126− browserPath <- liftIO $ T.strip . T.pack <$> readProcess "which" [ "chromium" ] ""
130+ let browserPath = T.strip $ T.pack chromium
127131 when (T.null browserPath) $ fail "No browser found"
128132 withDebugging <- isNothing <$> lookupEnv "NO_DEBUG"
129133 let wdConfig = WD.defaultConfig { WD.wdPort = fromIntegral $ _selenium_portNumber selenium }
@@ -1200,7 +1204,9 @@ tests withDebugging wdConfig caps _selenium = do
12001204 let static = do
12011205 checkBodyText "before\ninner\nafter"
12021206 -- Two <p> tags should be present
1203− [p1, p2] <- WD.findElems (WD.ByTag "p")
1207+ (p1, p2) <- WD.findElems (WD.ByTag "p") >>= \case
1208+ [p1, p2] -> pure (p1, p2)
1209+ _ -> error "Unexpected number of `p` tags (expected 2)"
12041210 ol <- findElemWithRetry (WD.ByTag "ol")
12051211 shouldContainText "before" p1
12061212 shouldContainText "inner" ol
@@ -1345,7 +1351,7 @@ testWidgetDebug' withDebugging beforeJS afterSwitchover bodyWidget = do
13451351 bodyWidget
13461352 el "script" $ text $ TE.decodeUtf8 $ LBS.toStrict $ jsaddleJs False
13471353 putStrLnDebug "rendering static"
1348− ((), html) <- liftIO $ renderStatic staticApp
1354+ ((), html) <- liftIO $ renderStatic $ runHydratableT staticApp
13491355 putStrLnDebug "rendered static"
13501356 waitBeforeJS <- liftIO newEmptyMVar -- Empty until JS should be run
13511357 waitUntilSwitchover <- liftIO newEmptyMVar -- Empty until switchover
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+4−9
@@ -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:
@@ -62,7 +57,7 @@ library
6257 cpp-options: -DANDROID
6358 build-tools: hsc2hs
6459 build-depends:
65− base >= 4.7 && < 4.12,
60+ base >= 4.7 && < 4.13,
6661 bytestring == 0.10.*,
6762 reflex >= 0.6.2,
6863 reflex-dom-core >=0.5.2 && <0.6,
@@ -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; }