on master help sign in
Merge branch 'develop' into ts-fix-exe-config
b82dabcAli Abrar
lib/executable-config/lookup/src-ghcjs/Obelisk/ExecutableConfig/Lookup.hs+15−7
@@ -15,15 +15,15 @@ import GHCJS.DOM.Document (getHead)
15import GHCJS.DOM.DOMStringMap (get)
15import GHCJS.DOM.DOMStringMap (get)
16import GHCJS.DOM.Element (getInnerHTML)
16import GHCJS.DOM.Element (getInnerHTML)
17import GHCJS.DOM.HTMLElement (HTMLElement(HTMLElement), getDataset)
17import GHCJS.DOM.HTMLElement (HTMLElement(HTMLElement), getDataset)
18−import GHCJS.DOM.NodeList (item, getLength)
18+import GHCJS.DOM.NodeList (IsNodeList, item, getLength)
19import GHCJS.DOM.ParentNode (querySelectorAll)
19import GHCJS.DOM.ParentNode (querySelectorAll)
20−import GHCJS.DOM.Types (Node(Node), castTo)
20+import GHCJS.DOM.Types (MonadJSM, Node(Node), castTo)
21
21
22getConfigs :: IO (Map Text ByteString)
22getConfigs :: IO (Map Text ByteString)
23getConfigs = do
23getConfigs = do
24 Just doc <- currentDocument
24 Just doc <- currentDocument
25 Just hd <- getHead doc
25 Just hd <- getHead doc
26− nodes <- collToList =<< querySelectorAll hd ("[data-obelisk-executable-config-inject-key]" :: Text)
26+ nodes <- nodeListNodes =<< querySelectorAll hd ("[data-obelisk-executable-config-inject-key]" :: Text)
27 fmap Map.fromList $ for nodes $ \node -> do
27 fmap Map.fromList $ for nodes $ \node -> do
28 e <- castTo HTMLElement node >>= \case
28 e <- castTo HTMLElement node >>= \case
29 Nothing -> error "Found node with data attribute obelisk-executable-config-inject-key that is not an HTMLElement."
29 Nothing -> error "Found node with data attribute obelisk-executable-config-inject-key that is not an HTMLElement."
@@ -34,10 +34,18 @@ getConfigs = do
34 <$> get dataset ("obeliskExecutableConfigInjectKey" :: Text)
34 <$> get dataset ("obeliskExecutableConfigInjectKey" :: Text)
35 <*> (fmap decodeOrFail (getInnerHTML e))
35 <*> (fmap decodeOrFail (getInnerHTML e))
36 where
36 where
37− collToList es = do
38− len <- getLength es
39− list <- traverse (item es) [0..len-1]
40− pure $ catMaybes list
41 decodeOrFail x = case B64.decode (T.encodeUtf8 x) of
37 decodeOrFail x = case B64.decode (T.encodeUtf8 x) of
42 Left e -> error ("Obelisk.ExecutableConfig.Lookup.getConfigs: error when decoding base64: " ++ e)
38 Left e -> error ("Obelisk.ExecutableConfig.Lookup.getConfigs: error when decoding base64: " ++ e)
43 Right x' -> x'
39 Right x' -> x'
40+
41+-- | Collect all nodes in the node list.
42+--
43+-- TODO: this and the version in obelisk-frontend should be
44+-- upstreamed to jsaddle.
45+nodeListNodes :: (IsNodeList l, MonadJSM m) => l -> m [Node]
46+nodeListNodes es = do
47+ len <- getLength es
48+ -- Warning! len is unsigned. If the NodeList is empty, we must avoid
49+ -- accidentally traversing over [0..maxBound::Word]
50+ nodes <- traverse (item es) $ if len == 0 then [] else [0..len-1]
51+ pure $ catMaybes nodes
lib/frontend/src/Obelisk/Frontend.hs+16−9
@@ -43,11 +43,11 @@ import qualified GHCJS.DOM as DOM
43import qualified GHCJS.DOM.Types as DOM
43import qualified GHCJS.DOM.Types as DOM
44import qualified GHCJS.DOM.History as DOM
44import qualified GHCJS.DOM.History as DOM
45import qualified GHCJS.DOM.Window as DOM
45import qualified GHCJS.DOM.Window as DOM
46−import Language.Javascript.JSaddle (JSM, jsNull)
46+import Language.Javascript.JSaddle (MonadJSM, JSM, jsNull)
47import GHCJS.DOM (currentDocument)
47import GHCJS.DOM (currentDocument)
48import GHCJS.DOM.Document (getHead)
48import GHCJS.DOM.Document (getHead)
49−import GHCJS.DOM.Node (removeChild_)
49+import GHCJS.DOM.Node (Node, removeChild_)
50−import GHCJS.DOM.NodeList (item, getLength)
50+import GHCJS.DOM.NodeList (IsNodeList, item, getLength)
51import GHCJS.DOM.ParentNode (querySelectorAll)
51import GHCJS.DOM.ParentNode (querySelectorAll)
52import Obelisk.Frontend.Cookie
52import Obelisk.Frontend.Cookie
53import Obelisk.Route.Frontend
53import Obelisk.Route.Frontend
@@ -105,13 +105,20 @@ removeHTMLConfigs :: JSM ()
105removeHTMLConfigs = void $ runMaybeT $ do
105removeHTMLConfigs = void $ runMaybeT $ do
106 doc <- MaybeT currentDocument
106 doc <- MaybeT currentDocument
107 hd <- MaybeT $ getHead doc
107 hd <- MaybeT $ getHead doc
108− es <- collToList =<< querySelectorAll hd ("[data-obelisk-executable-config-inject-key]" :: Text)
108+ es <- nodeListNodes =<< querySelectorAll hd ("[data-obelisk-executable-config-inject-key]" :: Text)
109 for_ es $ removeChild_ hd
109 for_ es $ removeChild_ hd
110− where
110+
111− collToList es = do
111+-- | Collect all nodes in the node list.
112+--
113+-- TODO: this and the version in exe-config/ghcjs/lookup should be
114+-- upstreamed to jsaddle.
115+nodeListNodes :: (IsNodeList l, MonadJSM m) => l -> m [Node]
116+nodeListNodes es = do
112− len <- getLength es
117+ len <- getLength es
113− lst <- traverse (item es) $ take (fromIntegral len) $ [0..] -- fun with unsigned types ...
118+ -- Warning! len is unsigned. If the NodeList is empty, we must avoid
119+ -- accidentally traversing over [0..maxBound::Word]
120+ nodes <- traverse (item es) $ if len == 0 then [] else [0..len-1]
114− pure $ catMaybes lst
121+ pure $ catMaybes nodes
115
122
116setInitialRoute :: Bool -> JSM ()
123setInitialRoute :: Bool -> JSM ()
117setInitialRoute useHash = do
124setInitialRoute useHash = do