From 91b75eee348643e1265ffdccc8fdc2940054a2c9 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 13 Mar 2024 13:52:50 +0400 Subject: [PATCH 01/64] WIP: Wasm Backend --- examples/todomvc/TodoItem.hs | 45 +- examples/todomvc/TodoList.hs | 23 +- examples/todomvc/Utils.hs | 45 +- examples/todomvc/todomvc.hs | 5 +- ghc-wasm-meta | 1 + htmlt.cabal | 92 ++-- jsbits/index.js | 23 + jsbits/jsffi.js | 147 +++++ src/HtmlT/Base.hs | 62 +-- src/HtmlT/DOM.hs | 597 +++++++++++++-------- src/HtmlT/Element.hs | 2 +- src/HtmlT/Internal.hs | 11 +- src/HtmlT/Main.hs | 14 +- src/HtmlT/Property.hs | 2 +- src/HtmlT/Types.hs | 12 +- src/JavaScript/Compat/Foreign/Callback.hs | 135 ----- src/JavaScript/Compat/Marshal.hs | 91 ---- src/JavaScript/Compat/Prim.hs | 177 ------ src/JavaScript/Compat/String.hs | 16 - src/JavaScript/Compat/String/JavaScript.hs | 207 ------- src/JavaScript/Compat/String/Native.hs | 115 ---- src/Wasm/Compat/Marshal.hs | 167 ++++++ src/Wasm/Compat/Prim.hs | 76 +++ webpack.config.js | 13 + 24 files changed, 925 insertions(+), 1153 deletions(-) create mode 160000 ghc-wasm-meta create mode 100644 jsbits/index.js create mode 100644 jsbits/jsffi.js delete mode 100644 src/JavaScript/Compat/Foreign/Callback.hs delete mode 100644 src/JavaScript/Compat/Marshal.hs delete mode 100644 src/JavaScript/Compat/Prim.hs delete mode 100644 src/JavaScript/Compat/String.hs delete mode 100644 src/JavaScript/Compat/String/JavaScript.hs delete mode 100644 src/JavaScript/Compat/String/Native.hs create mode 100644 src/Wasm/Compat/Marshal.hs create mode 100644 src/Wasm/Compat/Prim.hs create mode 100644 webpack.config.js diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index 8f566f9..1b48dfa 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -4,10 +4,8 @@ import Control.Monad.State import Data.Maybe import GHC.Generics (Generic) import HtmlT -import JavaScript.Compat.Marshal -import JavaScript.Compat.Prim -import JavaScript.Compat.String (JSString) -import JavaScript.Compat.String qualified as JSS +import Wasm.Compat.Marshal +import Wasm.Compat.Prim import "this" Utils @@ -66,23 +64,18 @@ html cfg = li_ do toggleClass "editing" editingDyn toggleClass "hidden" cfg.is_hidden_dyn div_ [class_ "view"] do - on "dblclick" $ decodeEvent (propDecoder "target") $ - eval . DoubleClickAction cfg + on @DblClickWithTarget $ eval . DoubleClickAction cfg input_ [class_ "toggle", type_ "checkbox"] do dynChecked $ (.completed) <$> fromRef cfg.state_ref - on "change" $ decodeEvent checkedDecoder $ - eval . CheckedAction cfg + on @"checkbox/change" $ eval . CheckedAction cfg label_ $ dynText $ (.title) <$> fromRef cfg.state_ref button_ [class_ "destroy"] do - on_ "click" cfg.ask_delete_item + on @"click" cfg.ask_delete_item input_ [class_ "edit", type_ "text"] do dynValue valueDyn - on "input" $ decodeEvent valueDecoder $ - eval . InputAction cfg - on "keydown" $ decodeEvent keyCodeDecoder $ - eval . KeydownAction cfg - on_ "blur" $ - eval (CommitAction cfg) + on @"input" $ eval . InputAction cfg + on @"keydown" $ eval . KeydownAction cfg + on @"input/blur" $ const $ eval (CommitAction cfg) emptyTodoItemState :: TodoItemState emptyTodoItemState = TodoItemState "" False Nothing @@ -93,17 +86,27 @@ instance ToJSVal TodoItemState where completed <- toJSVal s.completed editing <- toJSVal s.editing return $ js_buildObjectI3 - (JSS.toJSValPure "title") title - (JSS.toJSValPure "completed") completed - (JSS.toJSValPure "editing") editing + (toJSValPure @JSString "title") title + (toJSValPure @JSString "completed") completed + (toJSValPure @JSString "editing") editing instance FromJSVal TodoItemState where fromJSVal j = do - mtitle <- fromJSVal =<< getProp j "title" - mcompleted <- fromJSVal =<< getProp j "completed" - mediting <- fromJSVal =<< getProp j "editing" + mtitle <- fromJSVal =<< js_getProp j "title" + mcompleted <- fromJSVal =<< js_getProp j "completed" + mediting <- fromJSVal =<< js_getProp j "editing" return do title <- mtitle completed <- mcompleted editing <- mediting return TodoItemState {..} + +data DblClickWithTarget + +instance IsEventName DblClickWithTarget where + type EventListenerCb DblClickWithTarget = JSVal -> Step () + addEventListenerArgs = AddEventListenerArgs + { event_name = "dblclick" + , listener_options = defaultEventListenerOptions + , mk_callback = \k j -> liftIO (js_getProp j "target") >>= k + } diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index a928d9b..d38b6a1 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -6,9 +6,8 @@ import Data.List qualified as List import Data.Maybe import GHC.Generics (Generic) import HtmlT -import JavaScript.Compat.Marshal -import JavaScript.Compat.String (JSString(..)) -import JavaScript.Compat.String qualified as JSS +import Wasm.Compat.Marshal +import Wasm.Compat.Prim import "this" TodoItem qualified as TodoItem import "this" Utils @@ -62,7 +61,7 @@ eval = \case InputAction cfg newVal -> do modifyRef cfg.state_ref \s -> s {title = newVal} CommitAction cfg -> do - title <- JSS.strip . (.title) <$> readRef cfg.state_ref + title <- {- JSS.strip . -} (.title) <$> readRef cfg.state_ref case title of "" -> return () t -> modifyRef cfg.state_ref \s -> s @@ -100,15 +99,13 @@ html cfg = do h1_ (text "todos") input_ [class_ "new-todo", placeholder_ "What needs to be done?", autofocus_ True] do dynValue $ (.title) <$> fromRef cfg.state_ref - on "input" $ decodeEvent valueDecoder $ - eval . InputAction cfg - on "keydown" $ decodeEvent keyCodeDecoder $ - eval . KeydownAction cfg + on @"input" $ eval . InputAction cfg + on @"keydown" $ eval . KeydownAction cfg mainWidget = section_ [class_ "main"] do toggleClass "hidden" hiddenDyn input_ [id_ "toggle-all", class_ "toggle-all", type_ "checkbox"] do - on "click" $ decodeEvent checkedDecoder $ - eval . ToggleAllAction cfg + on @"checkbox/change" $ eval . ToggleAllAction cfg + return () label_ do attr "for" "toggle-all" text "Mark all as completed" @@ -125,12 +122,12 @@ html cfg = do footerWidget = footer_ [class_ "footer"] do toggleClass "hidden" hiddenDyn span_ [class_ "todo-count"] do - strong_ $ dynText $ JSS.pack . show <$> itemsLeftDyn + strong_ $ dynText $ toJSString . show <$> itemsLeftDyn dynText $ pluralize " item left" " items left" <$> itemsLeftDyn ul_ [class_ "filters"] do for_ [All, Active, Completed] filterWidget button_ [class_ "clear-completed"] do - on_ "click" $ eval (ClearCompletedAction cfg) + on @"click" $ eval (ClearCompletedAction cfg) text "Clear completed" footerInfoWidget = footer_ [class_ "info"] do p_ "Double-click to edit a todo" @@ -143,7 +140,7 @@ html cfg = do filterWidget flt = li_ do a_ [href_ (printFilter flt)] do toggleClass "selected" $ filterSelectedDyn flt - text $ JSS.pack (show flt) + text $ toJSString (show flt) hiddenDyn = Prelude.null . (.items) <$> fromRef cfg.state_ref itemsLeftDyn = diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs index ba9e0b5..c61f303 100644 --- a/examples/todomvc/Utils.hs +++ b/examples/todomvc/Utils.hs @@ -5,63 +5,58 @@ module Utils where import Control.Monad import Control.Monad.Reader -import Data.Coerce import Data.Typeable import HtmlT -import JavaScript.Compat.Foreign.Callback -import JavaScript.Compat.Marshal -import JavaScript.Compat.Prim -import JavaScript.Compat.String (JSString(..)) -import JavaScript.Compat.String qualified as JSS -import Unsafe.Coerce +import Wasm.Compat.Prim +import Wasm.Compat.Marshal mkUrlHashRef :: MonadReactive m => m (DynRef JSString) mkUrlHashRef = do initial <- liftIO js_readUrlHash routeRef <- newRef initial win <- getCurrentWindow - popStateCb <- liftIO $ asyncCallback $ + popStateCb <- liftIO $ js_dynExport1 \_ -> js_readUrlHash >>= dynStep . writeRef routeRef - liftIO $ js_setProp (coerce win) "onpopstate" (unsafeCoerce popStateCb) + liftIO $ js_addEventListener win ((\(JSString j) -> j) $ toJSString "onpopstate") popStateCb return routeRef localStorageSet :: forall a m. (MonadIO m, ToJSVal a, Typeable a) => a -> m () localStorageSet val = liftIO (toJSVal val >>= js_setItem key) where - key = JSS.pack . show $ typeRepFingerprint $ typeRep (Proxy @a) + key = toJSString . show $ typeRepFingerprint $ typeRep (Proxy @a) localStorageGet :: forall a m. (MonadIO m, FromJSVal a, Typeable a) => m (Maybe a) localStorageGet = liftIO do mval <- nullableToMaybe <$> (js_getItem key) + liftIO $ js_consoleLog . (.unNullable) =<< js_getItem key join <$> forM mval fromJSVal where - key = JSS.pack . show . typeRepFingerprint $ typeRep (Proxy @a) + key = toJSString . show . typeRepFingerprint $ typeRep (Proxy @a) -#if defined(javascript_HOST_ARCH) +#if defined(wasm32_HOST_ARCH) foreign import javascript unsafe - "(($1) => { setTimeout(function() {\ + "setTimeout(function() {\ var inputEl = $1.parentNode.parentNode.querySelector('input.edit');\ inputEl.focus();\ - }, 0); })" + }, 0)" js_todoItemInputFocus :: JSVal -> IO () foreign import javascript unsafe - "(function(key, val){\ - localStorage.setItem(key, JSON.stringify(val));\ - })" + "localStorage.setItem($1, JSON.stringify($2));" js_setItem :: JSString -> JSVal -> IO () foreign import javascript unsafe - "(function(key){\ - var itemText = localStorage.getItem(key);\ - return itemText ? JSON.parse(itemText) : null;\ - })" + "console.log($1)" + js_consoleLog :: JSVal -> IO () + +foreign import javascript unsafe + "var itemText = localStorage.getItem($1);\ + return itemText ? JSON.parse(itemText) : null;" js_getItem :: JSString -> IO (Nullable JSVal) + foreign import javascript unsafe - "(function(){\ - return location.hash;\ - })" + "location.hash" js_readUrlHash :: IO JSString -- Need this because GHC.JS.Prim.Internal.Build buildObjectI3 is @@ -72,7 +67,7 @@ foreign import javascript unsafe var res = {};\ res[k1] = v1; res[k2] = v2; res[k3] = v3;\ return res;\ - })" + })($1,$2,$3,$4,$5,$6)" js_buildObjectI3 :: JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal #else js_todoItemInputFocus :: JSVal -> IO () = errorGhcjsOnly diff --git a/examples/todomvc/todomvc.hs b/examples/todomvc/todomvc.hs index a8c800e..a453b25 100644 --- a/examples/todomvc/todomvc.hs +++ b/examples/todomvc/todomvc.hs @@ -6,7 +6,10 @@ import "this" TodoList qualified as TodoList import "this" Utils main :: IO () -main = void $ attachToBody do +main = return () + +foreign export ccall wasm_main :: IO () +wasm_main = void $ attachToBody do renv <- asks (.html_reactive_env) urlHashRef <- mkUrlHashRef todosRef <- dynStep $ TodoList.eval (TodoList.InitAction renv urlHashRef) diff --git a/ghc-wasm-meta b/ghc-wasm-meta new file mode 160000 index 0000000..426e46a --- /dev/null +++ b/ghc-wasm-meta @@ -0,0 +1 @@ +Subproject commit 426e46a5a8ffda63a5dde02e0bf9eb60f9cca089 diff --git a/htmlt.cabal b/htmlt.cabal index 545cc7c..ad329d8 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -89,10 +89,8 @@ library HtmlT.Main HtmlT.Property HtmlT.Types - JavaScript.Compat.Foreign.Callback - JavaScript.Compat.Marshal - JavaScript.Compat.Prim - JavaScript.Compat.String + Wasm.Compat.Prim + Wasm.Compat.Marshal other-modules: Paths_htmlt build-depends: @@ -102,30 +100,26 @@ library mtl, text, transformers, - if !arch(javascript) - build-depends: - ghc-prim, - other-modules: - JavaScript.Compat.String.Native - else - other-modules: - JavaScript.Compat.String.JavaScript + ghc-experimental, -executable htmlt-counter - import: htmlt-common - main-is: counter.hs - hs-source-dirs: ./examples/counter - build-depends: - base, - htmlt, - transformers, - if !flag(examples) - buildable: False +-- executable htmlt-counter +-- import: htmlt-common +-- main-is: counter.hs +-- hs-source-dirs: ./examples/counter +-- build-depends: +-- base, +-- htmlt, +-- transformers, +-- if !flag(examples) +-- buildable: False executable htmlt-todomvc import: htmlt-common main-is: todomvc.hs hs-source-dirs: ./examples/todomvc + ghc-options: + -no-hs-main -optl-mexec-model=reactor + -optl-Wl,--export=hs_init,--export=wasm_main other-modules: TodoItem TodoList @@ -137,32 +131,32 @@ executable htmlt-todomvc if !flag(examples) buildable: False -executable htmlt-simple-routing - import: htmlt-common - main-is: simple-routing.hs - hs-source-dirs: ./examples/simple-routing - other-modules: - Assets - Router - Pages - Utils - build-depends: - base, - bytestring, - mtl, - htmlt, - if !flag(examples) - buildable: False +-- executable htmlt-simple-routing +-- import: htmlt-common +-- main-is: simple-routing.hs +-- hs-source-dirs: ./examples/simple-routing +-- other-modules: +-- Assets +-- Router +-- Pages +-- Utils +-- build-depends: +-- base, +-- bytestring, +-- mtl, +-- htmlt, +-- if !flag(examples) +-- buildable: False -executable htmlt-benchmarks - import: htmlt-common - main-is: benchmarks.hs - hs-source-dirs: ./benchmarks/ - build-depends: - base, - htmlt, - text, - gauge, - -- Fails to build with javascript-backend - buildable: False +-- executable htmlt-benchmarks +-- import: htmlt-common +-- main-is: benchmarks.hs +-- hs-source-dirs: ./benchmarks/ +-- build-depends: +-- base, +-- htmlt, +-- text, +-- gauge, +-- -- Fails to build with javascript-backend +-- buildable: False diff --git a/jsbits/index.js b/jsbits/index.js new file mode 100644 index 0000000..02d3edf --- /dev/null +++ b/jsbits/index.js @@ -0,0 +1,23 @@ +import { WASI, File, OpenFile } from '@bjorn3/browser_wasi_shim'; +import * as jsffi from './jsffi'; + +let __exports = {}; + +window.startReactor = async function (wasmUri, opt) { + const wasi = new WASI([], [], [ + new OpenFile(new File([])), // stdin + new OpenFile(new File([])), // stdout + new OpenFile(new File([])), // stderr + ]); + + const wasm = await WebAssembly.compileStreaming(fetch(wasmUri)); + const inst = await WebAssembly.instantiate(wasm, { + wasi_snapshot_preview1: wasi.wasiImport, + ghc_wasm_jsffi: jsffi.default(__exports) + }); + + Object.assign(__exports, inst.exports); + await wasi.initialize(inst); + await inst.exports.hs_init(); + await inst.exports.wasm_main(); +}; diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js new file mode 100644 index 0000000..f95af10 --- /dev/null +++ b/jsbits/jsffi.js @@ -0,0 +1,147 @@ +// This file implements the JavaScript runtime logic for Haskell +// modules that use JSFFI. It is not an ESM module, but the template +// of one; the post-linker script will copy all contents into a new +// ESM module. + +// Manage a mapping from unique 32-bit ids to actual JavaScript +// values. +class JSValManager { + #lastk = 0; + #kv = new Map(); + + constructor() {} + + // Maybe just bump this.#lastk? For 64-bit ids that's sufficient, + // but better safe than sorry in the 32-bit case. + #allocKey() { + let k = this.#lastk; + while (true) { + if (!this.#kv.has(k)) { + this.#lastk = k; + return k; + } + k = (k + 1) | 0; + } + } + + newJSVal(v) { + const k = this.#allocKey(); + this.#kv.set(k, v); + return k; + } + + // A separate has() call to ensure we can store undefined as a value + // too. Also, unconditionally check this since the check is cheap + // anyway, if the check fails then there's a use-after-free to be + // fixed. + getJSVal(k) { + if (!this.#kv.has(k)) { + throw new WebAssembly.RuntimeError(`getJSVal(${k})`); + } + return this.#kv.get(k); + } + + // Check for double free as well. + freeJSVal(k) { + if (!this.#kv.delete(k)) { + throw new WebAssembly.RuntimeError(`freeJSVal(${k})`); + } + } +} + +// A simple & fast setImmediate() implementation for browsers. It's +// not a drop-in replacement for node.js setImmediate() because: +// 1. There's no clearImmediate(), and setImmediate() doesn't return +// anything +// 2. There's no guarantee that callbacks scheduled by setImmediate() +// are executed in the same order (in fact it's the opposite lol), +// but you are never supposed to rely on this assumption anyway +class SetImmediate { + #fs = []; + #mc = new MessageChannel(); + + constructor() { + this.#mc.port1.addEventListener("message", () => { + this.#fs.pop()(); + }); + this.#mc.port1.start(); + } + + setImmediate(cb, ...args) { + this.#fs.push(() => cb(...args)); + this.#mc.port2.postMessage(undefined); + } +} + +// The actual setImmediate() to be used. This is a ESM module top +// level binding and doesn't pollute the globalThis namespace. +let setImmediate; +if (globalThis.setImmediate) { + // node.js, bun + setImmediate = globalThis.setImmediate; +} else { + /* try { + * // deno + * setImmediate = (await import("node:timers")).setImmediate; + * } catch { */ + // browsers + const sm = new SetImmediate(); + setImmediate = (cb, ...args) => sm.setImmediate(cb, ...args); + /* } */ +} + +export default (__exports) => { +const __ghc_wasm_jsffi_jsval_manager = new JSValManager(); +const __ghc_wasm_jsffi_finalization_registry = new FinalizationRegistry(sp => __exports.rts_freeStablePtr(sp)); +return { +newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v), +getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), +freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), +scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), +ZC0ZCmainZCUtilsZC: ($1,$2,$3,$4,$5,$6) => ((function(k1, v1, k2, v2, k3, v3){ var res = {}; res[k1] = v1; res[k2] = v2; res[k3] = v3; return res; })($1,$2,$3,$4,$5,$6)), +ZC1ZCmainZCUtilsZC: () => (location.hash), +ZC2ZCmainZCUtilsZC: ($1) => {var itemText = localStorage.getItem($1); return itemText ? JSON.parse(itemText) : null;}, +ZC3ZCmainZCUtilsZC: ($1) => (console.log($1)), +ZC4ZCmainZCUtilsZC: ($1,$2) => {localStorage.setItem($1, JSON.stringify($2));}, +ZC5ZCmainZCUtilsZC: ($1) => (setTimeout(function() { var inputEl = $1.parentNode.parentNode.querySelector('input.edit'); inputEl.focus(); }, 0)), +ZC1ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: async ($1,$2,$3) => ($1.addEventListener($2, $3)), +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC2ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC($1,a1)), +ZC4ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => {$1[$2] = $3;}, +ZC7ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {if ($1.parentNode) $1.parentNode.removeChild($1); if ($2.parentNode) $2.parentNode.removeChild($2);}, +ZC8ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {for (;;){ if (!$2.previousSibling || !$2.previousSibling.parentNode || $2.previousSibling === $1 ) break; $2.previousSibling.parentNode.removeChild($2.previousSibling); }}, +ZC9ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: () => (window.document.body), +ZC11ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: () => {return window}, +ZC12ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: async ($1) => (window.addEventListener('beforeunload', $1)), +ZC13ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {$1.nodeValue = $2;}, +ZC14ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {$1.classList.remove($2);}, +ZC15ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {$1.classList.add($2);}, +ZC16ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createComment($1)), +ZC17ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createTextNode($1)), +ZC19ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createElement($1)), +ZC23ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => ($1.setAttribute($2, $3)), +ZC24ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => ($1.insertBefore($2, $3)), +ZC25ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => ($1.appendChild($2)), +ZC0ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), +ZC1ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1.length), +ZC2ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1.push($2)), +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: () => ([]), +ZC5ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), +ZC6ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => (($1 ? true : false)), +ZC8ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1), +ZC9ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1), +ZC10ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => {if ($1 === undefined || $1 === null) return 0; if (typeof $1 === 'boolean') return 1; if (typeof $1 === 'number') return 2; if (typeof $1 === 'string') return 3; if (Array.isArray($1)) return 4; return 5;}, +ZC11ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => (($1 === null || $1 === undefined)), +ZC14ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: () => (null), +ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), +ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), +ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, +ZC21ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => (__ghc_wasm_jsffi_finalization_registry.register($1, $2, $1)), +ZC18ZCghczminternalZCGHCziInternalziWasmziPrimziImportsZC: ($1,$2) => ($1.then(() => __exports.rts_promiseResolveUnit($2), err => __exports.rts_promiseReject($2, err))), +ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => (`${$1.stack ? $1.stack : $1}`), +ZC1ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2) => ((new TextDecoder('utf-8', {fatal: true})).decode(new Uint8Array(__exports.memory.buffer, $1, $2))), +ZC2ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written), +ZC3ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => ($1.length), +ZC4ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => {if (!__ghc_wasm_jsffi_finalization_registry.unregister($1)) { throw new WebAssembly.RuntimeError('js_callback_unregister'); }}, +ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziConcziInternalZC: async ($1) => (new Promise(res => setTimeout(res, $1 / 1000))), +}; +}; diff --git a/src/HtmlT/Base.hs b/src/HtmlT/Base.hs index 55ad268..c31066f 100644 --- a/src/HtmlT/Base.hs +++ b/src/HtmlT/Base.hs @@ -14,9 +14,8 @@ import HtmlT.DOM import HtmlT.Event import HtmlT.Internal import HtmlT.Types -import JavaScript.Compat.Marshal -import JavaScript.Compat.Prim -import JavaScript.Compat.String (JSString(..)) +import Wasm.Compat.Marshal +import Wasm.Compat.Prim -- | Create a DOM element with a given tag name and attach it to -- 'html_current_element'. Attributes, properties and children nodes can @@ -94,59 +93,6 @@ dynAttr k d = do el <- asks html_current_element performDyn $ liftIO . setAttribute el k <$> d --- | Attach listener to the root element. First agument is the name --- of the DOM event to listen. Second is the callback that accepts the fired --- DOM event object --- --- > el "button" do --- > on "click" \_event -> do --- > liftIO $ putStrLn "Clicked!" --- > text "Click here" -on :: EventName -> (DOMEvent -> Step ()) -> Html () -on name k = do - el <- asks html_current_element - onGlobalEvent defaultListenerOpts (nodeFromElement el) name k - --- | Same as 'on' but ignores 'DOMEvent' inside the callback -on_ :: EventName -> Step () -> Html () -on_ name = on name . const - --- | Same as 'on' but allows to specify 'ListenerOpts' -onOptions :: EventName -> ListenerOpts -> (DOMEvent -> Step ()) -> Html () -onOptions name opts k = do - el <- asks html_current_element - onGlobalEvent opts (nodeFromElement el) name k - -decodeEvent :: (JSVal -> MaybeT Step a) -> (a -> Step ()) -> DOMEvent -> Step () -decodeEvent dec act (DOMEvent jsevent) = - runMaybeT (dec jsevent) >>= maybe (pure ()) act - --- | Attach a listener to arbitrary target, not just the current root --- element (usually that would be @window@, @document@ or @body@ --- objects) -onGlobalEvent - :: MonadReactive m - => ListenerOpts - -- ^ Specify whether to call @event.stopPropagation()@ and - -- @event.preventDefault()@ on the fired event - -> DOMNode - -- ^ Event target - -> EventName - -- ^ Event name - -> (DOMEvent -> Step ()) - -- ^ Callback that accepts reference to the DOM event - -> m () -onGlobalEvent opts target name f = do - ReactiveEnv{renv_finalizers} <- askReactiveEnv - let - event = Event \re cb -> liftIO do - finalizerId <- nextQueueId re - unlisten <- addEventListener opts target name $ - dynStep . cb . f - modifyIORef' renv_finalizers $ Map.insert - (FinalizerQueueId finalizerId) (CustomFinalizer unlisten) - subscribe event id - -- | Assign CSS classes to the current root element. Compared to @prop -- "className"@ can be used multiple times for the same root -- @@ -191,7 +137,7 @@ toggleAttr att dyn = do performDyn $ liftIO . setup rootEl att <$> dyn where setup rootEl name = \case - True -> setAttribute rootEl name "on" + True -> setAttribute rootEl name $ toJSString "on" False -> removeAttribute rootEl name -- | Assign a CSS property to the root dynamically based on the value @@ -208,7 +154,7 @@ dynStyle cssProp dyn = do performDyn $ liftIO . setup rootEl <$> dyn where setup el t = do - styleVal <- getProp (unDOMElement el) "style" + styleVal <- js_getProp el.unDOMElement $ toJSString "style" cssVal <- toJSVal t js_setProp styleVal cssProp cssVal diff --git a/src/HtmlT/DOM.hs b/src/HtmlT/DOM.hs index e48af94..810556d 100644 --- a/src/HtmlT/DOM.hs +++ b/src/HtmlT/DOM.hs @@ -14,28 +14,239 @@ import Data.Coerce import GHC.Exts as Exts import GHC.Generics import Unsafe.Coerce - +import Wasm.Compat.Prim +import Wasm.Compat.Marshal import HtmlT.Types -import JavaScript.Compat.Foreign.Callback -import JavaScript.Compat.Marshal -import JavaScript.Compat.Prim -import JavaScript.Compat.String (JSString) -import JavaScript.Compat.String qualified as JSS - -data ListenerOpts = ListenerOpts - { lo_stop_propagation :: Bool - -- ^ If true call @event.stopPropagation()@ - , lo_prevent_default :: Bool - -- ^ If true call @event.preventDefault()@ - , lo_sync_callback :: Bool - -- ^ If true create callback with @syncCallback1 ThrowWouldBlock@ - -- otherwise — @asyncCallback1@ this is relevant for example when - -- listening to @BeforeUnloadEvent@ - -- https://developer.mozilla.org/en-US/docs/Web/API/BeforeUnloadEvent - } deriving stock (Generic) - -defaultListenerOpts :: ListenerOpts -defaultListenerOpts = ListenerOpts False False False +import HtmlT.Event + +import Data.Kind + +data EventListenerOptions = EventListenerOptions + { prevent_default :: Bool + , stop_propagation :: Bool + } deriving stock (Generic, Show, Eq) + +defaultEventListenerOptions :: EventListenerOptions +defaultEventListenerOptions = EventListenerOptions + { prevent_default = False + , stop_propagation = False + } + +on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> Html () +on k = addEventListener (addEventListenerArgs @eventName) k + +data AddEventListenerArgs callback = AddEventListenerArgs + { event_name :: JSString + , listener_options :: EventListenerOptions + , mk_callback :: callback -> JSVal -> Step () + } deriving (Generic) + +addEventListener + :: AddEventListenerArgs callback + -> callback + -> Html () +addEventListener args k = do + el <- asks (.html_current_element) + addEventListenerTarget el.unDOMElement args k + +-- | EventTarget.addEventListener() +-- https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener +addEventListenerTarget + :: MonadIO m + => JSVal + -> AddEventListenerArgs callback + -> callback + -> m () +addEventListenerTarget target args k = do + cb <- liftIO $ js_dynExport1 $ dynStep . args.mk_callback k + -- jscb <- withopts hscb + liftIO $ js_addEventListener target + (toJSValPure args.event_name) cb + let reactiveScope = 1::Int + installFinalizer _ _ = return () + installFinalizer reactiveScope do + js_addEventListener target + (toJSValPure args.event_name) cb + freeJSVal cb + +class IsEventName eventName where + type EventListenerCb eventName :: Type + addEventListenerArgs :: AddEventListenerArgs (EventListenerCb eventName) + +instance IsEventName "click" where + type EventListenerCb "click" = Step () + addEventListenerArgs = pointerEventArgs "click" + +instance IsEventName "mousedown" where + type EventListenerCb "mousedown" = Step () + addEventListenerArgs = pointerEventArgs "mousedown" + +instance IsEventName "mouseup" where + type EventListenerCb "mouseup" = Step () + addEventListenerArgs = pointerEventArgs "mouseup" + +instance IsEventName "dblclick" where + type EventListenerCb "dblclick" = Step () + addEventListenerArgs = pointerEventArgs "dblclick" + +instance IsEventName "submit" where + type EventListenerCb "submit" = Step () + addEventListenerArgs = submitEventArgs + +instance IsEventName "input" where + type EventListenerCb "input" = JSString -> Step () + addEventListenerArgs = inputEventArgs + +instance IsEventName "keydown" where + type EventListenerCb "keydown" = Int -> Step () + addEventListenerArgs = keyboardEventArgs "keydown" + +instance IsEventName "keyup" where + type EventListenerCb "keyup" = Int -> Step () + addEventListenerArgs = keyboardEventArgs "keyup" + +instance IsEventName "focus" where + type EventListenerCb "focus" = Step () + addEventListenerArgs = pointerEventArgs "focus" + +instance IsEventName "blur" where + type EventListenerCb "blur" = Step () + addEventListenerArgs = pointerEventArgs "blur" + +instance IsEventName "input/blur" where + type EventListenerCb "input/blur" = JSString -> Step () + addEventListenerArgs = inputEventArgs {event_name = "blur"} + +instance IsEventName "input/focus" where + type EventListenerCb "input/focus" = JSString -> Step () + addEventListenerArgs = inputEventArgs {event_name = "focus"} + +instance IsEventName "checkbox/change" where + type EventListenerCb "checkbox/change" = Bool -> Step () + addEventListenerArgs = checkboxChangeEventArgs + +instance IsEventName "select/change" where + type EventListenerCb "select/change" = JSString -> Step () + addEventListenerArgs = selectChangeEventArgs + +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event +pointerEventArgs :: JSString -> AddEventListenerArgs (Step ()) +pointerEventArgs event_name = AddEventListenerArgs + { event_name + , listener_options = defaultEventListenerOptions + , mk_callback = \k _ -> k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event +submitEventArgs :: AddEventListenerArgs (Step ()) +submitEventArgs = AddEventListenerArgs + { event_name = "submit" + , listener_options = defaultSubmitOptions + , mk_callback = \k _ -> k + } + where + defaultSubmitOptions = EventListenerOptions True True + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event +inputEventArgs :: AddEventListenerArgs (JSString -> Step ()) +inputEventArgs = AddEventListenerArgs + { event_name = "input" + , listener_options = defaultEventListenerOptions + , mk_callback = \k event -> do + target <- liftIO $ js_getProp event "target" + value <- liftIO $ js_getProp target "value" + liftIO (fromJSVal value) >>= mapM_ k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event +keyboardEventArgs :: JSString -> AddEventListenerArgs (Int -> Step ()) +keyboardEventArgs event_name = AddEventListenerArgs + { event_name + , listener_options = defaultEventListenerOptions + , mk_callback = \k event -> do + keyCode <- liftIO $ js_getProp event "keyCode" + liftIO (fromJSVal keyCode) >>= mapM_ k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event +focusEventArgs :: JSString -> AddEventListenerArgs (Step ()) +focusEventArgs event_name = AddEventListenerArgs + { event_name + , listener_options = defaultEventListenerOptions + , mk_callback = undefined + -- , mk_hs_callback = \k _ -> k + -- , mk_js_callback = \opts callbackId -> + -- Lam $ RevSeq $ TriggerEvent callbackId NullE : applyListenerOptions opts + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event +checkboxChangeEventArgs :: AddEventListenerArgs (Bool -> Step ()) +checkboxChangeEventArgs = AddEventListenerArgs + { event_name = "change" + , listener_options = defaultEventListenerOptions + , mk_callback = \k event -> do + target <- liftIO $ js_getProp event "target" + checked <- liftIO $ js_getProp target "checked" + liftIO (fromJSVal checked) >>= mapM_ k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event +selectChangeEventArgs :: AddEventListenerArgs (JSString -> Step ()) +selectChangeEventArgs = AddEventListenerArgs + { event_name = "change" + , listener_options = defaultEventListenerOptions + , mk_callback = \k event -> do + target <- liftIO $ js_getProp event "target" + value <- liftIO $ js_getProp target "value" + liftIO (fromJSVal value) >>= mapM_ k + } + +data Location = Location + { protocol :: JSString + -- ^ A string containing the protocol scheme of the URL, including + -- the final ':' + , hostname :: JSString + -- ^ A string containing the domain of the URL. + , port :: JSString + -- ^ A string containing the port number of the URL. + , pathname :: JSString + -- ^ A string containing an initial '/' followed by the path of the + -- URL, not including the query string or fragment. + , search :: JSString + -- ^ A string containing a '?' followed by the parameters or + -- "querystring" of the URL + , hash :: JSString + -- ^ A string containing a '#' followed by the fragment identifier + -- of the URL. + } deriving stock (Show, Eq, Generic) + +-- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event +popstateEventArgs :: AddEventListenerArgs (Location -> Step ()) +popstateEventArgs = AddEventListenerArgs + { event_name = "popstate" + , listener_options = defaultEventListenerOptions + , mk_callback = \k _event -> do + win <- liftIO js_getCurrentWindow + loc <- liftIO $ js_getProp win "location" + mprotocol <- liftIO $ fromJSVal =<< js_getProp loc "protocol" + mhostname <- liftIO $ fromJSVal =<< js_getProp loc "hostname" + mport <- liftIO $ fromJSVal =<< js_getProp loc "port" + mpathname <- liftIO $ fromJSVal =<< js_getProp loc "pathname" + msearch <- liftIO $ fromJSVal =<< js_getProp loc "search" + mhash <- liftIO $ fromJSVal =<< js_getProp loc "hash" + mapM_ k do + protocol <- mprotocol + hostname <- mhostname + port <- mport + pathname <- mpathname + search <- msearch + hash <- mhash + return Location {..} + } -- | Get global Window object @window@ -- https://developer.mozilla.org/en-US/docs/Web/API/Window @@ -116,45 +327,23 @@ unsafeInsertHtml parent manchor rawHtml = js_unsafeInsertHtml parent -- | Assuming given 'ContentBoundary' was inserted into the @parent@ -- element remove all the content inside the boundary. clearBoundary :: ContentBoundary -> IO () -clearBoundary ContentBoundary{..} = - js_clearBoundary boundary_begin boundary_end +clearBoundary b = + js_clearBoundary b.boundary_begin b.boundary_end -- | Detach 'ContentBoundary' from the DOM and everything inside the -- boundary. removeBoundary :: ContentBoundary -> IO () -removeBoundary ContentBoundary{..} = do - js_clearBoundary boundary_begin boundary_end - js_detachBoundary boundary_begin boundary_end +removeBoundary b = do + js_clearBoundary b.boundary_begin b.boundary_end + js_detachBoundary b.boundary_begin b.boundary_end -- | Run a given callback on BeforeUnloadEvent -- https://developer.mozilla.org/en-US/docs/Web/API/BeforeUnloadEvent onBeforeUnload :: IO () -> IO () onBeforeUnload cb = do - syncCb <- syncCallback ThrowWouldBlock cb - js_onBeforeUnload syncCb - --- | EventTarget.addEventListener() --- https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener -addEventListener - :: ListenerOpts - -> DOMNode - -> EventName - -> (DOMEvent -> IO ()) - -> IO (IO ()) -addEventListener ListenerOpts{..} target name f = do - hscb <- mkcallback (f . DOMEvent) - jscb <- withopts hscb - js_callMethod2 (coerce target) "addEventListener" - (JSS.toJSValPure (unEventName name)) (unsafeCoerce jscb) - return do - js_callMethod2 (coerce target) "removeEventListener" - (JSS.toJSValPure (unEventName name)) (unsafeCoerce jscb) - releaseCallback hscb - where - mkcallback = if lo_sync_callback - then syncCallback1 ThrowWouldBlock - else asyncCallback1 - withopts = js_callbackWithOptions lo_stop_propagation lo_prevent_default + jscb <- js_dynExport1 (const cb) + js_onBeforeUnload jscb + return () -- | Collection of deltaX, deltaY and deltaZ properties from WheelEvent -- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent @@ -164,12 +353,12 @@ data MouseDelta = MouseDelta , md_delta_z :: Int } deriving stock (Eq, Show, Generic) -mouseDeltaDecoder :: MonadIO m => JSVal -> MaybeT m MouseDelta -mouseDeltaDecoder mouseEvent = do - md_delta_x <- propDecoder "deltaX" mouseEvent - md_delta_y <- propDecoder "deltaY" mouseEvent - md_delta_z <- propDecoder "deltaZ" mouseEvent - return MouseDelta {..} +-- mouseDeltaDecoder :: MonadIO m => JSVal -> MaybeT m MouseDelta +-- mouseDeltaDecoder mouseEvent = do +-- md_delta_x <- propDecoder "deltaX" mouseEvent +-- md_delta_y <- propDecoder "deltaY" mouseEvent +-- md_delta_z <- propDecoder "deltaZ" mouseEvent +-- return MouseDelta {..} -- | Pair of two values, might denote either a size or coordinates in -- different contexts @@ -178,99 +367,77 @@ data Point a = Point , pt_y :: a } deriving stock (Eq, Show, Ord, Functor, Generic) --- | Read clientX and clientY properties from MouseEvent --- https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent -clientXYDecoder :: MonadIO m => JSVal -> MaybeT m (Point Int) -clientXYDecoder mouseEvent = do - pt_x <- propDecoder "clientX" mouseEvent - pt_y <- propDecoder "clientY" mouseEvent - return Point {..} - --- | Read offsetX and offsetY properties from MouseEvent --- https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent -offsetXYDecoder :: MonadIO m => JSVal -> MaybeT m (Point Int) -offsetXYDecoder mouseEvent = do - pt_x <- propDecoder "offsetX" mouseEvent - pt_y <- propDecoder "offsetY" mouseEvent - return Point {..} - --- | Read pageX and pageY properties from MouseEvent --- https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent -pageXYDecoder :: MonadIO m => JSVal -> MaybeT m (Point Int) -pageXYDecoder mouseEvent = do - pt_x <- propDecoder "pageX" mouseEvent - pt_y <- propDecoder "pageY" mouseEvent - return Point {..} - --- | Collection of altKey, ctrlKey, metaKey and shiftKey properties --- from KeyboardEvent -data KeyModifiers = KeyModifiers - { kmod_alt_key :: Bool - , kmod_ctrl_key :: Bool - , kmod_meta_key :: Bool - , kmod_shift_key :: Bool - } deriving stock (Eq, Show, Generic) - --- | Read altKey, ctrlKey, metaKey and shiftKey properties from --- KeyboardEvent --- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent -keyModifiersDecoder :: MonadIO m => JSVal -> MaybeT m KeyModifiers -keyModifiersDecoder keyEvent = do - kmod_alt_key <- propDecoder "altKey" keyEvent - kmod_ctrl_key <- propDecoder "ctrlKey" keyEvent - kmod_meta_key <- propDecoder "metaKey" keyEvent - kmod_shift_key <- propDecoder "shiftKey" keyEvent - return KeyModifiers {..} - --- | Read keyCode properties from KeyboardEvent --- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode -keyCodeDecoder :: MonadIO m => JSVal -> MaybeT m Int -keyCodeDecoder = propDecoder "keyCode" - --- | Collection of some useful information from KeyboardEvent -data KeyboardEvent = KeyboardEvent - { ke_modifiers :: KeyModifiers - , ke_key :: Maybe JSString - , ke_key_code :: Int - , ke_repeat :: Bool - } deriving stock (Generic) - --- | Read information from KeyboardEvent -keyboardEventDecoder :: MonadIO m => JSVal -> MaybeT m KeyboardEvent -keyboardEventDecoder keyEvent = do - ke_modifiers <- keyModifiersDecoder keyEvent - ke_key <- propDecoder "key" keyEvent - ke_key_code <- propDecoder "keyCode" keyEvent - ke_repeat <- propDecoder "repeat" keyEvent - return KeyboardEvent {..} - --- | Event.target.value --- https://developer.mozilla.org/en-US/docs/Web/API/Event/target --- https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-value -valueDecoder :: MonadIO m => JSVal -> MaybeT m JSString -valueDecoder = - propDecoder "target" >=> propDecoder "value" - --- | Event.target.checked --- https://developer.mozilla.org/en-US/docs/Web/API/Event/target --- https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#checked -checkedDecoder :: MonadIO m => JSVal -> MaybeT m Bool -checkedDecoder = - propDecoder "target" >=> propDecoder "checked" - -propDecoder :: (MonadIO m, FromJSVal v) => String -> JSVal -> MaybeT m v -propDecoder k obj = do - -- TODO: Make sure it is true that if this guard succeeds, - -- Object.getProp will never throw an exception! - guard $ not (isUndefined obj) && not (isNull obj) - MaybeT $ liftIO $ fromJSVal =<< - getProp obj k +-- -- | Read clientX and clientY properties from MouseEvent +-- -- https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent +-- clientXYDecoder :: MonadIO m => JSVal -> MaybeT m (Point Int) +-- clientXYDecoder mouseEvent = do +-- pt_x <- propDecoder "clientX" mouseEvent +-- pt_y <- propDecoder "clientY" mouseEvent +-- return Point {..} + +-- -- | Read offsetX and offsetY properties from MouseEvent +-- -- https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent +-- offsetXYDecoder :: MonadIO m => JSVal -> MaybeT m (Point Int) +-- offsetXYDecoder mouseEvent = do +-- pt_x <- propDecoder "offsetX" mouseEvent +-- pt_y <- propDecoder "offsetY" mouseEvent +-- return Point {..} + +-- -- | Read pageX and pageY properties from MouseEvent +-- -- https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent +-- pageXYDecoder :: MonadIO m => JSVal -> MaybeT m (Point Int) +-- pageXYDecoder mouseEvent = do +-- pt_x <- propDecoder "pageX" mouseEvent +-- pt_y <- propDecoder "pageY" mouseEvent +-- return Point {..} + +-- -- | Collection of altKey, ctrlKey, metaKey and shiftKey properties +-- -- from KeyboardEvent +-- data KeyModifiers = KeyModifiers +-- { kmod_alt_key :: Bool +-- , kmod_ctrl_key :: Bool +-- , kmod_meta_key :: Bool +-- , kmod_shift_key :: Bool +-- } deriving stock (Eq, Show, Generic) + +-- -- | Read altKey, ctrlKey, metaKey and shiftKey properties from +-- -- KeyboardEvent +-- -- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent +-- keyModifiersDecoder :: MonadIO m => JSVal -> MaybeT m KeyModifiers +-- keyModifiersDecoder keyEvent = do +-- kmod_alt_key <- propDecoder "altKey" keyEvent +-- kmod_ctrl_key <- propDecoder "ctrlKey" keyEvent +-- kmod_meta_key <- propDecoder "metaKey" keyEvent +-- kmod_shift_key <- propDecoder "shiftKey" keyEvent +-- return KeyModifiers {..} + +-- -- | Read keyCode properties from KeyboardEvent +-- -- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode +-- keyCodeDecoder :: MonadIO m => JSVal -> MaybeT m Int +-- keyCodeDecoder = propDecoder "keyCode" + +-- -- | Collection of some useful information from KeyboardEvent +-- data KeyboardEvent = KeyboardEvent +-- { ke_modifiers :: KeyModifiers +-- , ke_key :: Maybe JSString +-- , ke_key_code :: Int +-- , ke_repeat :: Bool +-- } deriving stock (Generic) + +-- -- | Read information from KeyboardEvent +-- keyboardEventDecoder :: MonadIO m => JSVal -> MaybeT m KeyboardEvent +-- keyboardEventDecoder keyEvent = do +-- ke_modifiers <- keyModifiersDecoder keyEvent +-- ke_key <- propDecoder "key" keyEvent +-- ke_key_code <- propDecoder "keyCode" keyEvent +-- ke_repeat <- propDecoder "repeat" keyEvent +-- return KeyboardEvent {..} errorGhcjsOnly :: a errorGhcjsOnly = error "Only GHCJS is supported" -#if !defined(javascript_HOST_ARCH) -js_onBeforeUnload :: Callback a -> IO () +#if !defined(wasm32_HOST_ARCH) +js_onBeforeUnload :: JSVal {-Callback a-} -> IO () js_onBeforeUnload = errorGhcjsOnly js_appendChild :: DOMElement -> DOMNode -> IO () = errorGhcjsOnly @@ -292,121 +459,93 @@ js_getCurrentWindow :: IO JSVal = errorGhcjsOnly js_getCurrentDocument :: IO JSVal = errorGhcjsOnly js_getCurrentBody :: IO JSVal = errorGhcjsOnly js_unsafeInsertHtml :: DOMElement -> Nullable DOMNode -> JSString -> IO () = errorGhcjsOnly -js_call0 :: JSVal -> IO JSVal = errorGhcjsOnly -js_call1 :: JSVal -> JSVal -> IO JSVal = errorGhcjsOnly -js_call2 :: JSVal -> JSVal -> JSVal -> IO JSVal = errorGhcjsOnly -js_callMethod0 :: JSVal -> JSString -> IO JSVal = errorGhcjsOnly -js_callMethod1 :: JSVal -> JSString -> JSVal -> IO JSVal = errorGhcjsOnly -js_callMethod2 :: JSVal -> JSString -> JSVal -> JSVal -> IO JSVal = errorGhcjsOnly js_waitDocumentLoad :: IO () = errorGhcjsOnly -js_callbackWithOptions :: Bool -> Bool -> Callback (JSVal -> IO ()) -> IO (Callback (JSVal -> IO ())) = errorGhcjsOnly +js_callbackWithOptions :: Bool -> Bool -> JSVal {-Callback (JSVal -> IO ())-} -> IO JSVal {-(Callback (JSVal -> IO ()))-} = errorGhcjsOnly js_setProp :: JSVal -> JSString -> JSVal -> IO () = errorGhcjsOnly +js_dynExport1 :: (JSVal -> IO ()) -> IO JSVal = errorGhcjsOnly +js_addEventListener :: JSVal -> JSVal -> JSVal -> IO () = errorGhcjsOnly +js_removeEventListener :: JSVal -> JSVal -> JSVal -> IO () = errorGhcjsOnly + #else foreign import javascript unsafe - "(($1, $2) => $1.appendChild($2))" + "$1.appendChild($2)" js_appendChild :: DOMElement -> DOMNode -> IO () foreign import javascript unsafe - "(($1, $2, $3) => $1.insertBefore($2, $3))" + "$1.insertBefore($2, $3)" js_insertBefore :: DOMElement -> DOMNode -> DOMNode -> IO () foreign import javascript unsafe - "(($1, $2, $3) => $1.setAttribute($2, $3))" + "$1.setAttribute($2, $3)" js_setAttribute :: DOMElement -> JSString -> JSString -> IO () foreign import javascript unsafe - "(($1, $2) => $1.removeAttribute($2))" + "$1.removeAttribute($2)" js_removeAttribute :: DOMElement -> JSString -> IO () foreign import javascript unsafe - "(($1, $2) => $1.removeChild($2))" + "$1.removeChild($2)" js_removeChild :: DOMElement -> DOMNode -> IO () foreign import javascript unsafe - "(($1, $2, $3) => $1.replaceChild($2, $3))" + "$1.replaceChild($2, $3)" js_replaceChild :: DOMElement -> DOMNode -> DOMNode -> IO () foreign import javascript unsafe - "(($1) => document.createElement($1))" + "document.createElement($1)" js_createElement :: JSString -> IO DOMElement foreign import javascript unsafe - "(($1, $2) => document.createElementNS($1, $2))" + "document.createElementNS($1, $2)" js_createElementNS :: JSString -> JSString -> IO DOMElement foreign import javascript unsafe - "(($1) => document.createTextNode($1))" + "document.createTextNode($1)" js_createTextNode :: JSString -> IO DOMNode foreign import javascript unsafe - "(($1) => document.createComment($1))" + "document.createComment($1)" js_createComment :: JSString -> IO DOMNode foreign import javascript unsafe - "(($1, $2) => $1.classList.add($2))" + "$1.classList.add($2);" js_classListAdd :: DOMElement -> JSString -> IO () foreign import javascript unsafe - "(($1, $2) => $1.classList.remove($2))" + "$1.classList.remove($2);" js_classListRemove :: DOMElement -> JSString -> IO () foreign import javascript unsafe - "(($1, $2) => { $1.nodeValue = $2; })" + "$1.nodeValue = $2;" js_setTextValue :: DOMNode -> JSString -> IO () +foreign import javascript safe + "window.addEventListener('beforeunload', $1)" + js_onBeforeUnload :: JSVal -> IO () foreign import javascript unsafe - "(($1) => window.addEventListener('beforeunload', $1))" - js_onBeforeUnload :: Callback a -> IO () -foreign import javascript unsafe - "(function(){ return window; })" + "return window" js_getCurrentWindow :: IO JSVal foreign import javascript unsafe - "(function(){ return window.document; })" + "window.document" js_getCurrentDocument :: IO JSVal foreign import javascript unsafe - "(function(){ return window.document.body; })" + "window.document.body" js_getCurrentBody :: IO JSVal foreign import javascript unsafe - "(function (begin, end) {\ - for (;;){\ - if (!end.previousSibling\ - || !end.previousSibling.parentNode\ - || end.previousSibling === begin\ - ) break;\ - end.previousSibling.parentNode.removeChild(end.previousSibling);\ - }\ - })" + "for (;;){\ + if (!$2.previousSibling\ + || !$2.previousSibling.parentNode\ + || $2.previousSibling === $1\ + ) break;\ + $2.previousSibling.parentNode.removeChild($2.previousSibling);\ + }" js_clearBoundary :: DOMNode -> DOMNode -> IO () foreign import javascript unsafe - "(function (begin, end) {\ - if (begin.parentNode) begin.parentNode.removeChild(begin);\ - if (end.parentNode) end.parentNode.removeChild(end);\ - })" + "if ($1.parentNode) $1.parentNode.removeChild($1);\ + if ($2.parentNode) $2.parentNode.removeChild($2);" js_detachBoundary :: DOMNode -> DOMNode -> IO () -foreign import javascript unsafe "(($1) => $1())" - js_call0 :: JSVal -> IO JSVal -foreign import javascript unsafe "(($1, $2) => $1($2))" - js_call1 :: JSVal -> JSVal -> IO JSVal -foreign import javascript unsafe "(($1, $2, $3) => $1($2, $3))" - js_call2 :: JSVal -> JSVal -> JSVal -> IO JSVal -foreign import javascript unsafe "(($1, $2) => $1[$2]())" - js_callMethod0 :: JSVal -> JSString -> IO JSVal -foreign import javascript unsafe "(($1, $2, $3) => $1[$2]($3))" - js_callMethod1 :: JSVal -> JSString -> JSVal -> IO JSVal -foreign import javascript unsafe "(($1, $2, $3, $4) => $1[$2]($3, $4))" - js_callMethod2 :: JSVal -> JSString -> JSVal -> JSVal -> IO JSVal foreign import javascript unsafe - "(function(el, anchor, htmlString){\ - var div = document.createElement('div');\ - div.innerHTML = htmlString;\ - var tempChilds = [];\ - for (var i = 0; i < div.childNodes.length; i++) {\ - tempChilds.push(div.childNodes[i]);\ - }\ - for (var j = 0; j < tempChilds.length; j++) {\ - div.removeChild(tempChilds[j]);\ - if (anchor) {\ - el.insertBefore(tempChilds[j], anchor);\ - } else{\ - el.appendChild(tempChilds[j]);\ - }\ - }\ - })" + "div.innerHTML = $3;\ + var tempChilds = [];\ + for (var i = 0; i < div.childNodes.length; i++) {\ + tempChilds.push(div.childNodes[i]);\ + }\ + for (var j = 0; j < tempChilds.length; j++) {\ + div.removeChild(tempChilds[j]);\ + if ($2) {\ + $1.insertBefore(tempChilds[j], $2);\ + } else{\ + $1.appendChild(tempChilds[j]);\ + }\ + }" js_unsafeInsertHtml :: DOMElement -> Nullable DOMNode -> JSString -> IO () -foreign import javascript unsafe - "(($1, $2, $3) => function(e) {\ - if ($1) e.stopPropagation();\ - if ($2) e.preventDefault();\ - return $3(e);\ - })" - js_callbackWithOptions :: Bool -> Bool -> Callback (JSVal -> IO ()) -> IO (Callback (JSVal -> IO ())) foreign import javascript interruptible "if (document.readyState == 'loading') {\ addEventListener('DOMContentLoaded', $c);\ @@ -415,19 +554,25 @@ foreign import javascript interruptible }" js_waitDocumentLoad :: IO () foreign import javascript unsafe - "(($1, $2, $3) => { $1[$2] = $3; })" + "$1[$2] = $3;" js_setProp :: JSVal -> JSString -> JSVal -> IO () -foreign import javascript unsafe "(() => null)" - js_null :: JSVal +foreign import javascript "wrapper" + js_dynExport1 :: (JSVal -> IO ()) -> IO JSVal +foreign import javascript safe + "$1.addEventListener($2, $3)" + js_addEventListener :: JSVal -> JSVal -> JSVal -> IO () +foreign import javascript safe + "$1.removeEventListener($2, $3)" + js_removeEventListener :: JSVal -> JSVal -> JSVal -> IO () #endif instance (a ~ (), MonadIO m) => IsString (HtmlT m a) where fromString s = do HtmlEnv{html_current_element, html_content_boundary} <- ask let jsstr = toJSString s - textNode <- liftIO $ createTextNode (JSS.fromJSValPure jsstr) + textNode <- liftIO $ createTextNode jsstr case html_content_boundary of - Just ContentBoundary{boundary_end} -> liftIO $ - js_insertBefore html_current_element textNode boundary_end + Just b -> liftIO $ + js_insertBefore html_current_element textNode b.boundary_end Nothing -> liftIO $ appendChild html_current_element textNode {-# INLINE fromString #-} diff --git a/src/HtmlT/Element.hs b/src/HtmlT/Element.hs index c570c39..b49e7f6 100644 --- a/src/HtmlT/Element.hs +++ b/src/HtmlT/Element.hs @@ -5,7 +5,7 @@ module HtmlT.Element where import HtmlT.Base import HtmlT.Types -import JavaScript.Compat.String (JSString(..)) +import Wasm.Compat.Prim -- | This typeclass allows for tag constructors to have variable -- length arguments. Each tag constructor like 'div_' defined below diff --git a/src/HtmlT/Internal.hs b/src/HtmlT/Internal.hs index 5bbde7e..f04e17f 100644 --- a/src/HtmlT/Internal.hs +++ b/src/HtmlT/Internal.hs @@ -2,6 +2,7 @@ module HtmlT.Internal where import Control.Monad.Reader import GHC.Generics +import Wasm.Compat.Prim import HtmlT.Event import HtmlT.Types @@ -28,16 +29,16 @@ insertNode n = do rootEl <- asks html_current_element boundary <- asks html_content_boundary case boundary of - Just ContentBoundary{..} -> liftIO $ - js_insertBefore rootEl n boundary_end + Just b -> liftIO $ + js_insertBefore rootEl n b.boundary_end Nothing -> liftIO $ appendChild rootEl n -- | Insert two DOM Comment nodes intended to be used as a boundary for -- dynamic content. insertBoundary :: MonadIO m => HtmlT m ContentBoundary insertBoundary = do - boundary_begin <- liftIO $ createComment "ContentBoundary {{" - boundary_end <- liftIO $ createComment "}}" + boundary_begin <- liftIO $ createComment $ toJSString "ContentBoundary {{" + boundary_end <- liftIO $ createComment $ toJSString "}}" insertNode boundary_begin insertNode boundary_end - return ContentBoundary{..} + return ContentBoundary {boundary_begin, boundary_end} diff --git a/src/HtmlT/Main.hs b/src/HtmlT/Main.hs index 2a00634..ccee798 100644 --- a/src/HtmlT/Main.hs +++ b/src/HtmlT/Main.hs @@ -4,6 +4,7 @@ module HtmlT.Main where import Control.Monad import Data.IORef import GHC.Generics +import Wasm.Compat.Prim import HtmlT.DOM import HtmlT.Event @@ -39,8 +40,8 @@ attachOptions StartOpts{..} render = mdo -- TODO: doesn't work with javascript-backend -- when startopts_wait_document_load -- js_waitDocumentLoad - begin <- createComment "ContentBoundary {{" - end <- createComment "}}" + begin <- createComment $ toJSString "ContentBoundary {{" + end <- createComment $ toJSString "}}" appendChild startopts_root_element begin appendChild startopts_root_element end let @@ -71,8 +72,7 @@ attachToBody html = do -- | Run finalizers and detach created elements from the DOM detach :: RunningApp -> IO () -detach RunningApp{..} = do - finalizers <- readIORef . renv_finalizers . html_reactive_env $ - runapp_html_env - applyFinalizer (html_reactive_env runapp_html_env) finalizers - removeBoundary runapp_boundary +detach app = do + finalizers <- readIORef app.runapp_html_env.html_reactive_env.renv_finalizers + applyFinalizer app.runapp_html_env.html_reactive_env finalizers + removeBoundary app.runapp_boundary diff --git a/src/HtmlT/Property.hs b/src/HtmlT/Property.hs index 67860e5..2152a96 100644 --- a/src/HtmlT/Property.hs +++ b/src/HtmlT/Property.hs @@ -6,7 +6,7 @@ module HtmlT.Property where import HtmlT.Base import HtmlT.Event import HtmlT.Types -import JavaScript.Compat.String (JSString(..)) +import Wasm.Compat.Prim -- TODO: Real-world usage has demonstrated that 'dynStyles' not diff --git a/src/HtmlT/Types.hs b/src/HtmlT/Types.hs index 7fce8a2..d53e64c 100644 --- a/src/HtmlT/Types.hs +++ b/src/HtmlT/Types.hs @@ -8,13 +8,14 @@ import GHC.Generics import HtmlT.Event import Control.Monad.Fix -import JavaScript.Compat.Prim -import JavaScript.Compat.String (JSString(..)) +import Wasm.Compat.Prim -- | HtmlT is nothing more than just a newtype over ReaderT HtmlEnv newtype HtmlT m a = HtmlT {unHtmlT :: ReaderT HtmlEnv m a} - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader HtmlEnv - , MonadFix, MonadCatch, MonadThrow, MonadMask, MonadTrans) + deriving newtype ( + Functor, Applicative, Monad, MonadIO, MonadReader HtmlEnv, + MonadFix, MonadCatch, MonadThrow, MonadMask, MonadTrans + ) data HtmlEnv = HtmlEnv { html_current_element :: DOMElement @@ -45,7 +46,8 @@ newtype DOMEvent = DOMEvent {unDOMEvent :: JSVal} -- | See https://developer.mozilla.org/en-US/docs/Web/Events for -- reference, what events are supported by particular elements newtype EventName = EventName {unEventName :: JSString} - deriving newtype IsString + +instance IsString EventName where fromString = EventName . toJSString -- | Two comment nodes that define a boundary and a placeholder to -- insert additional nodes within the DOM. diff --git a/src/JavaScript/Compat/Foreign/Callback.hs b/src/JavaScript/Compat/Foreign/Callback.hs deleted file mode 100644 index 950f314..0000000 --- a/src/JavaScript/Compat/Foreign/Callback.hs +++ /dev/null @@ -1,135 +0,0 @@ -{-# LANGUAGE CPP #-} -#if defined(javascript_HOST_ARCH) -module JavaScript.Compat.Foreign.Callback - ( module GHC.JS.Foreign.Callback - ) where - -import GHC.JS.Foreign.Callback -#else - -module JavaScript.Compat.Foreign.Callback - ( Callback - , OnBlocked(..) - , releaseCallback - -- * asynchronous callbacks - , asyncCallback - , asyncCallback1 - , asyncCallback2 - , asyncCallback3 - -- * synchronous callbacks - , syncCallback - , syncCallback1 - , syncCallback2 - , syncCallback3 - -- * synchronous callbacks that return a value - , syncCallback' - , syncCallback1' - , syncCallback2' - , syncCallback3' - ) where - -import JavaScript.Compat.Prim - -data OnBlocked = ContinueAsync | ThrowWouldBlock deriving (Eq) - -data Callback a - -{- | - When you create a callback, the Haskell runtime stores a reference to - the exported IO action or function. This means that all data referenced by the - exported value stays in memory, even if nothing outside the Haskell runtime - holds a reference to to callback. - Use 'releaseCallback' to free the reference. Subsequent calls from JavaScript - to the callback will result in an exception. - -} -releaseCallback :: Callback a -> IO () -releaseCallback = undefined - -{- | Make a callback (JavaScript function) that runs the supplied IO action in a synchronous - thread when called. - Call 'releaseCallback' when done with the callback, freeing memory referenced - by the IO action. - -} -syncCallback :: OnBlocked -- ^ what to do when the thread blocks - -> IO () -- ^ the Haskell action - -> IO (Callback (IO ())) -- ^ the callback -syncCallback = undefined - - -{- | Make a callback (JavaScript function) that runs the supplied IO function in a synchronous - thread when called. The callback takes one argument that it passes as a JSVal value to - the Haskell function. - Call 'releaseCallback' when done with the callback, freeing data referenced - by the function. - -} -syncCallback1 :: OnBlocked -- ^ what to do when the thread blocks - -> (JSVal -> IO ()) -- ^ the Haskell function - -> IO (Callback (JSVal -> IO ())) -- ^ the callback -syncCallback1 = undefined - - -{- | Make a callback (JavaScript function) that runs the supplied IO function in a synchronous - thread when called. The callback takes two arguments that it passes as JSVal values to - the Haskell function. - Call 'releaseCallback' when done with the callback, freeing data referenced - by the function. - -} -syncCallback2 :: OnBlocked -- ^ what to do when the thread blocks - -> (JSVal -> JSVal -> IO ()) -- ^ the Haskell function - -> IO (Callback (JSVal -> JSVal -> IO ())) -- ^ the callback -syncCallback2 = undefined - -{- | Make a callback (JavaScript function) that runs the supplied IO function in a synchronous - thread when called. The callback takes three arguments that it passes as JSVal values to - the Haskell function. - Call 'releaseCallback' when done with the callback, freeing data referenced - by the function. - -} -syncCallback3 :: OnBlocked -- ^ what to do when the thread blocks - -> (JSVal -> JSVal -> JSVal -> IO ()) -- ^ the Haskell function - -> IO (Callback (JSVal -> JSVal -> JSVal -> IO ())) -- ^ the callback -syncCallback3 = undefined - -{- | Make a callback (JavaScript function) that runs the supplied IO action in a synchronous - thread when called. - Call 'releaseCallback' when done with the callback, freeing memory referenced - by the IO action. - -} -syncCallback' :: IO JSVal - -> IO (Callback (IO JSVal)) -syncCallback' = undefined - -syncCallback1' :: (JSVal -> IO JSVal) - -> IO (Callback (JSVal -> IO JSVal)) -syncCallback1' = undefined - -syncCallback2' :: (JSVal -> JSVal -> IO JSVal) - -> IO (Callback (JSVal -> JSVal -> IO JSVal)) -syncCallback2' = undefined - -syncCallback3' :: (JSVal -> JSVal -> JSVal -> IO JSVal) - -> IO (Callback (JSVal -> JSVal -> JSVal -> IO JSVal)) -syncCallback3' = undefined - -{- | Make a callback (JavaScript function) that runs the supplied IO action in an asynchronous - thread when called. - Call 'releaseCallback' when done with the callback, freeing data referenced - by the IO action. - -} -asyncCallback :: IO () -- ^ the action that the callback runs - -> IO (Callback (IO ())) -- ^ the callback -asyncCallback = undefined - -asyncCallback1 :: (JSVal -> IO ()) -- ^ the function that the callback calls - -> IO (Callback (JSVal -> IO ())) -- ^ the calback -asyncCallback1 = undefined - -asyncCallback2 :: (JSVal -> JSVal -> IO ()) -- ^ the Haskell function that the callback calls - -> IO (Callback (JSVal -> JSVal -> IO ())) -- ^ the callback -asyncCallback2 = undefined - -asyncCallback3 :: (JSVal -> JSVal -> JSVal -> IO ()) -- ^ the Haskell function that the callback calls - -> IO (Callback (JSVal -> JSVal -> JSVal -> IO ())) -- ^ the callback -asyncCallback3 = undefined - -#endif diff --git a/src/JavaScript/Compat/Marshal.hs b/src/JavaScript/Compat/Marshal.hs deleted file mode 100644 index a655697..0000000 --- a/src/JavaScript/Compat/Marshal.hs +++ /dev/null @@ -1,91 +0,0 @@ -{-| -Implement the missing functionality, which is likely to be included in -the standard library at some point in the future. --} -{-# LANGUAGE CPP #-} -{-# LANGUAGE ForeignFunctionInterface #-} -{-# LANGUAGE JavaScriptFFI #-} -module JavaScript.Compat.Marshal where - -import Data.Bool -import Data.Coerce -import Data.Maybe -import JavaScript.Compat.Prim -import JavaScript.Compat.String -import Unsafe.Coerce - -newtype Nullable v = Nullable {unNullable :: JSVal} - -nullableToMaybe :: Coercible v JSVal => Nullable v -> Maybe v -nullableToMaybe (Nullable jsval) - | isNull jsval = Nothing - | otherwise = Just (coerce jsval) - -maybeToNullable :: Coercible v JSVal => Maybe v -> Nullable v -maybeToNullable = Nullable . maybe jsNull coerce - -class FromJSVal v where fromJSVal :: JSVal -> IO (Maybe v) - -instance FromJSVal Int where - fromJSVal = pure . Just . fromJSInt - -instance FromJSVal JSVal where - fromJSVal = pure . Just - -instance FromJSVal v => FromJSVal (Maybe v) where - fromJSVal j = maybe (pure (Just Nothing)) fromJSVal $ - nullableToMaybe (Nullable j) - -instance FromJSVal v => FromJSVal [v] where - fromJSVal s = fmap (Just . catMaybes) . mapM fromJSVal =<< fromJSArray s - -class ToJSVal v where toJSVal :: v -> IO JSVal - -instance ToJSVal Int where - toJSVal = pure . toJSInt - -instance ToJSVal Bool where - toJSVal = pure . bool js_false js_true - -instance ToJSVal JSVal where - toJSVal = pure - -instance ToJSVal v => ToJSVal (Maybe v) where - toJSVal s = pure . unNullable . maybeToNullable =<< mapM toJSVal s - -instance ToJSVal v => ToJSVal [v] where - toJSVal s = toJSArray =<< mapM toJSVal s - -#if !defined(javascript_HOST_ARCH) -instance FromJSVal JSString where fromJSVal = undefined - -instance ToJSVal JSString where toJSVal = undefined - -instance FromJSVal Bool where fromJSVal = undefined - -js_true :: JSVal = undefined -js_false :: JSVal = undefined -js_isString :: JSVal -> JSVal = undefined -#else - -instance FromJSVal JSString where - fromJSVal jsval = do - let - isString = unsafeCoerce $ - js_bool (unsafeCoerce False) (unsafeCoerce True) (js_isString jsval) - return $ if isString then Just (JSString jsval) else Nothing - -instance ToJSVal JSString where - toJSVal = pure . unJSString - -instance FromJSVal Bool where - fromJSVal = pure . Just . unsafeCoerce . - js_bool (unsafeCoerce False) (unsafeCoerce True) - -foreign import javascript unsafe - "(() => true)" js_true :: JSVal -foreign import javascript unsafe - "(() => false)" js_false :: JSVal -foreign import javascript unsafe - "((s) => typeof s === 'string')" js_isString :: JSVal -> JSVal -#endif diff --git a/src/JavaScript/Compat/Prim.hs b/src/JavaScript/Compat/Prim.hs deleted file mode 100644 index 88ca50c..0000000 --- a/src/JavaScript/Compat/Prim.hs +++ /dev/null @@ -1,177 +0,0 @@ -{-# LANGUAGE CPP #-} -{-# LANGUAGE MagicHash #-} -{-# LANGUAGE DeriveDataTypeable #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE JavaScriptFFI #-} -{-# LANGUAGE GHCForeignImportPrim #-} -{-# LANGUAGE UnliftedFFITypes #-} -{-# LANGUAGE UnboxedTuples #-} - -#if defined(javascript_HOST_ARCH) -module JavaScript.Compat.Prim - ( module GHC.JS.Prim - ) where - -import GHC.JS.Prim -#else - -module JavaScript.Compat.Prim ( JSVal(..), JSVal# - , JSException(..) - , WouldBlockException(..) - , toIO - , resolve - , resolveIO - , mkJSException - , fromJSString - , toJSString - , toJSArray - , fromJSArray - , fromJSInt - , toJSInt - , isNull - , isUndefined - , jsNull - , getProp - , getProp' - , getProp# - , unsafeGetProp - , unsafeGetProp' - , unsafeGetProp# - , unpackJSString# - , unpackJSStringUtf8# - , unsafeUnpackJSString# - , unsafeUnpackJSStringUtf8# - , unpackJSStringUtf8## - , unsafeUnpackJSStringUtf8## - ) where - -import Data.Typeable (Typeable) - -import GHC.Prim -import qualified GHC.Exception as Ex -import qualified GHC.Exts as Exts - -{- - JSVal is a boxed type that can be used as FFI - argument or result. --} - -data JSVal = JSVal Addr# -type JSVal# = Addr# - -{- - When a JavaScript exception is raised inside - a safe or interruptible foreign call, it is converted - to a JSException - -} -data JSException = JSException JSVal String - deriving (Typeable) - -instance Ex.Exception JSException - -instance Show JSException where - show (JSException _ xs) = "JavaScript exception: " ++ xs - -toIO :: Exts.Any -> IO Exts.Any -toIO = undefined - -resolve :: JSVal# -> JSVal# -> Exts.Any -> IO () -resolve = undefined - -resolveIO :: JSVal# -> JSVal# -> IO Exts.Any -> IO () -resolveIO = undefined - -mkJSException :: JSVal -> IO JSException -mkJSException = undefined - -{- | Low-level conversion utilities for packages that cannot - depend on ghcjs-base - -} - -{- | returns an empty string if the JSVal does not contain - a string - -} -fromJSString :: JSVal -> String -fromJSString = undefined - -toJSString :: String -> JSVal -toJSString = undefined - -fromJSArray :: JSVal -> IO [JSVal] -fromJSArray = undefined - -toJSArray :: [JSVal] -> IO JSVal -toJSArray = undefined - -{- | returns zero if the JSVal does not contain a number - -} -fromJSInt :: JSVal -> Int -fromJSInt = undefined - -toJSInt :: Int -> JSVal -toJSInt = undefined - -isNull :: JSVal -> Bool -isNull = undefined - -isUndefined :: JSVal -> Bool -isUndefined = undefined - -jsNull :: JSVal -jsNull = undefined - -getProp :: JSVal -> String -> IO JSVal -getProp = undefined - --- | only safe on immutable object -unsafeGetProp :: JSVal -> String -> JSVal -unsafeGetProp = undefined - -getProp' :: JSVal -> JSVal -> IO JSVal -getProp' = undefined - --- | only safe on immutable object -unsafeGetProp' :: JSVal -> JSVal -> JSVal -unsafeGetProp' = undefined - - --- | only safe on immutable Addr# -getProp# :: JSVal -> Addr# -> IO JSVal -getProp# = undefined - --- | only safe on immutable Addr# and JSVal -unsafeGetProp# :: JSVal -> Addr# -> JSVal -unsafeGetProp# = undefined - -unpackJSString# :: Addr# -> IO JSVal -unpackJSString# = undefined - -unpackJSStringUtf8# :: Addr# -> IO JSVal -unpackJSStringUtf8# = undefined - -unpackJSStringUtf8## :: Addr# -> State# s -> (# State# s, JSVal# #) -unpackJSStringUtf8## = undefined - --- | only safe on immutable Addr# -unsafeUnpackJSString# :: Addr# -> JSVal -unsafeUnpackJSString# = undefined - --- | only safe on immutable Addr# -unsafeUnpackJSStringUtf8# :: Addr# -> JSVal -unsafeUnpackJSStringUtf8# = undefined - -unsafeUnpackJSStringUtf8## :: Addr# -> JSVal# -unsafeUnpackJSStringUtf8## = undefined - -{- | If a synchronous thread tries to do something that can only - be done asynchronously, and the thread is set up to not - continue asynchronously, it receives this exception. - -} -data WouldBlockException = WouldBlockException - deriving (Typeable) - -instance Show WouldBlockException where - show _ = "thread would block" - -instance Ex.Exception WouldBlockException -#endif diff --git a/src/JavaScript/Compat/String.hs b/src/JavaScript/Compat/String.hs deleted file mode 100644 index 5ca61ec..0000000 --- a/src/JavaScript/Compat/String.hs +++ /dev/null @@ -1,16 +0,0 @@ -{-| -Implement the missing functionality, which is likely to be included in -the standard library at some point in the future. --} -{-# LANGUAGE CPP #-} -#if defined(javascript_HOST_ARCH) -module JavaScript.Compat.String - ( module JavaScript.Compat.String.JavaScript - ) where -import JavaScript.Compat.String.JavaScript -#else -module JavaScript.Compat.String - ( module JavaScript.Compat.String.Native - ) where -import JavaScript.Compat.String.Native -#endif diff --git a/src/JavaScript/Compat/String/JavaScript.hs b/src/JavaScript/Compat/String/JavaScript.hs deleted file mode 100644 index 5d8a3b7..0000000 --- a/src/JavaScript/Compat/String/JavaScript.hs +++ /dev/null @@ -1,207 +0,0 @@ -{-# LANGUAGE CPP #-} -{-# LANGUAGE ForeignFunctionInterface #-} -{-# LANGUAGE JavaScriptFFI #-} -module JavaScript.Compat.String.JavaScript where - -import GHC.Exts as Exts -import JavaScript.Compat.Prim -import System.IO.Unsafe -import Unsafe.Coerce - -newtype JSString = JSString {unJSString :: JSVal} - -toJSValPure :: JSString -> JSVal -toJSValPure = unJSString - -fromJSValPure :: JSVal -> JSString -fromJSValPure = JSString - -instance Show JSString where - show = show . unpack - {-# INLINE show #-} - -instance Eq JSString where - (==) (JSString a) (JSString b) = unsafeCoerce $ - js_stringEq a b (unsafeCoerce True) (unsafeCoerce False) - {-# INLINE (==) #-} - -instance Ord JSString where - -- TODO: Could be made way faster once implemented in JavaScript - compare a b = unpack a `compare` unpack b - -instance IsString JSString where - fromString = JSString . toJSString - {-# INLINE fromString #-} - -instance Semigroup JSString where - (<>) = append - {-# INLINE (<>) #-} - -instance Monoid JSString where - mempty = empty - {-# INLINE mempty #-} - -empty :: JSString -empty = "" -{-# NOINLINE empty #-} - -pack :: String -> JSString -pack = JSString . toJSString -{-# INLINE pack #-} - -unpack :: JSString -> String -unpack = fromJSString . unJSString -{-# INLINE unpack #-} - -strip :: JSString -> JSString -strip = JSString . js_strip . unJSString -{-# INLINE strip #-} - -append :: JSString -> JSString -> JSString -append (JSString a) (JSString b) = JSString (js_append a b) -{-# INLINE append #-} - -stripPrefix :: JSString -> JSString -> Maybe JSString -stripPrefix (JSString str) (JSString prefix) = - let - jsVal = js_stripPrefix str prefix - in - if isUndefined jsVal then Nothing else Just (JSString jsVal) -{-# INLINE stripPrefix #-} - -breakOn :: JSString -> JSString -> (JSString, JSString) -breakOn (JSString sep) (JSString str) = - let - jsTuple = js_breakOn sep str - in - ( JSString (js_unsafeIndex 0 jsTuple) - , JSString (js_unsafeIndex 1 jsTuple) - ) -{-# INLINE breakOn #-} - -splitOn :: JSString -> JSString -> [JSString] -splitOn (JSString sep) (JSString str) = fmap JSString $ unsafePerformIO $ - fromJSArray (js_splitOn sep str) -{-# NOINLINE splitOn #-} - -intercalate :: JSString -> [JSString] -> JSString -intercalate (JSString sep) list = - let - jsList = unsafePerformIO $ toJSArray (fmap unJSString list) - in - JSString $ js_intercalate sep jsList -{-# NOINLINE intercalate #-} - -drop :: Int -> JSString -> JSString -drop n (JSString str) = JSString $ js_drop n str -{-# INLINE drop #-} - -take :: Int -> JSString -> JSString -take n (JSString str) = JSString $ js_take n str -{-# INLINE take #-} - -encodeURIComponent :: JSString -> JSString -encodeURIComponent = - JSString . js_encodeURIComponent . unJSString -{-# INLINE encodeURIComponent #-} - -decodeURIComponent :: JSString -> JSString -decodeURIComponent = - JSString . js_decodeURIComponent . unJSString -{-# INLINE decodeURIComponent #-} - -toLower :: JSString -> JSString -toLower = JSString . js_toLower . unJSString -{-# INLINE toLower #-} - -toUpper :: JSString -> JSString -toUpper = JSString . js_toUpper . unJSString -{-# INLINE toUpper #-} - -isInfixOf :: JSString -> JSString -> Bool -isInfixOf (JSString substr) (JSString str) = - unsafeCoerce $ js_bool (unsafeCoerce False) (unsafeCoerce True) (js_isInfixOf substr str) -{-# INLINE isInfixOf #-} - -null :: JSString -> Bool -null = (==empty) -{-# INLINE null #-} - -#if !defined(javascript_HOST_ARCH) -js_stringEq :: JSVal -> JSVal -> Exts.Any -> Exts.Any -> Exts.Any = undefined -js_strip :: JSVal -> JSVal = undefined -js_append :: JSVal -> JSVal -> JSVal = undefined -js_stripPrefix :: JSVal -> JSVal -> JSVal = undefined -js_splitOn :: JSVal-> JSVal -> JSVal = undefined -js_breakOn :: JSVal-> JSVal -> JSVal = undefined -js_unsafeIndex :: Int -> JSVal -> JSVal = undefined -js_intercalate :: JSVal -> JSVal -> JSVal = undefined -js_drop :: Int -> JSVal -> JSVal = undefined -js_take :: Int -> JSVal -> JSVal = undefined -js_encodeURIComponent :: JSVal -> JSVal = undefined -js_decodeURIComponent :: JSVal -> JSVal = undefined -js_toLower :: JSVal -> JSVal = undefined -js_toUpper :: JSVal -> JSVal = undefined -js_isInfixOf :: JSVal -> JSVal -> JSVal = undefined -js_bool :: Exts.Any -> Exts.Any -> JSVal -> Exts.Any = undefined -#else -foreign import javascript unsafe - "((lhs, rhs, ifeq, ifneq) => lhs == rhs ? ifeq : ifneq)" - js_stringEq :: JSVal -> JSVal -> Exts.Any -> Exts.Any -> Exts.Any -foreign import javascript unsafe - "((str) => str.replace(/^\\s+|\\s+$/g, ''))" - js_strip :: JSVal -> JSVal -foreign import javascript unsafe - "((a, b) => a + b)" - js_append :: JSVal -> JSVal -> JSVal -foreign import javascript unsafe - "((prefix, str) => {\ - if (str.startsWith(prefix)) {\ - return str.slice(prefix.length);\ - }\ - return undefined;\ - })" - js_stripPrefix :: JSVal -> JSVal -> JSVal -foreign import javascript unsafe - "((sep, str) => str.split(sep))" - js_splitOn :: JSVal -> JSVal -> JSVal -foreign import javascript unsafe - "((sep, str) => {\ - var index = str.indexOf(sep);\ - if (index !== -1) {\ - return [str.slice(0, index), str.slice(index)];\ - }\ - return [str, ''];\ - })" - js_breakOn :: JSVal -> JSVal -> JSVal -foreign import javascript unsafe - "((i, arr) => arr[i])" - js_unsafeIndex :: Int -> JSVal -> JSVal -foreign import javascript unsafe - "((sep, list) => list.join(sep))" - js_intercalate :: JSVal -> JSVal -> JSVal -foreign import javascript unsafe - "((n, str) => str.slice(n))" - js_drop :: Int -> JSVal -> JSVal -foreign import javascript unsafe - "((n, str) => str.slice(0, n))" - js_take :: Int -> JSVal -> JSVal -foreign import javascript unsafe - "encodeURIComponent" - js_encodeURIComponent :: JSVal -> JSVal -foreign import javascript unsafe - "decodeURIComponent" - js_decodeURIComponent :: JSVal -> JSVal -foreign import javascript unsafe - "((s) => s.toLowerCase())" - js_toLower :: JSVal -> JSVal -foreign import javascript unsafe - "((s) => s.toUpperCase())" - js_toUpper :: JSVal -> JSVal -foreign import javascript unsafe - "((substr, str) => str.includes(substr))" - js_isInfixOf :: JSVal -> JSVal -> JSVal -foreign import javascript unsafe - "((iffalse, iftrue, jsbool) => jsbool ? iftrue : iffalse)" - js_bool :: Exts.Any -> Exts.Any -> JSVal -> Exts.Any -#endif diff --git a/src/JavaScript/Compat/String/Native.hs b/src/JavaScript/Compat/String/Native.hs deleted file mode 100644 index fc6583b..0000000 --- a/src/JavaScript/Compat/String/Native.hs +++ /dev/null @@ -1,115 +0,0 @@ -module JavaScript.Compat.String.Native where - -import Data.Char qualified as C -import Data.Text (Text) -import Data.Text qualified as T -import GHC.Exts as Exts -import JavaScript.Compat.Prim - -newtype JSString = JSString {unJSString :: Text} - deriving newtype (Eq, Ord, Show, IsString, Semigroup, Monoid) - -toJSValPure :: JSString -> JSVal -toJSValPure = undefined - -fromJSValPure :: JSVal -> JSString -fromJSValPure = undefined - -empty :: JSString -empty = JSString T.empty -{-# INLINE empty #-} - -pack :: String -> JSString -pack = JSString . T.pack -{-# INLINE pack #-} - -unpack :: JSString -> String -unpack = T.unpack . unJSString -{-# INLINE unpack #-} - -strip :: JSString -> JSString -strip = JSString . T.strip . unJSString -{-# INLINE strip #-} - -append :: JSString -> JSString -> JSString -append (JSString a) (JSString b) = JSString $ T.append a b -{-# INLINE append #-} - -stripPrefix :: JSString -> JSString -> Maybe JSString -stripPrefix (JSString a) (JSString b) = - JSString <$> T.stripPrefix a b -{-# INLINE stripPrefix #-} - -breakOn :: JSString -> JSString -> (JSString, JSString) -breakOn (JSString a) (JSString b) = - let (c, d) = T.breakOn a b in (JSString c, JSString d) -{-# INLINE breakOn #-} - -splitOn :: JSString -> JSString -> [JSString] -splitOn (JSString a) (JSString b) = fmap JSString $ T.splitOn a b -{-# NOINLINE splitOn #-} - -intercalate :: JSString -> [JSString] -> JSString -intercalate (JSString s) l = JSString $ T.intercalate s $ fmap unJSString l -{-# INLINE intercalate #-} - -drop :: Int -> JSString -> JSString -drop n (JSString s) = JSString $ T.drop n s -{-# INLINE drop #-} - -take :: Int -> JSString -> JSString -take n (JSString s) = JSString $ T.take n s -{-# INLINE take #-} - -encodeURIComponent :: JSString -> JSString -encodeURIComponent = - JSString . T.pack . concatMap encodeChar . T.unpack . unJSString - where - encodeChar c - | C.isAlphaNum c = [c] - | c == ' ' = "+" - | otherwise = '%' : showHex (C.ord c) "" - -decodeURIComponent :: JSString -> JSString -decodeURIComponent = JSString . T.pack . decode . T.unpack . unJSString - where - decode [] = [] - decode ('%':x1:x2:xs) - | C.isHexDigit x1 && C.isHexDigit x2 = - C.chr (16 * digitToInt x1 + digitToInt x2) : decode xs - decode ('+':xs) = ' ' : decode xs - decode (x:xs) = x : decode xs - -showHex :: Int -> String -> String -showHex n acc - | n < 16 = intToDigit n : acc - | otherwise = let (q,r) = n `divMod` 16 in showHex q (intToDigit r : acc) - -digitToInt :: Char -> Int -digitToInt c - | '0' <= c && c <= '9' = fromEnum c - fromEnum '0' - | 'a' <= c && c <= 'f' = fromEnum c - fromEnum 'a' + 10 - | 'A' <= c && c <= 'F' = fromEnum c - fromEnum 'A' + 10 - | otherwise = error "digitToInt: not a digit" - -intToDigit :: Int -> Char -intToDigit n - | 0 <= n && n <= 9 = toEnum (fromEnum '0' + n) - | 10 <= n && n <= 15 = toEnum (fromEnum 'a' + n - 10) - | otherwise = error "intToDigit: not a digit" - -toLower :: JSString -> JSString -toLower = JSString . T.toLower . unJSString -{-# INLINE toLower #-} - -toUpper :: JSString -> JSString -toUpper = JSString . T.toUpper . unJSString -{-# INLINE toUpper #-} - -isInfixOf :: JSString -> JSString -> Bool -isInfixOf (JSString a) (JSString b) = T.isInfixOf a b -{-# INLINE isInfixOf #-} - -null :: JSString -> Bool -null = T.null . unJSString -{-# INLINE null #-} diff --git a/src/Wasm/Compat/Marshal.hs b/src/Wasm/Compat/Marshal.hs new file mode 100644 index 0000000..59c6347 --- /dev/null +++ b/src/Wasm/Compat/Marshal.hs @@ -0,0 +1,167 @@ +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE ForeignFunctionInterface #-} +{-# LANGUAGE JavaScriptFFI #-} +module Wasm.Compat.Marshal where + +import Control.Monad +import Data.Maybe +import Data.String +import Data.Coerce +import Wasm.Compat.Prim + +newtype Nullable v = Nullable {unNullable :: JSVal} + +nullableToMaybe :: Coercible v JSVal => Nullable v -> Maybe v +nullableToMaybe (Nullable j) + | js_isNull j > 0 = Nothing + | otherwise = Just (coerce j) + +maybeToNullable :: Coercible v JSVal => Maybe v -> Nullable v +maybeToNullable = Nullable . maybe js_null coerce + +newtype TypeResult = TypeResult {unTypeResult :: Int} + +pattern TypeNull, TypeBool, TypeNumber, TypeString, TypeArray, TypeObject :: TypeResult +pattern TypeNull = TypeResult 0 +pattern TypeBool = TypeResult 1 +pattern TypeNumber = TypeResult 2 +pattern TypeString = TypeResult 3 +pattern TypeArray = TypeResult 4 +pattern TypeObject = TypeResult 5 + +class FromJSVal v where fromJSVal :: JSVal -> IO (Maybe v) + +class FromJSValPure v where fromJSValPure :: JSVal -> Maybe v + +instance {-# OVERLAPS #-} FromJSValPure v => FromJSVal v where + fromJSVal = pure . fromJSValPure + +instance FromJSValPure Int where + fromJSValPure j = case js_typeOf j of + TypeNumber -> Just (js_unsafeInt j) + _ -> Nothing + +instance FromJSValPure v => FromJSValPure (Maybe v) where + fromJSValPure j + = maybe (Just Nothing) fromJSValPure + $ nullableToMaybe (Nullable j) + +instance FromJSValPure JSVal where fromJSValPure = Just + +instance FromJSValPure JSString where + fromJSValPure j = case js_typeOf j of + TypeString -> Just (JSString j) + _ -> Nothing + +instance FromJSValPure Bool where + fromJSValPure j = case js_typeOf j of + TypeBool -> Just (js_unsafeBool j) + _ -> Nothing + +instance FromJSVal v => FromJSVal [v] where + fromJSVal s = case js_typeOf s of + TypeArray -> do + len <- js_arrayLength s + xs <- forM [0..(len - 1)] $ fromJSVal <=< js_arrayIndex s + return $ Just $ catMaybes xs + _ -> return Nothing + +class ToJSVal v where toJSVal :: v -> IO JSVal + +class ToJSValPure v where toJSValPure :: v -> JSVal + +instance {-# OVERLAPS #-} ToJSValPure v => ToJSVal v where + toJSVal = pure . toJSValPure + +instance ToJSValPure Int where toJSValPure = js_intJSVal + +instance ToJSValPure Bool where toJSValPure = js_boolJSVal + +instance ToJSValPure JSVal where toJSValPure j = j + +instance ToJSValPure JSString where toJSValPure (JSString j) = j + +instance ToJSValPure v => ToJSValPure (Maybe v) where + toJSValPure = unNullable . maybeToNullable . fmap toJSValPure + +instance ToJSVal v => ToJSVal [v] where + toJSVal s = do + arr <- js_newEmptyArray + forM_ s $ toJSVal >=> js_arrayPush arr + return arr + +instance IsString JSString where fromString = toJSString + +instance Semigroup JSString where (<>) = js_concatStr + +instance Monoid JSString where mempty = js_emptyStr + +instance Eq JSString where (==) a b = fromJSString a == fromJSString b + +instance Show JSString where show = show . fromJSString + +instance Ord JSString where compare a b = fromJSString a `compare` fromJSString b + +#if !defined(wasm32_HOST_ARCH) + +js_true :: JSVal = undefined +js_false :: JSVal = undefined +js_null :: JSVal = undefined +js_emptyStr :: JSString = undefined +js_isString :: JSVal -> JSVal = undefined +js_isNull :: JSVal -> Int = undefined +js_typeOf :: JSVal -> TypeResult = undefined +js_unsafeInt :: JSVal -> Int = undefined +js_unsafeBool :: JSVal -> Bool = undefined +js_intJSVal :: Int -> JSVal = undefined +js_boolJSVal :: Bool -> JSVal = undefined +js_getProp :: JSVal -> JSString -> IO JSVal = undefined +js_concatStr :: JSString -> JSString -> JSString = undefined +js_newEmptyArray :: IO JSVal = undefined +js_arrayPush :: JSVal -> JSVal -> IO () = undefined +js_arrayLength :: JSVal -> IO Int = undefined +js_arrayIndex :: JSVal -> Int -> IO JSVal = undefined + +#else + +foreign import javascript unsafe + "true" js_true :: JSVal +foreign import javascript unsafe + "false" js_false :: JSVal +foreign import javascript unsafe + "null" js_null :: JSVal +foreign import javascript unsafe + "''" js_emptyStr :: JSString +foreign import javascript unsafe + "typeof $1 === 'string'" js_isString :: JSVal -> JSVal +foreign import javascript unsafe + "($1 === null || $1 === undefined)" js_isNull :: JSVal -> Int +foreign import javascript unsafe + "if ($1 === undefined || $1 === null) return 0;\ + if (typeof $1 === 'boolean') return 1;\ + if (typeof $1 === 'number') return 2;\ + if (typeof $1 === 'string') return 3;\ + if (Array.isArray($1)) return 4;\ + return 5;" js_typeOf :: JSVal -> TypeResult +foreign import javascript unsafe + "$1" js_unsafeInt :: JSVal -> Int +foreign import javascript unsafe + "$1" js_unsafeBool :: JSVal -> Bool +foreign import javascript unsafe + "$1" js_intJSVal :: Int -> JSVal +foreign import javascript unsafe + "($1 ? true : false)" js_boolJSVal :: Bool -> JSVal +foreign import javascript unsafe + "$1[$2]" js_getProp :: JSVal -> JSString -> IO JSVal +foreign import javascript unsafe + "$1 + $2" js_concatStr :: JSString -> JSString -> JSString +foreign import javascript unsafe + "[]" js_newEmptyArray :: IO JSVal +foreign import javascript unsafe + "$1.push($2)" js_arrayPush :: JSVal -> JSVal -> IO () +foreign import javascript unsafe + "$1.length" js_arrayLength :: JSVal -> IO Int +foreign import javascript unsafe + "$1[$2]" js_arrayIndex :: JSVal -> Int -> IO JSVal +#endif diff --git a/src/Wasm/Compat/Prim.hs b/src/Wasm/Compat/Prim.hs new file mode 100644 index 0000000..76af87c --- /dev/null +++ b/src/Wasm/Compat/Prim.hs @@ -0,0 +1,76 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnboxedTuples #-} +{-# LANGUAGE UnliftedNewtypes #-} + +#if defined(wasm32_HOST_ARCH) +module Wasm.Compat.Prim ( + module GHC.Wasm.Prim +) where +import GHC.Wasm.Prim +#else +module Wasm.Compat.Prim ( + JSVal#(..), + JSVal(..), + freeJSVal, + JSString (..), + fromJSString, + toJSString, + JSException (..), + WouldBlockException (..), + PromisePendingException (..), + mkJSCallback, + runIO, + runNonIO, +) where + +import Control.Exception +import GHC.Exts +import GHC.Stable + +newtype JSVal# + = JSVal# (Any :: UnliftedType) + +data JSVal + = forall a . JSVal JSVal# (Weak# JSVal#) (StablePtr# a) + +freeJSVal :: JSVal -> IO () +freeJSVal _ = error "freeJSVal: only implmented on Wasm Backend" + +newtype JSString = JSString JSVal + +fromJSString :: JSString -> String +fromJSString _ = error "fromJSString: only implmented on Wasm Backend" + +toJSString :: String -> JSString +toJSString _ = error "toJSString: only implmented on Wasm Backend" + +newtype JSException = JSException JSVal + +instance Show JSException where + showsPrec _ _ = error "showsPrec @JSException: only implmented on Wasm Backend" + +instance Exception JSException + +data WouldBlockException + = WouldBlockException + deriving (Show) + +instance Exception WouldBlockException + +data PromisePendingException + = PromisePendingException + deriving (Show) + +instance Exception PromisePendingException + +mkJSCallback :: (StablePtr a -> IO JSVal) -> a -> IO JSVal +mkJSCallback _ _ = error "mkJSCallback: only implmented on Wasm Backend" + +runIO :: (JSVal -> a -> IO ()) -> IO a -> IO JSVal +runIO _ _ = error "runIO: only implmented on Wasm Backend" + +runNonIO :: (JSVal -> a -> IO ()) -> a -> IO JSVal +runNonIO _ _ = error "runNonIO: only implmented on Wasm Backend" +#endif diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..cde7f9c --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,13 @@ +const path = require('path'); + +module.exports = { + entry: './jsbits/index.js', + output: { + path: path.resolve(__dirname, 'dist-newstyle'), + filename: 'index.bundle.js', + }, + resolve: { + extensions: ['.ts', '.js'], + }, + devtool: false, +}; From 789401609c4c3f559396c67844cc20d6591f707b Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 13 Mar 2024 19:26:52 +0400 Subject: [PATCH 02/64] Text to JSString conversion --- examples/simple-routing/Assets.hs | 2 +- examples/simple-routing/Pages.hs | 5 +- examples/simple-routing/Router.hs | 6 +- examples/simple-routing/Utils.hs | 36 ++---- examples/simple-routing/prism.externs | 16 --- examples/simple-routing/simple-routing.hs | 8 +- examples/todomvc/TodoItem.hs | 7 +- examples/todomvc/TodoList.hs | 20 +-- examples/todomvc/Utils.hs | 7 +- htmlt.cabal | 7 +- jsbits/jsffi.js | 25 ++-- src/HtmlT/Base.hs | 48 +++---- src/HtmlT/DOM.hs | 115 +++++++++-------- src/HtmlT/Element.hs | 3 +- src/HtmlT/Internal.hs | 4 +- src/HtmlT/Main.hs | 4 +- src/HtmlT/Property.hs | 149 +++++++++++----------- src/Wasm/Compat/Marshal.hs | 49 +++++++ 18 files changed, 283 insertions(+), 228 deletions(-) delete mode 100644 examples/simple-routing/prism.externs diff --git a/examples/simple-routing/Assets.hs b/examples/simple-routing/Assets.hs index 9410daa..09ff0df 100644 --- a/examples/simple-routing/Assets.hs +++ b/examples/simple-routing/Assets.hs @@ -1,7 +1,7 @@ module Assets where import GHC.Generics -import JavaScript.Compat.String (JSString(..)) +import Wasm.Compat.Prim data Country = Country { title :: JSString diff --git a/examples/simple-routing/Pages.hs b/examples/simple-routing/Pages.hs index b4f9af3..40bdb8d 100644 --- a/examples/simple-routing/Pages.hs +++ b/examples/simple-routing/Pages.hs @@ -7,9 +7,8 @@ import Data.List qualified as List import Data.Maybe import Data.Ord import HtmlT -import JavaScript.Compat.Marshal -import JavaScript.Compat.String (JSString) -import JavaScript.Compat.String qualified as JSS +import Wasm.Compat.Marshal +import Wasm.Compat.Prim import "this" Assets import "this" Router diff --git a/examples/simple-routing/Router.hs b/examples/simple-routing/Router.hs index 386e25a..0335e5c 100644 --- a/examples/simple-routing/Router.hs +++ b/examples/simple-routing/Router.hs @@ -7,8 +7,8 @@ import Data.Maybe import Data.Function import GHC.Generics import Text.Read -import JavaScript.Compat.String (JSString(..)) -import JavaScript.Compat.String qualified as JSS +import Wasm.Compat.Prim +import Wasm.Compat.Marshal data UrlParts = Url { partsPath :: [JSString] -- ^ Path segments @@ -68,7 +68,7 @@ parseRoute = \case Just "region" -> SortByRegion Just "subregion" -> SortBySubregion _ -> defaultCountriesListQ.sort_by - parseIntQuery = readMaybe . JSS.unpack + parseIntQuery = readMaybe . fromJSString printRoute :: Route -> UrlParts printRoute = \case diff --git a/examples/simple-routing/Utils.hs b/examples/simple-routing/Utils.hs index bbf873c..9b997b7 100644 --- a/examples/simple-routing/Utils.hs +++ b/examples/simple-routing/Utils.hs @@ -6,26 +6,18 @@ module Utils where import Control.Monad.IO.Class import Data.Coerce import HtmlT -import JavaScript.Compat.Foreign.Callback -import JavaScript.Compat.Marshal -import JavaScript.Compat.Prim -import JavaScript.Compat.String (JSString) -import JavaScript.Compat.String qualified as JSS +import Wasm.Compat.Prim +import Wasm.Compat.Marshal import Unsafe.Coerce mkUrlHashRef :: MonadReactive m => m (DynRef JSString) mkUrlHashRef = do initial <- liftIO js_readUrlHash routeRef <- newRef initial - win <- liftIO getCurrentWindow - popStateCb <- liftIO $ asyncCallback $ + win <- getCurrentWindow + popStateCb <- liftIO $ js_dynExport1 \_ -> js_readUrlHash >>= dynStep . writeRef routeRef - liftIO $ js_callMethod2 (coerce win) "addEventListener" - (JSS.toJSValPure "popstate") (unsafeCoerce popStateCb) - installFinalizer do - js_callMethod2 (coerce win) "removeEventListener" - (JSS.toJSValPure "popstate") (unsafeCoerce popStateCb) - releaseCallback popStateCb + liftIO $ js_addEventListener win ((\(JSString j) -> j) $ toJSString "onpopstate") popStateCb return routeRef pushUrl :: MonadIO m => JSString -> m () @@ -37,7 +29,7 @@ highlightHaskell = js_highlightHaskell insertScript :: JSString -> IO () insertScript = js_insertScript -#if defined(javascript_HOST_ARCH) +#if defined(wasm32_HOST_ARCH) foreign import javascript unsafe "(function(el, code){\ if (!code) return;\ @@ -47,7 +39,7 @@ foreign import javascript unsafe svgPaths[i].classList.add('selected');\ }\ svgGroup.parentElement.appendChild(svgGroup);\ - })" + })($1,$2)" js_selectCountry :: DOMElement -> Nullable JSVal -> IO () foreign import javascript unsafe @@ -60,11 +52,11 @@ foreign import javascript unsafe iter = iter.parentNode;\ }\ return null;\ - })" + })($1)" js_svgClickGetCountryCode :: DOMEvent -> IO (Nullable JSVal) foreign import javascript unsafe - "((s) => Prism.highlight(s, Prism.languages.haskell, 'haskell'))" + "Prism.highlight($1, Prism.languages.haskell, 'haskell')" js_highlightHaskell :: JSString -> JSString foreign import javascript unsafe @@ -72,17 +64,13 @@ foreign import javascript unsafe var scriptEl = document.createElement('script');\ scriptEl.innerText = script;\ document.head.appendChild(scriptEl);\ - })" + })($1)" js_insertScript :: JSString -> IO () foreign import javascript unsafe - "(function(){\ - return location.hash;\ - })" + "location.hash" js_readUrlHash :: IO JSString foreign import javascript unsafe - "(function(url){\ - return location = url;\ - })" + "location = $1;" js_pushHref :: JSString -> IO () #else js_selectCountry :: DOMElement -> Nullable JSVal -> IO () = errorGhcjsOnly diff --git a/examples/simple-routing/prism.externs b/examples/simple-routing/prism.externs deleted file mode 100644 index 34e97e8..0000000 --- a/examples/simple-routing/prism.externs +++ /dev/null @@ -1,16 +0,0 @@ -/** @const */ -var Prism = {}; - -/** @const */ -Prism.languages = {}; - -/** @const */ -Prism.languages.haskell = {}; - -/** - * @param {string} code - * @param {!Object} language - * @param {string} languageString - * @return {string} - */ -Prism.highlight = function(code, language, languageString) {}; \ No newline at end of file diff --git a/examples/simple-routing/simple-routing.hs b/examples/simple-routing/simple-routing.hs index 26a8d46..f3ad9b3 100644 --- a/examples/simple-routing/simple-routing.hs +++ b/examples/simple-routing/simple-routing.hs @@ -3,7 +3,8 @@ import Control.Monad.IO.Class import Data.Maybe import Data.Functor import HtmlT -import JavaScript.Compat.String (JSString(..)) +import Wasm.Compat.Prim +import Wasm.Compat.Marshal import "this" Pages import "this" Router @@ -11,7 +12,10 @@ import "this" Utils import "this" Assets main :: IO () -main = void $ attachToBody do +main = return () + +foreign export ccall wasm_main :: IO () +wasm_main = void $ attachToBody do liftIO $ insertScript prismJs el "style" (text awsmCss) el "style" (text customCss) diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index 1b48dfa..fae17fe 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -4,6 +4,7 @@ import Control.Monad.State import Data.Maybe import GHC.Generics (Generic) import HtmlT +import Data.Text import Wasm.Compat.Marshal import Wasm.Compat.Prim @@ -16,15 +17,15 @@ data TodoItemConfig = TodoItemConfig } data TodoItemState = TodoItemState - { title :: JSString + { title :: Text , completed :: Bool - , editing :: Maybe JSString + , editing :: Maybe Text } deriving stock (Show, Eq, Generic) data TodoItemAction a where CancelAction :: TodoItemConfig -> TodoItemAction () CommitAction :: TodoItemConfig -> TodoItemAction () - InputAction :: TodoItemConfig -> JSString -> TodoItemAction () + InputAction :: TodoItemConfig -> Text -> TodoItemAction () DoubleClickAction :: TodoItemConfig -> JSVal -> TodoItemAction () CheckedAction :: TodoItemConfig -> Bool -> TodoItemAction () KeydownAction :: TodoItemConfig -> Int -> TodoItemAction () diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index d38b6a1..1f8c83d 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -8,6 +8,8 @@ import GHC.Generics (Generic) import HtmlT import Wasm.Compat.Marshal import Wasm.Compat.Prim +import Data.Text (Text) +import Data.Text qualified as Text import "this" TodoItem qualified as TodoItem import "this" Utils @@ -17,7 +19,7 @@ data TodoListConfig = TodoListConfig } data TodoListState = TodoListState - { title :: JSString + { title :: Text , items :: [TodoItem.TodoItemState] , filter :: Filter } deriving (Show, Eq, Generic) @@ -30,9 +32,9 @@ newtype LocalStorageTodoItems = LocalStorageTodoItems } deriving newtype (ToJSVal, FromJSVal) data TodoListAction a where - InitAction :: ReactiveEnv -> DynRef JSString -> TodoListAction (DynRef TodoListState) + InitAction :: ReactiveEnv -> DynRef Text -> TodoListAction (DynRef TodoListState) ToggleAllAction :: TodoListConfig -> Bool -> TodoListAction () - InputAction :: TodoListConfig -> JSString -> TodoListAction () + InputAction :: TodoListConfig -> Text -> TodoListAction () CommitAction :: TodoListConfig -> TodoListAction () KeydownAction :: TodoListConfig -> Int -> TodoListAction () DeleteItemAction :: TodoListConfig -> Int -> TodoListAction () @@ -122,7 +124,7 @@ html cfg = do footerWidget = footer_ [class_ "footer"] do toggleClass "hidden" hiddenDyn span_ [class_ "todo-count"] do - strong_ $ dynText $ toJSString . show <$> itemsLeftDyn + strong_ $ dynText $ Text.pack . show <$> itemsLeftDyn dynText $ pluralize " item left" " items left" <$> itemsLeftDyn ul_ [class_ "filters"] do for_ [All, Active, Completed] filterWidget @@ -140,7 +142,7 @@ html cfg = do filterWidget flt = li_ do a_ [href_ (printFilter flt)] do toggleClass "selected" $ filterSelectedDyn flt - text $ toJSString (show flt) + text $ Text.pack $ show flt hiddenDyn = Prelude.null . (.items) <$> fromRef cfg.state_ref itemsLeftDyn = @@ -183,24 +185,24 @@ todoItemModifier cfg idx elemModifier = Modifier \upd f -> do overIx n f (x:xs) = x : overIx (pred n) f xs overIx n _ [] = [] -pluralize :: JSString -> JSString -> Int -> JSString +pluralize :: Text -> Text -> Int -> Text pluralize singular plural 0 = singular pluralize singular plural _ = plural -parseFilter :: JSString -> Maybe Filter +parseFilter :: Text -> Maybe Filter parseFilter = \case "#/" -> Just All "#/active" -> Just Active "#/completed" -> Just Completed _ -> Nothing -printFilter :: Filter -> JSString +printFilter :: Filter -> Text printFilter = \case All -> "#/" Active -> "#/active" Completed -> "#/completed" -styles :: JSString +styles :: Text styles = "\ \body {\ \ margin: 0;\ diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs index c61f303..f533339 100644 --- a/examples/todomvc/Utils.hs +++ b/examples/todomvc/Utils.hs @@ -7,16 +7,17 @@ import Control.Monad import Control.Monad.Reader import Data.Typeable import HtmlT +import Data.Text (Text) import Wasm.Compat.Prim import Wasm.Compat.Marshal -mkUrlHashRef :: MonadReactive m => m (DynRef JSString) +mkUrlHashRef :: MonadReactive m => m (DynRef Text) mkUrlHashRef = do - initial <- liftIO js_readUrlHash + initial <- liftIO $ textFromJSString =<< js_readUrlHash routeRef <- newRef initial win <- getCurrentWindow popStateCb <- liftIO $ js_dynExport1 \_ -> - js_readUrlHash >>= dynStep . writeRef routeRef + js_readUrlHash >>= textFromJSString >>= dynStep . writeRef routeRef liftIO $ js_addEventListener win ((\(JSString j) -> j) $ toJSString "onpopstate") popStateCb return routeRef diff --git a/htmlt.cabal b/htmlt.cabal index ad329d8..aa4d6b0 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -29,7 +29,7 @@ common htmlt-common -Wall -Wno-missing-signatures -Wno-name-shadowing -Wno-unused-matches -Wno-unused-do-bind if flag(production) - ghc-options: -O2 + ghc-options: -O3 default-extensions: AllowAmbiguousTypes BangPatterns @@ -101,6 +101,7 @@ library text, transformers, ghc-experimental, + ghc-prim, -- executable htmlt-counter -- import: htmlt-common @@ -127,6 +128,7 @@ executable htmlt-todomvc build-depends: base, htmlt, + text, mtl, if !flag(examples) buildable: False @@ -135,6 +137,9 @@ executable htmlt-todomvc -- import: htmlt-common -- main-is: simple-routing.hs -- hs-source-dirs: ./examples/simple-routing +-- ghc-options: +-- -no-hs-main -optl-mexec-model=reactor +-- -optl-Wl,--export=hs_init,--export=wasm_main -- other-modules: -- Assets -- Router diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index f95af10..7d653c4 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -121,17 +121,20 @@ ZC19ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createElement( ZC23ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => ($1.setAttribute($2, $3)), ZC24ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => ($1.insertBefore($2, $3)), ZC25ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => ($1.appendChild($2)), -ZC0ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), -ZC1ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1.length), -ZC2ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1.push($2)), -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: () => ([]), -ZC5ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), -ZC6ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => (($1 ? true : false)), -ZC8ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1), -ZC9ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1), -ZC10ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => {if ($1 === undefined || $1 === null) return 0; if (typeof $1 === 'boolean') return 1; if (typeof $1 === 'number') return 2; if (typeof $1 === 'string') return 3; if (Array.isArray($1)) return 4; return 5;}, -ZC11ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => (($1 === null || $1 === undefined)), -ZC14ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: () => (null), +ZC0ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1.length), +ZC1ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written), +ZC2ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ((new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)))), +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), +ZC4ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1.length), +ZC5ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1.push($2)), +ZC6ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: () => ([]), +ZC8ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), +ZC9ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => (($1 ? true : false)), +ZC11ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1), +ZC12ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1), +ZC13ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => {if ($1 === undefined || $1 === null) return 0; if (typeof $1 === 'boolean') return 1; if (typeof $1 === 'number') return 2; if (typeof $1 === 'string') return 3; if (Array.isArray($1)) return 4; return 5;}, +ZC14ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => (($1 === null || $1 === undefined)), +ZC17ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: () => (null), ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, diff --git a/src/HtmlT/Base.hs b/src/HtmlT/Base.hs index c31066f..b19e1a7 100644 --- a/src/HtmlT/Base.hs +++ b/src/HtmlT/Base.hs @@ -9,6 +9,7 @@ import Control.Monad.Trans.Maybe import Data.Foldable import Data.IORef import Data.Map qualified as Map +import Data.Text import HtmlT.DOM import HtmlT.Event @@ -24,7 +25,7 @@ import Wasm.Compat.Prim -- > el "div" do -- > prop "className" "container" -- > el "span" $ text "Lorem Ipsum" -el :: JSString -> Html a -> Html a +el :: Text -> Html a -> Html a el tag child = do newRootEl <- liftIO (createElement tag) appendHtmlT newRootEl child @@ -37,19 +38,19 @@ el tag child = do -- > prop "width" "400" -- > elns "http://www.w3.org/2000/svg" "path" do -- > prop "d" "M150 0 L75 200 L225 200 Z" -elns :: JSString -> JSString -> Html a -> Html a +elns :: Text -> Text -> Html a -> Html a elns ns tag child = do newRootEl <- liftIO (createElementNS ns tag) appendHtmlT newRootEl child -- | Create a TextNode and attach it to 'html_current_element' -text :: JSString -> Html () +text :: Text -> Html () text txt = do textNode <- liftIO (createTextNode txt) insertNode textNode -- | Create a TextNode with dynamic content -dynText :: Dynamic JSString -> Html () +dynText :: Dynamic Text -> Html () dynText d = do txt <- readDyn d textNode <- liftIO (createTextNode txt) @@ -60,35 +61,35 @@ dynText d = do -- | Assign a property to 'html_current_element'. Don't confuse -- attributes and properties -- https://stackoverflow.com/questions/6003819/what-is-the-difference-between-properties-and-attributes-in-html -prop :: ToJSVal v => JSString -> v -> Html () +prop :: ToJSVal v => Text -> v -> Html () prop key val = do rootEl <- asks html_current_element - v <- liftIO $ toJSVal val - liftIO $ js_setProp (unDOMElement rootEl) key v + jkey <- liftIO $ textToJSString key + jval <- liftIO $ toJSVal val + liftIO $ js_setProp rootEl.unDOMElement jkey jval -- | Assign a property with dynamic content to the root element dynProp :: (ToJSVal v, FromJSVal v) - => JSString + => Text -> Dynamic v -> Html () -dynProp jsKey dyn = do +dynProp key dyn = do + jKey <- liftIO $ textToJSString key el <- asks html_current_element + let setup el t = toJSVal t >>= js_setProp el.unDOMElement jKey performDyn $ liftIO . setup el <$> dyn - where - setup el t = toJSVal t - >>= js_setProp (unDOMElement el) jsKey -- | Assign an attribute to the root element. Don't confuse attributes -- and properties -- https://stackoverflow.com/questions/6003819/what-is-the-difference-between-properties-and-attributes-in-html -attr :: JSString -> JSString -> Html () +attr :: Text -> Text -> Html () attr k v = do el <- asks html_current_element liftIO $ setAttribute el k v -- | Assign an attribute with dynamic content to the root element -dynAttr :: JSString -> Dynamic JSString -> Html () +dynAttr :: Text -> Dynamic Text -> Html () dynAttr k d = do el <- asks html_current_element performDyn $ liftIO . setAttribute el k <$> d @@ -99,7 +100,7 @@ dynAttr k d = do -- > el "div" do -- > classes "container row" -- > classes "mt-1 mb-2" --- classes :: JSString -> Html () +-- classes :: Text -> Html () -- classes cs = do -- rootEl <- asks html_current_element -- for_ (T.splitOn " " cs) $ liftIO . classListAdd rootEl @@ -113,7 +114,7 @@ dynAttr k d = do -- > el "button" do -- > on_ "click" $ modifyRef showRef not -- > text "Toggle visibility" -toggleClass :: JSString -> Dynamic Bool -> Html () +toggleClass :: Text -> Dynamic Bool -> Html () toggleClass cs dyn = do rootEl <- asks html_current_element performDyn $ liftIO . setup rootEl cs <$> dyn @@ -131,13 +132,13 @@ toggleClass cs dyn = do -- > el "button" do -- > on_ "click" $ modifyRef hiddenRef not -- > text "Toggle visibility" -toggleAttr :: JSString -> Dynamic Bool -> Html () +toggleAttr :: Text -> Dynamic Bool -> Html () toggleAttr att dyn = do rootEl <- asks html_current_element performDyn $ liftIO . setup rootEl att <$> dyn where setup rootEl name = \case - True -> setAttribute rootEl name $ toJSString "on" + True -> setAttribute rootEl name "on" False -> removeAttribute rootEl name -- | Assign a CSS property to the root dynamically based on the value @@ -148,15 +149,16 @@ toggleAttr att dyn = do -- > dynStyle "background" $ bool "initial" "red" <$> fromRef colorRef -- > on_ "click" $ modifyRef colorRef not -- > text "Toggle background color" -dynStyle :: JSString -> Dynamic JSString -> Html () +dynStyle :: Text -> Dynamic Text -> Html () dynStyle cssProp dyn = do rootEl <- asks html_current_element - performDyn $ liftIO . setup rootEl <$> dyn + jCssProp <- liftIO $ textToJSString cssProp + performDyn $ liftIO . setup jCssProp rootEl <$> dyn where - setup el t = do + setup jCssProp el t = do styleVal <- js_getProp el.unDOMElement $ toJSString "style" cssVal <- toJSVal t - js_setProp styleVal cssProp cssVal + js_setProp styleVal jCssProp cssVal -- | Alias for @pure ()@, useful when some Html action is expected. blank :: Applicative m => m () @@ -302,7 +304,7 @@ portal newRootEl html = do -- > unsafeHtml "\ -- > \\ -- > \" -unsafeHtml :: MonadIO m => JSString -> HtmlT m () +unsafeHtml :: MonadIO m => Text -> HtmlT m () unsafeHtml htmlText = do henv <- ask let anchor = fmap boundary_end henv.html_content_boundary diff --git a/src/HtmlT/DOM.hs b/src/HtmlT/DOM.hs index 810556d..90d9354 100644 --- a/src/HtmlT/DOM.hs +++ b/src/HtmlT/DOM.hs @@ -18,6 +18,7 @@ import Wasm.Compat.Prim import Wasm.Compat.Marshal import HtmlT.Types import HtmlT.Event +import Data.Text import Data.Kind @@ -36,15 +37,12 @@ on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> Ht on k = addEventListener (addEventListenerArgs @eventName) k data AddEventListenerArgs callback = AddEventListenerArgs - { event_name :: JSString + { event_name :: Text , listener_options :: EventListenerOptions , mk_callback :: callback -> JSVal -> Step () } deriving (Generic) -addEventListener - :: AddEventListenerArgs callback - -> callback - -> Html () +addEventListener :: AddEventListenerArgs callback -> callback -> Html () addEventListener args k = do el <- asks (.html_current_element) addEventListenerTarget el.unDOMElement args k @@ -59,14 +57,13 @@ addEventListenerTarget -> m () addEventListenerTarget target args k = do cb <- liftIO $ js_dynExport1 $ dynStep . args.mk_callback k + jEventName <- liftIO $ toJSVal args.event_name -- jscb <- withopts hscb - liftIO $ js_addEventListener target - (toJSValPure args.event_name) cb + liftIO $ js_addEventListener target jEventName cb let reactiveScope = 1::Int installFinalizer _ _ = return () installFinalizer reactiveScope do - js_addEventListener target - (toJSValPure args.event_name) cb + js_addEventListener target jEventName cb freeJSVal cb class IsEventName eventName where @@ -94,7 +91,7 @@ instance IsEventName "submit" where addEventListenerArgs = submitEventArgs instance IsEventName "input" where - type EventListenerCb "input" = JSString -> Step () + type EventListenerCb "input" = Text -> Step () addEventListenerArgs = inputEventArgs instance IsEventName "keydown" where @@ -114,11 +111,11 @@ instance IsEventName "blur" where addEventListenerArgs = pointerEventArgs "blur" instance IsEventName "input/blur" where - type EventListenerCb "input/blur" = JSString -> Step () + type EventListenerCb "input/blur" = Text -> Step () addEventListenerArgs = inputEventArgs {event_name = "blur"} instance IsEventName "input/focus" where - type EventListenerCb "input/focus" = JSString -> Step () + type EventListenerCb "input/focus" = Text -> Step () addEventListenerArgs = inputEventArgs {event_name = "focus"} instance IsEventName "checkbox/change" where @@ -126,11 +123,11 @@ instance IsEventName "checkbox/change" where addEventListenerArgs = checkboxChangeEventArgs instance IsEventName "select/change" where - type EventListenerCb "select/change" = JSString -> Step () + type EventListenerCb "select/change" = Text -> Step () addEventListenerArgs = selectChangeEventArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event -pointerEventArgs :: JSString -> AddEventListenerArgs (Step ()) +pointerEventArgs :: Text -> AddEventListenerArgs (Step ()) pointerEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -148,7 +145,7 @@ submitEventArgs = AddEventListenerArgs defaultSubmitOptions = EventListenerOptions True True -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event -inputEventArgs :: AddEventListenerArgs (JSString -> Step ()) +inputEventArgs :: AddEventListenerArgs (Text -> Step ()) inputEventArgs = AddEventListenerArgs { event_name = "input" , listener_options = defaultEventListenerOptions @@ -160,7 +157,7 @@ inputEventArgs = AddEventListenerArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardEventArgs :: JSString -> AddEventListenerArgs (Int -> Step ()) +keyboardEventArgs :: Text -> AddEventListenerArgs (Int -> Step ()) keyboardEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -173,14 +170,11 @@ keyboardEventArgs event_name = AddEventListenerArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event -focusEventArgs :: JSString -> AddEventListenerArgs (Step ()) +focusEventArgs :: Text -> AddEventListenerArgs (Step ()) focusEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions - , mk_callback = undefined - -- , mk_hs_callback = \k _ -> k - -- , mk_js_callback = \opts callbackId -> - -- Lam $ RevSeq $ TriggerEvent callbackId NullE : applyListenerOptions opts + , mk_callback = \k _ -> k } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event @@ -195,7 +189,7 @@ checkboxChangeEventArgs = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -selectChangeEventArgs :: AddEventListenerArgs (JSString -> Step ()) +selectChangeEventArgs :: AddEventListenerArgs (Text -> Step ()) selectChangeEventArgs = AddEventListenerArgs { event_name = "change" , listener_options = defaultEventListenerOptions @@ -206,20 +200,20 @@ selectChangeEventArgs = AddEventListenerArgs } data Location = Location - { protocol :: JSString + { protocol :: Text -- ^ A string containing the protocol scheme of the URL, including -- the final ':' - , hostname :: JSString + , hostname :: Text -- ^ A string containing the domain of the URL. - , port :: JSString + , port :: Text -- ^ A string containing the port number of the URL. - , pathname :: JSString + , pathname :: Text -- ^ A string containing an initial '/' followed by the path of the -- URL, not including the query string or fragment. - , search :: JSString + , search :: Text -- ^ A string containing a '?' followed by the parameters or -- "querystring" of the URL - , hash :: JSString + , hash :: Text -- ^ A string containing a '#' followed by the fragment identifier -- of the URL. } deriving stock (Show, Eq, Generic) @@ -270,13 +264,18 @@ appendChild = js_appendChild -- | Element.setAttribute() -- https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute -setAttribute :: DOMElement -> JSString -> JSString -> IO () -setAttribute e k v = js_setAttribute e k v +setAttribute :: DOMElement -> Text -> Text -> IO () +setAttribute e k v = do + jk <- textToJSString k + jv <- textToJSString v + js_setAttribute e jk jv -- | Element.removeAttribute() -- https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute -removeAttribute :: DOMElement -> JSString -> IO () -removeAttribute e k = js_removeAttribute e k +removeAttribute :: DOMElement -> Text -> IO () +removeAttribute e k = do + jk <- textToJSString k + js_removeAttribute e jk -- | DOMNode.removeChild() -- https://developer.mozilla.org/en-US/docs/Web/API/DOMNode/removeChild @@ -285,44 +284,60 @@ removeChild = js_removeChild -- | Document.createElement() -- https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement -createElement :: JSString -> IO DOMElement -createElement = js_createElement +createElement :: Text -> IO DOMElement +createElement tagName = do + jTagName <- textToJSString tagName + js_createElement jTagName -- | Document.createElementNS() -- https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS -createElementNS :: JSString -> JSString -> IO DOMElement -createElementNS n t = js_createElementNS n t +createElementNS :: Text -> Text -> IO DOMElement +createElementNS ns tagName = do + jNs <- textToJSString ns + jTagName <- textToJSString tagName + js_createElementNS jNs jTagName -- | Document.createTextNode() -- https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode -createTextNode :: JSString -> IO DOMNode -createTextNode = js_createTextNode +createTextNode :: Text -> IO DOMNode +createTextNode t = do + jt <- textToJSString t + js_createTextNode jt -- | Document.createComment() -- https://developer.mozilla.org/en-US/docs/Web/API/Document/createComment -createComment :: JSString -> IO DOMNode -createComment = js_createComment +createComment :: Text -> IO DOMNode +createComment c = do + jc <- textToJSString c + js_createComment jc -- | Element.classList.add() -- https://developer.mozilla.org/en-US/docs/Web/API/Element/classList -classListAdd :: DOMElement -> JSString -> IO () -classListAdd e c = js_classListAdd e c +classListAdd :: DOMElement -> Text -> IO () +classListAdd e c = do + jc <- textToJSString c + js_classListAdd e jc -- | Element.classList.remove() -- https://developer.mozilla.org/en-US/docs/Web/API/Element/classList -classListRemove :: DOMElement -> JSString -> IO () -classListRemove e c = js_classListRemove e c +classListRemove :: DOMElement -> Text -> IO () +classListRemove e c = do + jc <- textToJSString c + js_classListRemove e jc -- | Assign text to DOMNode.nodeValue -- https://developer.mozilla.org/en-US/docs/Web/API/DOMNode/nodeValue -setTextValue :: DOMNode -> JSString -> IO () -setTextValue v = js_setTextValue v +setTextValue :: DOMNode -> Text -> IO () +setTextValue n v = do + jv <- textToJSString v + js_setTextValue n jv -- | Insert raw HTML code, similar to @parent.innerHTML = rawHtml@ but -- does not removes siblings -unsafeInsertHtml :: DOMElement -> Maybe DOMNode -> JSString -> IO () -unsafeInsertHtml parent manchor rawHtml = js_unsafeInsertHtml parent - (maybeToNullable manchor) rawHtml +unsafeInsertHtml :: DOMElement -> Maybe DOMNode -> Text -> IO () +unsafeInsertHtml parent manchor rawHtml = do + jRawHtml <- textToJSString rawHtml + js_unsafeInsertHtml parent (maybeToNullable manchor) jRawHtml -- | Assuming given 'ContentBoundary' was inserted into the @parent@ -- element remove all the content inside the boundary. @@ -570,7 +585,7 @@ instance (a ~ (), MonadIO m) => IsString (HtmlT m a) where fromString s = do HtmlEnv{html_current_element, html_content_boundary} <- ask let jsstr = toJSString s - textNode <- liftIO $ createTextNode jsstr + textNode <- liftIO $ js_createTextNode jsstr case html_content_boundary of Just b -> liftIO $ js_insertBefore html_current_element textNode b.boundary_end diff --git a/src/HtmlT/Element.hs b/src/HtmlT/Element.hs index b49e7f6..0987c9b 100644 --- a/src/HtmlT/Element.hs +++ b/src/HtmlT/Element.hs @@ -6,6 +6,7 @@ module HtmlT.Element where import HtmlT.Base import HtmlT.Types import Wasm.Compat.Prim +import Data.Text -- | This typeclass allows for tag constructors to have variable -- length arguments. Each tag constructor like 'div_' defined below @@ -18,7 +19,7 @@ import Wasm.Compat.Prim -- https://github.com/chrisdone/lucid/blob/fb3b0e7c189c2acd8d88838d4a13923f24542ee8/src/Lucid/Base.hs#L272 class Term arg result | result -> arg where term - :: JSString -- ^ Name. + :: Text -- ^ Name. -> arg -- ^ Some argument. -> result -- ^ Result: either an element or an attribute. diff --git a/src/HtmlT/Internal.hs b/src/HtmlT/Internal.hs index f04e17f..0c39110 100644 --- a/src/HtmlT/Internal.hs +++ b/src/HtmlT/Internal.hs @@ -37,8 +37,8 @@ insertNode n = do -- dynamic content. insertBoundary :: MonadIO m => HtmlT m ContentBoundary insertBoundary = do - boundary_begin <- liftIO $ createComment $ toJSString "ContentBoundary {{" - boundary_end <- liftIO $ createComment $ toJSString "}}" + boundary_begin <- liftIO $ createComment "ContentBoundary {{" + boundary_end <- liftIO $ createComment "}}" insertNode boundary_begin insertNode boundary_end return ContentBoundary {boundary_begin, boundary_end} diff --git a/src/HtmlT/Main.hs b/src/HtmlT/Main.hs index ccee798..4ab705a 100644 --- a/src/HtmlT/Main.hs +++ b/src/HtmlT/Main.hs @@ -40,8 +40,8 @@ attachOptions StartOpts{..} render = mdo -- TODO: doesn't work with javascript-backend -- when startopts_wait_document_load -- js_waitDocumentLoad - begin <- createComment $ toJSString "ContentBoundary {{" - end <- createComment $ toJSString "}}" + begin <- createComment "ContentBoundary {{" + end <- createComment "}}" appendChild startopts_root_element begin appendChild startopts_root_element end let diff --git a/src/HtmlT/Property.hs b/src/HtmlT/Property.hs index 2152a96..40cbea5 100644 --- a/src/HtmlT/Property.hs +++ b/src/HtmlT/Property.hs @@ -6,6 +6,7 @@ module HtmlT.Property where import HtmlT.Base import HtmlT.Event import HtmlT.Types +import Data.Text import Wasm.Compat.Prim @@ -14,15 +15,15 @@ import Wasm.Compat.Prim -- set the CSS color for an element, essentially no other CSS property -- can be applied to this element, as they will be overwritten by -- 'dynStyles'. -dynStyles :: Dynamic JSString -> Html () +dynStyles :: Dynamic Text -> Html () dynStyles = dynProp "style" {-# INLINE dynStyles #-} -dynValue :: Dynamic JSString -> Html () +dynValue :: Dynamic Text -> Html () dynValue = dynProp "value" {-# INLINE dynValue #-} -dynClass :: Dynamic JSString -> Html () +dynClass :: Dynamic Text -> Html () dynClass = dynProp "className" {-# INLINE dynClass #-} @@ -34,7 +35,7 @@ dynDisabled :: Dynamic Bool -> Html () dynDisabled = dynProp "disabled" {-# INLINE dynDisabled #-} -title_ :: JSString -> Html () +title_ :: Text -> Html () title_ = prop "title" {-# INLINE title_ #-} @@ -46,31 +47,31 @@ hidden_ :: Bool -> Html () hidden_ = prop "hidden" {-# INLINE hidden_ #-} -value_ :: JSString -> Html () +value_ :: Text -> Html () value_ = prop "value" {-# INLINE value_ #-} -defaultValue_ :: JSString -> Html () +defaultValue_ :: Text -> Html () defaultValue_ = prop "defaultValue" {-# INLINE defaultValue_ #-} -accept_ :: JSString -> Html () +accept_ :: Text -> Html () accept_ = prop "accept" {-# INLINE accept_ #-} -acceptCharset_ :: JSString -> Html () +acceptCharset_ :: Text -> Html () acceptCharset_ = prop "acceptCharset" {-# INLINE acceptCharset_ #-} -action_ :: JSString -> Html () +action_ :: Text -> Html () action_ = prop "action" {-# INLINE action_ #-} autocomplete_ :: Bool -> Html () -autocomplete_ b = prop @JSString "autocomplete" (if b then "on" else "off") +autocomplete_ b = prop @Text "autocomplete" (if b then "on" else "off") {-# INLINE autocomplete_ #-} -autosave_ :: JSString -> Html () +autosave_ :: Text -> Html () autosave_ = prop "autosave" {-# INLINE autosave_ #-} @@ -78,27 +79,27 @@ disabled_ :: Bool -> Html () disabled_ = prop "disabled" {-# INLINE disabled_ #-} -enctype_ :: JSString -> Html () +enctype_ :: Text -> Html () enctype_ = prop "enctype" {-# INLINE enctype_ #-} -formation_ :: JSString -> Html () +formation_ :: Text -> Html () formation_ = prop "formation" {-# INLINE formation_ #-} -list_ :: JSString -> Html () +list_ :: Text -> Html () list_ = prop "list" {-# INLINE list_ #-} -maxlength_ :: JSString -> Html () +maxlength_ :: Text -> Html () maxlength_ = prop "maxlength" {-# INLINE maxlength_ #-} -minlength_ :: JSString -> Html () +minlength_ :: Text -> Html () minlength_ = prop "minlength" {-# INLINE minlength_ #-} -method_ :: JSString -> Html () +method_ :: Text -> Html () method_ = prop "method" {-# INLINE method_ #-} @@ -110,7 +111,7 @@ novalidate_ :: Bool -> Html () novalidate_ = prop "noValidate" {-# INLINE novalidate_ #-} -pattern_ :: JSString -> Html () +pattern_ :: Text -> Html () pattern_ = prop "pattern" {-# INLINE pattern_ #-} @@ -122,103 +123,103 @@ required_ :: Bool -> Html () required_ = prop "required" {-# INLINE required_ #-} -size_ :: JSString -> Html () +size_ :: Text -> Html () size_ = prop "size" {-# INLINE size_ #-} -forProp_ :: JSString -> Html () +forProp_ :: Text -> Html () forProp_ = prop "for" {-# INLINE forProp_ #-} -ref_ :: JSString -> Html () +ref_ :: Text -> Html () ref_ = prop "ref" {-# INLINE ref_ #-} -formProp_ :: JSString -> Html () +formProp_ :: Text -> Html () formProp_ = prop "form" {-# INLINE formProp_ #-} -max_ :: JSString -> Html () +max_ :: Text -> Html () max_ = prop "max" {-# INLINE max_ #-} -min_ :: JSString -> Html () +min_ :: Text -> Html () min_ = prop "min" {-# INLINE min_ #-} -step_ :: JSString -> Html () +step_ :: Text -> Html () step_ = prop "step" {-# INLINE step_ #-} -cols_ :: JSString -> Html () +cols_ :: Text -> Html () cols_ = prop "cols" {-# INLINE cols_ #-} -rows_ :: JSString -> Html () +rows_ :: Text -> Html () rows_ = prop "rows" {-# INLINE rows_ #-} -wrap_ :: JSString -> Html () +wrap_ :: Text -> Html () wrap_ = prop "wrap" {-# INLINE wrap_ #-} -target_ :: JSString -> Html () +target_ :: Text -> Html () target_ = prop "target" {-# INLINE target_ #-} -download_ :: JSString -> Html () +download_ :: Text -> Html () download_ = prop "download" {-# INLINE download_ #-} -downloadAs_ :: JSString -> Html () +downloadAs_ :: Text -> Html () downloadAs_ = prop "downloadAs" {-# INLINE downloadAs_ #-} -hreflang_ :: JSString -> Html () +hreflang_ :: Text -> Html () hreflang_ = prop "hreflang" {-# INLINE hreflang_ #-} -media_ :: JSString -> Html () +media_ :: Text -> Html () media_ = prop "media" {-# INLINE media_ #-} -ping_ :: JSString -> Html () +ping_ :: Text -> Html () ping_ = prop "ping" {-# INLINE ping_ #-} -rel_ :: JSString -> Html () +rel_ :: Text -> Html () rel_ = prop "rel" {-# INLINE rel_ #-} -ismap_ :: JSString -> Html () +ismap_ :: Text -> Html () ismap_ = prop "ismap" {-# INLINE ismap_ #-} -usemap_ :: JSString -> Html () +usemap_ :: Text -> Html () usemap_ = prop "usemap" {-# INLINE usemap_ #-} -shape_ :: JSString -> Html () +shape_ :: Text -> Html () shape_ = prop "shape" {-# INLINE shape_ #-} -coords_ :: JSString -> Html () +coords_ :: Text -> Html () coords_ = prop "coords" {-# INLINE coords_ #-} -src_ :: JSString -> Html () +src_ :: Text -> Html () src_ = prop "src" {-# INLINE src_ #-} -height_ :: JSString -> Html () +height_ :: Text -> Html () height_ = prop "height" {-# INLINE height_ #-} -width_ :: JSString -> Html () +width_ :: Text -> Html () width_ = prop "width" {-# INLINE width_ #-} -alt_ :: JSString -> Html () +alt_ :: Text -> Html () alt_ = prop "alt" {-# INLINE alt_ #-} @@ -234,11 +235,11 @@ loop_ :: Bool -> Html () loop_ = prop "loop" {-# INLINE loop_ #-} -preload_ :: JSString -> Html () +preload_ :: Text -> Html () preload_ = prop "preload" {-# INLINE preload_ #-} -poster_ :: JSString -> Html () +poster_ :: Text -> Html () poster_ = prop "poster" {-# INLINE poster_ #-} @@ -246,99 +247,99 @@ default_ :: Bool -> Html () default_ = prop "default" {-# INLINE default_ #-} -kind_ :: JSString -> Html () +kind_ :: Text -> Html () kind_ = prop "kind" {-# INLINE kind_ #-} -srclang_ :: JSString -> Html () +srclang_ :: Text -> Html () srclang_ = prop "srclang" {-# INLINE srclang_ #-} -sandbox_ :: JSString -> Html () +sandbox_ :: Text -> Html () sandbox_ = prop "sandbox" {-# INLINE sandbox_ #-} -seamless_ :: JSString -> Html () +seamless_ :: Text -> Html () seamless_ = prop "seamless" {-# INLINE seamless_ #-} -srcdoc_ :: JSString -> Html () +srcdoc_ :: Text -> Html () srcdoc_ = prop "srcdoc" {-# INLINE srcdoc_ #-} -reversed_ :: JSString -> Html () +reversed_ :: Text -> Html () reversed_ = prop "reversed" {-# INLINE reversed_ #-} -start_ :: JSString -> Html () +start_ :: Text -> Html () start_ = prop "start" {-# INLINE start_ #-} -align_ :: JSString -> Html () +align_ :: Text -> Html () align_ = prop "align" {-# INLINE align_ #-} -colspan_ :: JSString -> Html () +colspan_ :: Text -> Html () colspan_ = attr "colspan" {-# INLINE colspan_ #-} -rowspan_ :: JSString -> Html () +rowspan_ :: Text -> Html () rowspan_ = attr "rowspan" {-# INLINE rowspan_ #-} -headers_ :: JSString -> Html () +headers_ :: Text -> Html () headers_ = prop "headers" {-# INLINE headers_ #-} -scope_ :: JSString -> Html () +scope_ :: Text -> Html () scope_ = prop "scope" {-# INLINE scope_ #-} -async_ :: JSString -> Html () +async_ :: Text -> Html () async_ = prop "async" {-# INLINE async_ #-} -charset_ :: JSString -> Html () +charset_ :: Text -> Html () charset_ = prop "charset" {-# INLINE charset_ #-} -content_ :: JSString -> Html () +content_ :: Text -> Html () content_ = prop "content" {-# INLINE content_ #-} -defer_ :: JSString -> Html () +defer_ :: Text -> Html () defer_ = prop "defer" {-# INLINE defer_ #-} -httpEquiv_ :: JSString -> Html () +httpEquiv_ :: Text -> Html () httpEquiv_ = prop "httpEquiv" {-# INLINE httpEquiv_ #-} -language_ :: JSString -> Html () +language_ :: Text -> Html () language_ = prop "language" {-# INLINE language_ #-} -scoped_ :: JSString -> Html () +scoped_ :: Text -> Html () scoped_ = prop "scoped" {-# INLINE scoped_ #-} -type_ :: JSString -> Html () +type_ :: Text -> Html () type_ = prop "type" {-# INLINE type_ #-} -name_ :: JSString -> Html () +name_ :: Text -> Html () name_ = prop "name" {-# INLINE name_ #-} -href_ :: JSString -> Html () +href_ :: Text -> Html () href_ = prop "href" {-# INLINE href_ #-} -id_ :: JSString -> Html () +id_ :: Text -> Html () id_ = prop "id" {-# INLINE id_ #-} -placeholder_ :: JSString -> Html () +placeholder_ :: Text -> Html () placeholder_ = prop "placeholder" {-# INLINE placeholder_ #-} @@ -350,18 +351,18 @@ autofocus_ :: Bool -> Html () autofocus_ = prop "autofocus" {-# INLINE autofocus_ #-} -class_ :: JSString -> Html () +class_ :: Text -> Html () class_ = prop "className" {-# INLINE class_ #-} -data_ :: JSString -> JSString -> Html () -data_ k v = prop @JSString ("data-" <> k) v +data_ :: Text -> Text -> Html () +data_ k v = prop @Text ("data-" <> k) v {-# INLINE data_ #-} -role_ :: JSString -> Html () +role_ :: Text -> Html () role_ = attr "role" {-# INLINE role_ #-} -style_ :: JSString -> Html () +style_ :: Text -> Html () style_ = prop "style" {-# INLINE style_ #-} diff --git a/src/Wasm/Compat/Marshal.hs b/src/Wasm/Compat/Marshal.hs index 59c6347..6909f3b 100644 --- a/src/Wasm/Compat/Marshal.hs +++ b/src/Wasm/Compat/Marshal.hs @@ -2,6 +2,8 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE JavaScriptFFI #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnboxedTuples #-} module Wasm.Compat.Marshal where import Control.Monad @@ -9,6 +11,13 @@ import Data.Maybe import Data.String import Data.Coerce import Wasm.Compat.Prim +import GHC.Prim +import GHC.Ptr +import GHC.Int +import GHC.IO +import Data.Text.Internal +import Data.Array.Byte +import Data.Word newtype Nullable v = Nullable {unNullable :: JSVal} @@ -47,6 +56,10 @@ instance FromJSValPure v => FromJSValPure (Maybe v) where = maybe (Just Nothing) fromJSValPure $ nullableToMaybe (Nullable j) +instance FromJSVal v => FromJSVal (Maybe v) where + fromJSVal j = maybe (pure (Just Nothing)) fromJSVal $ + nullableToMaybe (Nullable j) + instance FromJSValPure JSVal where fromJSValPure = Just instance FromJSValPure JSString where @@ -67,6 +80,11 @@ instance FromJSVal v => FromJSVal [v] where return $ Just $ catMaybes xs _ -> return Nothing +instance FromJSVal Text where + fromJSVal j = case js_typeOf j of + TypeString -> fmap Just $ textFromJSString $ JSString j + _ -> pure Nothing + class ToJSVal v where toJSVal :: v -> IO JSVal class ToJSValPure v where toJSValPure :: v -> JSVal @@ -82,6 +100,9 @@ instance ToJSValPure JSVal where toJSValPure j = j instance ToJSValPure JSString where toJSValPure (JSString j) = j +instance ToJSVal v => ToJSVal (Maybe v) where + toJSVal = fmap (unNullable . maybeToNullable) . mapM toJSVal + instance ToJSValPure v => ToJSValPure (Maybe v) where toJSValPure = unNullable . maybeToNullable . fmap toJSValPure @@ -91,6 +112,9 @@ instance ToJSVal v => ToJSVal [v] where forM_ s $ toJSVal >=> js_arrayPush arr return arr +instance ToJSVal Text where + toJSVal = fmap (\(JSString j) -> j) . textToJSString + instance IsString JSString where fromString = toJSString instance Semigroup JSString where (<>) = js_concatStr @@ -103,6 +127,19 @@ instance Show JSString where show = show . fromJSString instance Ord JSString where compare a b = fromJSString a `compare` fromJSString b +textToJSString :: Text -> IO JSString +textToJSString (Text (ByteArray arr) off len) = do + let addr = byteArrayContents# arr + js_decodeUtf8 (Ptr addr `plusPtr` off) len + +textFromJSString :: JSString -> IO Text +textFromJSString j = IO \s0 -> + let (# s1, len@(I# len#) #) = unIO (js_stringLength j) s0 + (# s2, marr #) = newByteArray# (len# *# 3#) s1 + (# s3, tlen #) = unIO (js_encodeUtf8 j (Ptr (mutableByteArrayContents# marr)) len) s2 + (# s4, arr #) = unsafeFreezeByteArray# marr s3 + in (# s4, (Text (ByteArray arr) 0 tlen) #) + #if !defined(wasm32_HOST_ARCH) js_true :: JSVal = undefined @@ -122,6 +159,9 @@ js_newEmptyArray :: IO JSVal = undefined js_arrayPush :: JSVal -> JSVal -> IO () = undefined js_arrayLength :: JSVal -> IO Int = undefined js_arrayIndex :: JSVal -> Int -> IO JSVal = undefined +js_decodeUtf8 :: Ptr Word8 -> Int -> IO JSString = undefined +js_encodeUtf8 :: JSString -> Ptr Word8 -> Int -> IO () = undefined +js_stringLength :: JSString -> IO Int = undefined #else @@ -164,4 +204,13 @@ foreign import javascript unsafe "$1.length" js_arrayLength :: JSVal -> IO Int foreign import javascript unsafe "$1[$2]" js_arrayIndex :: JSVal -> Int -> IO JSVal +foreign import javascript unsafe + "(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)))" + js_decodeUtf8 :: Ptr Word8 -> Int -> IO JSString +foreign import javascript unsafe + "(new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written" + js_encodeUtf8 :: JSString -> Ptr Word8 -> Int -> IO Int +foreign import javascript unsafe + "$1.length" + js_stringLength :: JSString -> IO Int #endif From 912f68fd7f6ca25f4d4cf560d58ef978a0b29f07 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 15 Mar 2024 12:38:31 +0400 Subject: [PATCH 03/64] WIP: Wasm Backend --- default.nix | 8 +- examples/simple-routing/Assets.hs | 21 +- examples/simple-routing/Pages.hs | 45 ++- examples/simple-routing/Router.hs | 92 +++-- htmlt.cabal | 39 +- shell.nix | 2 +- src/HtmlT/DOM.hs | 53 +-- src/HtmlT/Event.hs | 594 +++++++++++++++--------------- src/HtmlT/Types.hs | 7 +- src/Wasm/Compat/Marshal.hs | 6 +- 10 files changed, 455 insertions(+), 412 deletions(-) diff --git a/default.nix b/default.nix index 9939795..c3d1eea 100644 --- a/default.nix +++ b/default.nix @@ -1,14 +1,8 @@ { pkgs ? import (builtins.fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/3e2237222b33d8b5754cc1cc3ee155cadd76770d.tar.gz"; + url = "https://github.com/NixOS/nixpkgs/archive/f4429fde23e1fb20ee27f264e74c28c619d2cebb.tar.gz"; }) {} }: { shell = { - javascript = pkgs.mkShell { - buildInputs = [ - pkgs.pkgsCross.ghcjs.buildPackages.haskell.compiler.ghcHEAD - pkgs.haskellPackages.cabal-install - ]; - }; x86_64 = pkgs.mkShell { buildInputs = [ pkgs.haskell.compiler.ghcHEAD diff --git a/examples/simple-routing/Assets.hs b/examples/simple-routing/Assets.hs index 09ff0df..42d4549 100644 --- a/examples/simple-routing/Assets.hs +++ b/examples/simple-routing/Assets.hs @@ -2,15 +2,16 @@ module Assets where import GHC.Generics import Wasm.Compat.Prim +import Data.Text data Country = Country - { title :: JSString - , code :: JSString - , wiki_href :: JSString + { title :: Text + , code :: Text + , wiki_href :: Text , population :: Int - , flag_icon :: Maybe JSString - , region :: JSString - , subregion :: JSString + , flag_icon :: Maybe Text + , region :: Text + , subregion :: Text } deriving Generic countries :: [Country] @@ -250,7 +251,7 @@ countries = , Country "Vatican City" "VA" "https://en.wikipedia.org/wiki/Vatican_City" 799 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Flag_of_the_Vatican_City.svg/16px-Flag_of_the_Vatican_City.svg.png") "Europe" "Southern Europe" ] -awsmCss :: JSString +awsmCss :: Text awsmCss = "\ \@charset \"UTF-8\";\ \/*!\ @@ -951,7 +952,7 @@ awsmCss = "\ \ background:rgba(0, 100, 193, 0.25);\ \}" -countriesMap :: JSString +countriesMap :: Text countriesMap = "\ \\ \\ @@ -4225,7 +4226,7 @@ countriesMap = "\ \\ \" -prismJs :: JSString +prismJs :: Text prismJs = "\ \var _self=\"undefined\"!=typeof window?window:\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\\blang(?:uage)?-([\\w-]+)\\b/i,n=0,e={},M={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof W?new W(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,\"&\").replace(/=l.reach);y+=m.value.length,m=m.next){var b=m.value;if(t.length>n.length)return;if(!(b instanceof W)){var k,x=1;if(h){if(!(k=z(v,y,n,f))||k.index>=n.length)break;var w=k.index,A=k.index+k[0].length,P=y;for(P+=m.value.length;P<=w;)m=m.next,P+=m.value.length;if(P-=m.value.length,y=P,m.value instanceof W)continue;for(var E=m;E!==t.tail&&(Pl.reach&&(l.reach=N);var j=m.prev;O&&(j=I(t,j,O),y+=O.length),q(t,j,x);var C=new W(o,g?M.tokenize(S,g):S,d,S);if(m=I(t,j,C),L&&I(t,m,L),1l.reach&&(l.reach=_.reach)}}}}}}(e,a,n,a.head,0),function(e){var n=[],t=e.head.next;for(;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=M.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=M.hooks.all[e];if(t&&t.length)for(var r,a=0;r=t[a++];)r(n)}},Token:W};function W(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||\"\").length}function z(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function i(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function I(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function q(e,n,t){for(var r=n.next,a=0;a\"+a.content+\"\"},!u.document)return u.addEventListener&&(M.disableWorkerMessageHandler||u.addEventListener(\"message\",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(M.highlight(r,M.languages[t],t)),a&&u.close()},!1)),M;var t=M.util.currentScript();function r(){M.manual||M.highlightAll()}if(t&&(M.filename=t.src,t.hasAttribute(\"data-manual\")&&(M.manual=!0)),!M.manual){var a=document.readyState;\"loading\"===a||\"interactive\"===a&&t&&t.defer?document.addEventListener(\"DOMContentLoaded\",r):window.requestAnimationFrame?window.requestAnimationFrame(r):window.setTimeout(r,16)}return M}(_self);\"undefined\"!=typeof module&&module.exports&&(module.exports=Prism),\"undefined\"!=typeof global&&(global.Prism=Prism);\ \Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\\?[\\s\\S]+?\\?>/,greedy:!0},doctype:{pattern:/\"'[\\]]|\"[^\"]*\"|'[^']*')+(?:\\[(?:[^<\"'\\]]|\"[^\"]*\"|'[^']*'|<(?!!--)|)*\\]\\s*)?>/i,greedy:!0,inside:{\"internal-subset\":{pattern:/(^[^\\[]*\\[)[\\s\\S]+(?=\\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/\"[^\"]*\"|'[^']*'/,greedy:!0},punctuation:/^$|[[\\]]/,\"doctype-tag\":/^DOCTYPE/i,name:/[^\\s<>'\"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\\/?(?!\\d)[^\\s>\\/=$<%]+(?:\\s(?:\\s*[^\\s>\\/=]+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))|(?=[\\s/>])))+)?\\s*\\/?>/,greedy:!0,inside:{tag:{pattern:/^<\\/?[^\\s>\\/]+/,inside:{punctuation:/^<\\/?/,namespace:/^[^\\s>\\/:]+:/}},\"special-attr\":[],\"attr-value\":{pattern:/=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:\"attr-equals\"},/\"|'/]}},punctuation:/\\/?>/,\"attr-name\":{pattern:/[^\\s>\\/]+/,inside:{namespace:/^[^\\s>\\/:]+:/}}}},entity:[{pattern:/&[\\da-z]{1,8};/i,alias:\"named-entity\"},/&#x?[\\da-f]{1,8};/i]},Prism.languages.markup.tag.inside[\"attr-value\"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside[\"internal-subset\"].inside=Prism.languages.markup,Prism.hooks.add(\"wrap\",function(a){\"entity\"===a.type&&(a.attributes.title=a.content.replace(/&/,\"&\"))}),Object.defineProperty(Prism.languages.markup.tag,\"addInlined\",{value:function(a,e){var s={};s[\"language-\"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={\"included-cdata\":{pattern://i,inside:s}};t[\"language-\"+e]={pattern:/[\\s\\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp(\"(<__[^>]*>)(?:))*\\\\]\\\\]>|(?!)\".replace(/__/g,function(){return a}),\"i\"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore(\"markup\",\"cdata\",n)}}),Object.defineProperty(Prism.languages.markup.tag,\"addAttribute\",{value:function(a,e){Prism.languages.markup.tag.inside[\"special-attr\"].push({pattern:RegExp(\"(^|[\\\"'\\\\s])(?:\"+a+\")\\\\s*=\\\\s*(?:\\\"[^\\\"]*\\\"|'[^']*'|[^\\\\s'\\\">=]+(?=[\\\\s>]))\",\"i\"),lookbehind:!0,inside:{\"attr-name\":/^[^\\s=]+/,\"attr-value\":{pattern:/=[\\s\\S]+/,inside:{value:{pattern:/(^=\\s*([\"']|(?![\"'])))\\S[\\s\\S]*(?=\\2$)/,lookbehind:!0,alias:[e,\"language-\"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:\"attr-equals\"},/\"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend(\"markup\",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml;\ @@ -4233,7 +4234,7 @@ prismJs = "\ \Prism.languages.haskell={comment:{pattern:/(^|[^-!#$%*+=?&@|~.:<>^\\\\\\/])(?:--(?:(?=.)[^-!#$%*+=?&@|~.:<>^\\\\\\/].*|$)|\\{-[\\s\\S]*?-\\})/m,lookbehind:!0},char:{pattern:/'(?:[^\\\\']|\\\\(?:[abfnrtv\\\\\"'&]|\\^[A-Z@[\\]^_]|ACK|BEL|BS|CAN|CR|DC1|DC2|DC3|DC4|DEL|DLE|EM|ENQ|EOT|ESC|ETB|ETX|FF|FS|GS|HT|LF|NAK|NUL|RS|SI|SO|SOH|SP|STX|SUB|SYN|US|VT|\\d+|o[0-7]+|x[0-9a-fA-F]+))'/,alias:\"string\"},string:{pattern:/\"(?:[^\\\\\"]|\\\\(?:\\S|\\s+\\\\))*\"/,greedy:!0},keyword:/\\b(?:case|class|data|deriving|do|else|if|in|infixl|infixr|instance|let|module|newtype|of|primitive|then|type|where)\\b/,\"import-statement\":{pattern:/(^[\\t ]*)import\\s+(?:qualified\\s+)?(?:[A-Z][\\w']*)(?:\\.[A-Z][\\w']*)*(?:\\s+as\\s+(?:[A-Z][\\w']*)(?:\\.[A-Z][\\w']*)*)?(?:\\s+hiding\\b)?/m,lookbehind:!0,inside:{keyword:/\\b(?:as|hiding|import|qualified)\\b/,punctuation:/\\./}},builtin:/\\b(?:abs|acos|acosh|all|and|any|appendFile|approxRational|asTypeOf|asin|asinh|atan|atan2|atanh|basicIORun|break|catch|ceiling|chr|compare|concat|concatMap|const|cos|cosh|curry|cycle|decodeFloat|denominator|digitToInt|div|divMod|drop|dropWhile|either|elem|encodeFloat|enumFrom|enumFromThen|enumFromThenTo|enumFromTo|error|even|exp|exponent|fail|filter|flip|floatDigits|floatRadix|floatRange|floor|fmap|foldl|foldl1|foldr|foldr1|fromDouble|fromEnum|fromInt|fromInteger|fromIntegral|fromRational|fst|gcd|getChar|getContents|getLine|group|head|id|inRange|index|init|intToDigit|interact|ioError|isAlpha|isAlphaNum|isAscii|isControl|isDenormalized|isDigit|isHexDigit|isIEEE|isInfinite|isLower|isNaN|isNegativeZero|isOctDigit|isPrint|isSpace|isUpper|iterate|last|lcm|length|lex|lexDigits|lexLitChar|lines|log|logBase|lookup|map|mapM|mapM_|max|maxBound|maximum|maybe|min|minBound|minimum|mod|negate|not|notElem|null|numerator|odd|or|ord|otherwise|pack|pi|pred|primExitWith|print|product|properFraction|putChar|putStr|putStrLn|quot|quotRem|range|rangeSize|read|readDec|readFile|readFloat|readHex|readIO|readInt|readList|readLitChar|readLn|readOct|readParen|readSigned|reads|readsPrec|realToFrac|recip|rem|repeat|replicate|return|reverse|round|scaleFloat|scanl|scanl1|scanr|scanr1|seq|sequence|sequence_|show|showChar|showInt|showList|showLitChar|showParen|showSigned|showString|shows|showsPrec|significand|signum|sin|sinh|snd|sort|span|splitAt|sqrt|subtract|succ|sum|tail|take|takeWhile|tan|tanh|threadToIOResult|toEnum|toInt|toInteger|toLower|toRational|toUpper|truncate|uncurry|undefined|unlines|until|unwords|unzip|unzip3|userError|words|writeFile|zip|zip3|zipWith|zipWith3)\\b/,number:/\\b(?:\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?|0o[0-7]+|0x[0-9a-f]+)\\b/i,operator:[{pattern:/`(?:[A-Z][\\w']*\\.)*[_a-z][\\w']*`/,greedy:!0},{pattern:/(\\s)\\.(?=\\s)/,lookbehind:!0},/[-!#$%*+=?&@|~:<>^\\\\\\/][-!#$%*+=?&@|~.:<>^\\\\\\/]*|\\.[-!#$%*+=?&@|~.:<>^\\\\\\/]+/],hvariable:{pattern:/\\b(?:[A-Z][\\w']*\\.)*[_a-z][\\w']*/,inside:{punctuation:/\\./}},constant:{pattern:/\\b(?:[A-Z][\\w']*\\.)*[A-Z][\\w']*/,inside:{punctuation:/\\./}},punctuation:/[{}[\\];(),.:]/},Prism.languages.hs=Prism.languages.haskell;\ \" -prismCss :: JSString +prismCss :: Text prismCss = "\ \/* PrismJS 1.25.0\ \https://prismjs.com/download.html#themes=prism&languages=haskell */\ diff --git a/examples/simple-routing/Pages.hs b/examples/simple-routing/Pages.hs index 40bdb8d..cffdcca 100644 --- a/examples/simple-routing/Pages.hs +++ b/examples/simple-routing/Pages.hs @@ -6,6 +6,9 @@ import Data.Foldable import Data.List qualified as List import Data.Maybe import Data.Ord +import Data.Text qualified as Text +import Data.Text (Text) +import Data.Function((&)) import HtmlT import Wasm.Compat.Marshal import Wasm.Compat.Prim @@ -66,7 +69,7 @@ homePage = unsafeHtml $ "\ \and implement backend part of HTML5-style routing.

\ \

Last thing we need to run the site is this auxiliary function \ \mkUrlHashRef \ - \that creates a DynRef JSString — dynamic value containing current \ + \that creates a DynRef Text — dynamic value containing current \ \hash-string from the browser. When parsed to Dynamic Route \ \and then mapped with (<&>) operator to \ \Dynamic (Html ()) the dyn function can be used to \ @@ -82,7 +85,7 @@ countriesListPage :: CountriesListQ -> Html () countriesListPage q = div_ [class_ "CountriesList"] do searchQueryRef <- newRef q form_ do - onOptions "submit" (ListenerOpts True True True) \_event -> do + on @"submit" do newRoute <- toUrl . CountriesListR . (\s -> s{page = 1}) <$> readRef searchQueryRef pushUrl newRoute div_ [style_ "display:flex;"] do @@ -90,8 +93,7 @@ countriesListPage q = div_ [class_ "CountriesList"] do [ type_ "text" , placeholder_ "Search countries by title", autofocus_ True ] do dynValue $ fromMaybe "" . (.search) <$> fromRef searchQueryRef - on "input" $ decodeEvent valueDecoder $ - modifyRef searchQueryRef . (\v s -> s{search = v}) . Just + on @"input" $ modifyRef searchQueryRef . (\v s -> s{search = v}) . Just button_ [type_ "submit"] "Search" table_ do thead_ $ tr_ do @@ -102,7 +104,7 @@ countriesListPage q = div_ [class_ "CountriesList"] do thSort SortByPopulation "Population" tbody_ do for_ pageResults \(n, country) -> tr_ do - td_ do text (JSS.pack (show @Int n)) + td_ do text (Text.pack (show @Int n)) td_ do a_ [href_ (mkMapLink country.code)] do for_ country.flag_icon @@ -110,14 +112,14 @@ countriesListPage q = div_ [class_ "CountriesList"] do text country.title td_ do text country.region td_ do text country.subregion - td_ do text (JSS.pack (show country.population)) + td_ do text (Text.pack (show country.population)) center_ do for_ (paginate total q.page itemsPerPage) \case Nothing -> button_ [disabled_ True] "..." Just p -> a_ [ href_ (toUrl (CountriesListR q {page = p}))] $ - button_ [disabled_ (q.page == p)] $ text $ JSS.pack $ show p + button_ [disabled_ (q.page == p)] $ text $ Text.pack $ show p dl_ do dt_ "Country" dd_ $ unsafeHtml "The word country comes from text "▲" (sortVal, Desc) | sortVal == sortBy -> text "▼" otherwise -> text "" - on_ "click" do pushUrl $ toUrl . CountriesListR . toggleSortBy sortBy $ q + on @"click" do pushUrl $ toUrl . CountriesListR . toggleSortBy sortBy $ q toggleSortBy sortBy q | q.sort_by == sortBy = q {sort_dir = flipDir q.sort_dir} @@ -156,7 +158,7 @@ countriesListPage q = div_ [class_ "CountriesList"] do $ countries countryFilter country = case q.search of Just needle -> - JSS.isInfixOf (JSS.toLower needle) (JSS.toLower country.title) + Text.isInfixOf (Text.toLower needle) (Text.toLower country.title) Nothing -> True countrySortBy = case q.sort_by of SortByTitle -> Left . (.title) @@ -167,7 +169,7 @@ countriesListPage q = div_ [class_ "CountriesList"] do Asc -> Left . countrySortBy Desc -> Right . Down . countrySortBy itemsPerPage = 40 - mkMapLink = toUrl . CountriesMapR . CountriesMapQ . Just . JSS.toLower + mkMapLink = toUrl . CountriesMapR . CountriesMapQ . Just . Text.toLower countriesMapPage :: CountriesMapQ -> Html () countriesMapPage q = @@ -176,11 +178,13 @@ countriesMapPage q = unsafeHtml countriesMap figcaption_ "political map of the planet Earth" centerEl <- asks html_current_element - liftIO $ js_selectCountry centerEl $ maybeToNullable $ - fmap JSS.toJSValPure q.selected - on "click" \event -> do - mcode <- fmap JSS.fromJSValPure . nullableToMaybe <$> - liftIO (js_svgClickGetCountryCode event) + liftIO do + msel <- mapM toJSVal q.selected + js_selectCountry centerEl $ maybeToNullable msel + on @ClickWithEvent \event -> do + mcode <- liftIO (js_svgClickGetCountryCode event) + & (fmap nullableToMaybe) + & mapM fromJSVal mapM_ (pushUrl . toUrl . CountriesMapR . CountriesMapQ . Just) mcode paginate @@ -202,3 +206,14 @@ paginate totalItems curPage limit (pageQuot, pageRem) = totalItems `divMod` limit totalPages = if pageRem == 0 then pageQuot else pageQuot + 1 maxLinks = 10 + + +data ClickWithEvent + +instance IsEventName ClickWithEvent where + type EventListenerCb ClickWithEvent = JSVal -> Step () + addEventListenerArgs = AddEventListenerArgs + { event_name = "dblclick" + , listener_options = defaultEventListenerOptions + , mk_callback = \k j -> k j + } diff --git a/examples/simple-routing/Router.hs b/examples/simple-routing/Router.hs index 0335e5c..050ceeb 100644 --- a/examples/simple-routing/Router.hs +++ b/examples/simple-routing/Router.hs @@ -7,12 +7,15 @@ import Data.Maybe import Data.Function import GHC.Generics import Text.Read +import Data.Text (Text) +import Data.Text qualified as Text import Wasm.Compat.Prim import Wasm.Compat.Marshal +import Data.Char qualified as C data UrlParts = Url - { partsPath :: [JSString] -- ^ Path segments - , partsQuery :: [(JSString, JSString)] -- ^ GET parameters + { partsPath :: [Text] -- ^ Path segments + , partsQuery :: [(Text, Text)] -- ^ GET parameters } deriving (Eq, Show, Generic) data Route @@ -22,14 +25,14 @@ data Route deriving (Eq, Show, Generic) data CountriesListQ = CountriesListQ - { search :: Maybe JSString + { search :: Maybe Text , page :: Int , sort_by :: CountrySortBy , sort_dir :: SortDir } deriving (Eq, Show, Generic) data CountriesMapQ = CountriesMapQ - { selected :: Maybe JSString + { selected :: Maybe Text } deriving (Eq, Show, Generic) data SortDir = Asc | Desc @@ -68,7 +71,7 @@ parseRoute = \case Just "region" -> SortByRegion Just "subregion" -> SortBySubregion _ -> defaultCountriesListQ.sort_by - parseIntQuery = readMaybe . fromJSString + parseIntQuery = readMaybe . Text.unpack printRoute :: Route -> UrlParts printRoute = \case @@ -94,7 +97,7 @@ printRoute = \case SortByRegion -> "region" SortBySubregion -> "subregion") . mfilter (/=defaultCountriesListQ.sort_by) . Just - toIntQuery = JSS.pack . show + toIntQuery = Text.pack . show defaultCountriesListQ :: CountriesListQ defaultCountriesListQ = CountriesListQ @@ -109,39 +112,74 @@ defaultCountriesMapQ = CountriesMapQ { selected = Nothing } -toUrl :: Route -> JSString -toUrl = ("#"<>) . partsToText . printRoute +toUrl :: Route -> Text +toUrl = ("#"<>) . printUrlParts . printRoute -fromUrl :: JSString -> Maybe Route +fromUrl :: Text -> Maybe Route fromUrl url = url - & JSS.stripPrefix "#" + & Text.stripPrefix "#" & fromMaybe url - & textToParts + & parseUrlParts & parseRoute -partsToText :: UrlParts -> JSString -partsToText (Url s q) = JSS.intercalate "?" (segments : query) +printUrlParts :: UrlParts -> Text +printUrlParts (Url s q) = Text.intercalate "?" (segments : query) where segments = - JSS.intercalate "/" $ fmap JSS.encodeURIComponent s + Text.intercalate "/" $ fmap encodeURIComponent s query = q - & fmap (bimap JSS.encodeURIComponent JSS.encodeURIComponent) + & fmap (bimap encodeURIComponent encodeURIComponent) & fmap (\(k, v) -> k <> "=" <> v) - & List.filter (not . JSS.null) - & JSS.intercalate "&" - & List.filter (not . JSS.null) . (:[]) + & List.filter (not . Text.null) + & Text.intercalate "&" + & List.filter (not . Text.null) . (:[]) -textToParts :: JSString -> UrlParts -textToParts t = Url segments query +parseUrlParts :: Text -> UrlParts +parseUrlParts t = Url segments query where (segmentsStr, queryStr) = breakOn1 "?" t segments = segmentsStr - & JSS.splitOn "/" - & List.filter (not . JSS.null) - & fmap JSS.decodeURIComponent + & Text.splitOn "/" + & List.filter (not . Text.null) + & fmap decodeURIComponent query = queryStr - & JSS.splitOn "&" - & List.filter (not . JSS.null) - & fmap (breakOn1 "=" . JSS.decodeURIComponent) + & Text.splitOn "&" + & List.filter (not . Text.null) + & fmap (breakOn1 "=" . decodeURIComponent) breakOn1 s t = - let (a, b) = JSS.breakOn s t in (a, JSS.drop 1 b) + let (a, b) = Text.breakOn s t in (a, Text.drop 1 b) + +encodeURIComponent :: Text -> Text +encodeURIComponent = + Text.pack . concatMap encodeChar . Text.unpack + where + encodeChar c + | C.isAlphaNum c = [c] + | c == ' ' = "+" + | otherwise = '%' : showHex (C.ord c) "" + showHex :: Int -> String -> String + showHex n acc + | n < 16 = intToDigit n : acc + | otherwise = let (q,r) = n `divMod` 16 in showHex q (intToDigit r : acc) + intToDigit :: Int -> Char + intToDigit n + | 0 <= n && n <= 9 = toEnum (fromEnum '0' + n) + | 10 <= n && n <= 15 = toEnum (fromEnum 'a' + n - 10) + | otherwise = error "intToDigit: not a digit" + +decodeURIComponent :: Text -> Text +decodeURIComponent = + Text.pack . decode . Text.unpack + where + decode [] = [] + decode ('%':x1:x2:xs) + | C.isHexDigit x1 && C.isHexDigit x2 = + C.chr (16 * digitToInt x1 + digitToInt x2) : decode xs + decode ('+':xs) = ' ' : decode xs + decode (x:xs) = x : decode xs + digitToInt :: Char -> Int + digitToInt c + | '0' <= c && c <= '9' = fromEnum c - fromEnum '0' + | 'a' <= c && c <= 'f' = fromEnum c - fromEnum 'a' + 10 + | 'A' <= c && c <= 'F' = fromEnum c - fromEnum 'A' + 10 + | otherwise = error "digitToInt: not a digit" diff --git a/htmlt.cabal b/htmlt.cabal index aa4d6b0..06fc6c4 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -133,25 +133,26 @@ executable htmlt-todomvc if !flag(examples) buildable: False --- executable htmlt-simple-routing --- import: htmlt-common --- main-is: simple-routing.hs --- hs-source-dirs: ./examples/simple-routing --- ghc-options: --- -no-hs-main -optl-mexec-model=reactor --- -optl-Wl,--export=hs_init,--export=wasm_main --- other-modules: --- Assets --- Router --- Pages --- Utils --- build-depends: --- base, --- bytestring, --- mtl, --- htmlt, --- if !flag(examples) --- buildable: False +executable htmlt-simple-routing + import: htmlt-common + main-is: simple-routing.hs + hs-source-dirs: ./examples/simple-routing + ghc-options: + -no-hs-main -optl-mexec-model=reactor + -optl-Wl,--export=hs_init,--export=wasm_main + other-modules: + Assets + Router + Pages + Utils + build-depends: + base, + bytestring, + mtl, + htmlt, + text, + if !flag(examples) + buildable: False -- executable htmlt-benchmarks -- import: htmlt-common diff --git a/shell.nix b/shell.nix index 8b5272f..ffda97a 100644 --- a/shell.nix +++ b/shell.nix @@ -1 +1 @@ -(import ./default.nix {}).shell.javascript +(import ./default.nix {}).shell.x86_64 diff --git a/src/HtmlT/DOM.hs b/src/HtmlT/DOM.hs index 90d9354..e1feb11 100644 --- a/src/HtmlT/DOM.hs +++ b/src/HtmlT/DOM.hs @@ -4,7 +4,10 @@ Functions and definitions to manipulate and query the DOM tree {-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ForeignFunctionInterface #-} + +#if defined(wasm32_HOST_ARCH) {-# LANGUAGE JavaScriptFFI #-} +#endif module HtmlT.DOM where import Control.Monad @@ -12,7 +15,7 @@ import Control.Monad.Reader import Control.Monad.Trans.Maybe import Data.Coerce import GHC.Exts as Exts -import GHC.Generics +import GHC.Generics hiding (R) import Unsafe.Coerce import Wasm.Compat.Prim import Wasm.Compat.Marshal @@ -39,7 +42,7 @@ on k = addEventListener (addEventListenerArgs @eventName) k data AddEventListenerArgs callback = AddEventListenerArgs { event_name :: Text , listener_options :: EventListenerOptions - , mk_callback :: callback -> JSVal -> Step () + , mk_callback :: callback -> JSVal -> R () } deriving (Generic) addEventListener :: AddEventListenerArgs callback -> callback -> Html () @@ -56,7 +59,7 @@ addEventListenerTarget -> callback -> m () addEventListenerTarget target args k = do - cb <- liftIO $ js_dynExport1 $ dynStep . args.mk_callback k + cb <- liftIO $ js_dynExport1 $ trampoline . args.mk_callback k jEventName <- liftIO $ toJSVal args.event_name -- jscb <- withopts hscb liftIO $ js_addEventListener target jEventName cb @@ -71,63 +74,63 @@ class IsEventName eventName where addEventListenerArgs :: AddEventListenerArgs (EventListenerCb eventName) instance IsEventName "click" where - type EventListenerCb "click" = Step () + type EventListenerCb "click" = R () addEventListenerArgs = pointerEventArgs "click" instance IsEventName "mousedown" where - type EventListenerCb "mousedown" = Step () + type EventListenerCb "mousedown" = R () addEventListenerArgs = pointerEventArgs "mousedown" instance IsEventName "mouseup" where - type EventListenerCb "mouseup" = Step () + type EventListenerCb "mouseup" = R () addEventListenerArgs = pointerEventArgs "mouseup" instance IsEventName "dblclick" where - type EventListenerCb "dblclick" = Step () + type EventListenerCb "dblclick" = R () addEventListenerArgs = pointerEventArgs "dblclick" instance IsEventName "submit" where - type EventListenerCb "submit" = Step () + type EventListenerCb "submit" = R () addEventListenerArgs = submitEventArgs instance IsEventName "input" where - type EventListenerCb "input" = Text -> Step () + type EventListenerCb "input" = Text -> R () addEventListenerArgs = inputEventArgs instance IsEventName "keydown" where - type EventListenerCb "keydown" = Int -> Step () + type EventListenerCb "keydown" = Int -> R () addEventListenerArgs = keyboardEventArgs "keydown" instance IsEventName "keyup" where - type EventListenerCb "keyup" = Int -> Step () + type EventListenerCb "keyup" = Int -> R () addEventListenerArgs = keyboardEventArgs "keyup" instance IsEventName "focus" where - type EventListenerCb "focus" = Step () + type EventListenerCb "focus" = R () addEventListenerArgs = pointerEventArgs "focus" instance IsEventName "blur" where - type EventListenerCb "blur" = Step () + type EventListenerCb "blur" = R () addEventListenerArgs = pointerEventArgs "blur" instance IsEventName "input/blur" where - type EventListenerCb "input/blur" = Text -> Step () + type EventListenerCb "input/blur" = Text -> R () addEventListenerArgs = inputEventArgs {event_name = "blur"} instance IsEventName "input/focus" where - type EventListenerCb "input/focus" = Text -> Step () + type EventListenerCb "input/focus" = Text -> R () addEventListenerArgs = inputEventArgs {event_name = "focus"} instance IsEventName "checkbox/change" where - type EventListenerCb "checkbox/change" = Bool -> Step () + type EventListenerCb "checkbox/change" = Bool -> R () addEventListenerArgs = checkboxChangeEventArgs instance IsEventName "select/change" where - type EventListenerCb "select/change" = Text -> Step () + type EventListenerCb "select/change" = Text -> R () addEventListenerArgs = selectChangeEventArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event -pointerEventArgs :: Text -> AddEventListenerArgs (Step ()) +pointerEventArgs :: Text -> AddEventListenerArgs (R ()) pointerEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -135,7 +138,7 @@ pointerEventArgs event_name = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event -submitEventArgs :: AddEventListenerArgs (Step ()) +submitEventArgs :: AddEventListenerArgs (R ()) submitEventArgs = AddEventListenerArgs { event_name = "submit" , listener_options = defaultSubmitOptions @@ -145,7 +148,7 @@ submitEventArgs = AddEventListenerArgs defaultSubmitOptions = EventListenerOptions True True -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event -inputEventArgs :: AddEventListenerArgs (Text -> Step ()) +inputEventArgs :: AddEventListenerArgs (Text -> R ()) inputEventArgs = AddEventListenerArgs { event_name = "input" , listener_options = defaultEventListenerOptions @@ -157,7 +160,7 @@ inputEventArgs = AddEventListenerArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardEventArgs :: Text -> AddEventListenerArgs (Int -> Step ()) +keyboardEventArgs :: Text -> AddEventListenerArgs (Int -> R ()) keyboardEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -170,7 +173,7 @@ keyboardEventArgs event_name = AddEventListenerArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event -focusEventArgs :: Text -> AddEventListenerArgs (Step ()) +focusEventArgs :: Text -> AddEventListenerArgs (R ()) focusEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -178,7 +181,7 @@ focusEventArgs event_name = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -checkboxChangeEventArgs :: AddEventListenerArgs (Bool -> Step ()) +checkboxChangeEventArgs :: AddEventListenerArgs (Bool -> R ()) checkboxChangeEventArgs = AddEventListenerArgs { event_name = "change" , listener_options = defaultEventListenerOptions @@ -189,7 +192,7 @@ checkboxChangeEventArgs = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -selectChangeEventArgs :: AddEventListenerArgs (Text -> Step ()) +selectChangeEventArgs :: AddEventListenerArgs (Text -> R ()) selectChangeEventArgs = AddEventListenerArgs { event_name = "change" , listener_options = defaultEventListenerOptions @@ -219,7 +222,7 @@ data Location = Location } deriving stock (Show, Eq, Generic) -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event -popstateEventArgs :: AddEventListenerArgs (Location -> Step ()) +popstateEventArgs :: AddEventListenerArgs (Location -> R ()) popstateEventArgs = AddEventListenerArgs { event_name = "popstate" , listener_options = defaultEventListenerOptions diff --git a/src/HtmlT/Event.hs b/src/HtmlT/Event.hs index 2d70fc9..c755080 100644 --- a/src/HtmlT/Event.hs +++ b/src/HtmlT/Event.hs @@ -25,146 +25,220 @@ import Data.Set qualified as Set import Data.Tuple import GHC.Exts import GHC.Fingerprint -import GHC.Generics +import GHC.Generics hiding (R) import Unsafe.Coerce +import Data.List qualified as List + +data ReactiveEnv = ReactiveEnv + { scope :: ReactiveScope + , reactive_state_ref :: IORef ReactiveState + } deriving (Generic) + +data ReactiveState = ReactiveState + { subscriptions :: Map EventId [(ReactiveScope, Any -> R ())] + , scopes :: Map ReactiveScope ReactiveNode + , transaction_queue :: Map EventId (R ()) + , id_supply :: Int + -- ^ Id supply for EventId and ReactiveScope + } deriving (Generic) + +newtype EventId = EventId { unEventId :: Int } + deriving newtype (Eq, Ord, Show, Num, Enum) + +newtype ReactiveScope = ReactiveScope { unReactiveScope :: Int } + deriving newtype (Show, Num, Ord, Eq) -- | Represents a stream of event occurrences of type @a@. Its actual -- representation is simply a function that subscribes to the event -newtype Event a = Event - { unEvent :: ReactiveEnv -> Callback a -> IO () - } +newtype Event a = Event { subscribe :: (a -> R ()) -> R () } + +instance Functor Event where + fmap f (Event s) = Event \k -> s . (. f) $ k -- | Contains a value that is subject to change over time. Provides -- operations for reading the current value ('readDyn') and -- subscribing to its future changes ('updates'). data Dynamic a = Dynamic - { dynamic_read :: IO a + { sample :: IO a -- ^ Read current value. Use public alias 'readDyn' instead - , dynamic_updates :: Event a + , updates :: Event a -- ^ Event that fires when the value changes. Use public alias -- 'updates' instead } deriving stock Generic +instance Functor Dynamic where + fmap f (Dynamic s u) = Dynamic (fmap f s) (fmap f u) + +instance Applicative Dynamic where + pure = constDyn + (<*>) = dynamicSplat + +dynamicSplat :: Dynamic (a -> b) -> Dynamic a -> Dynamic b +dynamicSplat df da = + let + updates = Event \k -> mdo + let + fire newF newA = defer queueId do + f <- liftIO $ maybe (readDyn df) pure newF + a <- liftIO $ maybe (readDyn da) pure newA + k (f a) + df.updates.subscribe \f -> fire (Just f) Nothing + da.updates.subscribe \a -> fire Nothing (Just a) + queueId <- EventId <$> reactive (const nextIntId) + return () + sample = liftA2 ($) df.sample da.sample + in + Dynamic {sample, updates} + -- | A mutable variable that allows for subscription to new values. It -- shares a similar API to 'IORef' (see 'readRef', 'writeRef', -- 'modifyRef') data DynRef a = DynRef - { dynref_dynamic :: Dynamic a + { dynamic :: Dynamic a -- ^ Holds the current value and an event that notifies about value -- modifications - , dynref_modifier :: Modifier a + , modifier :: Modifier a -- ^ Funtion to update the value } deriving stock Generic -- | Function that updates the value inside the 'DynRef' +-- 'Bool' argument controls whether the modification should +-- trigger an update event. It's possible to update the 'DynRef' +-- without notifying the subscribers for optimization purposes, in +-- cases when you know that all changes already been reflected in +-- the DOM newtype Modifier a = Modifier - { unModifier :: forall r. Bool -> (a -> (a, r)) -> Step r - -- ^ 'Bool' argument controls whether the modification should - -- trigger an update event. It's possible to update the 'DynRef' - -- without notifying the subscribers for optimization purposes, in - -- cases when you know that all changes already been reflected in - -- the DOM + { unModifier :: forall r. Bool -> (a -> (a, r)) -> R r } --- | State inside 'Step' -newtype TransactState = TransactState - { unTransactState :: Map QueueId (Step ()) - } deriving newtype (Semigroup, Monoid) +-- | Minimal implementation for 'HasReactiveEnv' +newtype ReactiveT m a = ReactiveT + { unReactiveT :: ReaderT ReactiveScope (StateT ReactiveState m) a + } + deriving newtype ( + Functor, Applicative, Monad, MonadIO, MonadFix, MonadCatch, MonadThrow, + MonadMask, MonadState ReactiveState, MonadReader ReactiveScope + ) --- | Evaluation of effects triggered by an event firing -newtype Step a = Step { unStep :: StateT TransactState IO a } - deriving newtype - ( Functor, Applicative, Monad, MonadIO, MonadState TransactState, MonadFix - , MonadCatch, MonadThrow, MonadMask - ) +newtype ReactivT m a = ReactivT + { unReactivT :: ReaderT ReactiveEnv m a + } + deriving newtype ( + Functor, Applicative, Monad, MonadIO, MonadFix, MonadCatch, MonadThrow, + MonadMask, MonadReader ReactiveEnv + ) --- | Represents the environment necessary for "reactive" operations, --- such as creating a new 'Event', subscribing to an event etc -data ReactiveEnv = ReactiveEnv - { renv_subscriptions :: IORef (Map QueueId [(QueueId, Callback Any)]) - -- ^ Keeps track of subscriptions - , renv_finalizers :: IORef (Map FinalizerKey FinalizerValue) - -- ^ Keeps track of finalizers. These finalizers will be activated - -- shortly before the current part of the application is terminated. - , renv_id_generator :: IORef QueueId - -- ^ Maintains the next value to be used for generating 'QueueId' - } deriving Generic +type Callback a = a -> R () --- | Minimal implementation for 'HasReactiveEnv' -newtype ReactiveT m a = ReactiveT - { unReactiveT :: ReaderT ReactiveEnv m a - } deriving newtype - ( Functor, Applicative, Monad, MonadIO, MonadFix, MonadCatch, MonadThrow - , MonadMask - ) - --- | Identifies a computation inside 'TransactState'. The integer --- value within 'QueueId' dictates the execution order in a reactive --- transaction (with higher values executing later). It is also --- utilized to prioritize events derived from other events, ensuring --- they are processed after the source events. This is basically the --- mechanism that prevents double-firing of Dynamics constructed --- using, for instance, the Applicative instance. -newtype QueueId = QueueId {unQueueId :: Int} - deriving newtype (Eq, Show, Ord, Num, Enum, Bounded) - -data FinalizerKey - = FinalizerEventId QueueId - | FinalizerQueueId QueueId - | FinalizerFingerprintId Fingerprint - deriving (Eq, Ord, Generic) - -data FinalizerValue - = SubscriptionSet (Set QueueId) - | CustomFinalizer (IO ()) - deriving Generic - -class HasReactiveEnv m where askReactiveEnv :: m ReactiveEnv - -type MonadReactive m = (HasReactiveEnv m, MonadIO m) +type R = ReactiveT IO -type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s +type Subscriptions = Map EventId [(ReactiveScope, Any -> R ())] -type Callback a = a -> Step () +type Finalizers = Map ReactiveScope ReactiveNode -type Trigger a = a -> Step () +data ReactiveNode = ReactiveNode + { nodes :: [ReactiveScope] + , parent :: Maybe ReactiveScope + , finalizers :: [R ()] + } deriving stock Generic --- | Create new empty 'ReactiveEnv' -newReactiveEnv :: MonadIO m => m ReactiveEnv -newReactiveEnv = liftIO do - renv_finalizers <- newIORef Map.empty - renv_subscriptions <- newIORef Map.empty - renv_id_generator <- newIORef $ QueueId 0 - return ReactiveEnv {..} +freeScope :: ReactiveScope -> R () +freeScope rscope = do + mRemovedNode <- state $ swap . freeScopeFn rscope + forM_ mRemovedNode \n -> do + sequence_ n.finalizers + forM_ n.nodes freeScope --- | Create new event and a function to supply values to that event --- --- > (event, push) <- newEvent @String --- > push "New Value" -- event fires with given value -newEvent :: forall a m. MonadReactive m => m (Event a, Trigger a) -newEvent = do - renv <- askReactiveEnv - eventId <- liftIO (nextQueueId renv) - let event = Event $ unsafeSubscribe eventId - return (event, unsafeTrigger eventId renv) - --- | Create a new 'DynRef' using given initial value --- --- > showRef <- newRef False --- > dynStep $ writeRef showRef True -- this triggers update event for showRef -newRef :: forall a m. MonadReactive m => a -> m (DynRef a) +freeScopeFn :: ReactiveScope -> ReactiveState -> (ReactiveState, Maybe ReactiveNode) +freeScopeFn rscope s = + let + (mRemovedNode, scopes0) = Map.alterF (,Nothing) rscope $ s.scopes + removedParent = mRemovedNode >>= (.parent) + subscriptions = unsubscribe s.subscriptions + scopes = maybe scopes0 (unlinkParentScope scopes0) removedParent + in + ((s::ReactiveState) { subscriptions, scopes }, mRemovedNode) + where + unsubscribe :: Subscriptions -> Subscriptions + unsubscribe s = + let + removeCollectEmpty a k b = + let c = filterSubscriptions b + in (if List.null c then k:a else a, c) + (emptyKeys, s1) = Map.mapAccumWithKey removeCollectEmpty [] s + in + List.foldl' (flip Map.delete) s1 emptyKeys + + unlinkParentScope :: Finalizers -> ReactiveScope -> Finalizers + unlinkParentScope f r = + Map.alter (fmap (\n -> n { nodes = List.filter (/=rscope) n.nodes })) r f + + filterSubscriptions [] = [] + filterSubscriptions ((s, c):xs) | s == rscope = xs + | otherwise = (s, c) : filterSubscriptions xs + +unsafeSubscribeFn :: EventId -> (a -> R ()) -> ReactiveScope -> ReactiveState -> ReactiveState +unsafeSubscribeFn eid k rs s = + let + insertSubscription (Just xs) = Just $ (rs, k . unsafeCoerce):xs + insertSubscription Nothing = Just [(rs, k . unsafeCoerce)] + in + s {subscriptions = Map.alter insertSubscription eid s.subscriptions } + +unsafeSubscribe :: EventId -> (a -> R ()) -> R () +unsafeSubscribe eid k = ask >>= \rs -> modify (unsafeSubscribeFn eid k rs) + +installFinalizer :: R () -> ReactiveScope -> ReactiveState -> ReactiveState +installFinalizer fin rs s = + let + insertFin (Just n) = Just $ n { finalizers = fin : n.finalizers} + insertFin Nothing = Nothing + in + s {scopes = Map.alter insertFin rs s.scopes } + +unsafeTrigger :: EventId -> a -> R () +unsafeTrigger eid a = defer eid do + callbacks <- gets $ fromMaybe [] . + Map.lookup eid . (.subscriptions) + forM_ callbacks $ ($ unsafeCoerce @_ @Any a) . snd + +newReactiveScopeFn :: ReactiveScope -> ReactiveState -> (ReactiveScope, ReactiveState) +newReactiveScopeFn parent s0 = + let + (s1, intId) = nextIntId s0 + rscope = ReactiveScope intId + scopes = Map.insert rscope (ReactiveNode [] (Just parent) []) s1.scopes + in + (rscope, s1 {scopes}) + +-- | Defers a computation (typically an event firing) until the end of +-- the current reactive transaction. This allows for the avoidance of +-- double firing of events constructed from multiple other events. +defer :: EventId -> R () -> R () +defer k act = modify \s -> s {transaction_queue = Map.insert k act s.transaction_queue} + +newEvent :: R (Event a, a -> R ()) +newEvent = state \s0 -> + let + (s1, eventId) = nextIntId s0 + event = Event $ unsafeSubscribe $ EventId eventId + trig = unsafeTrigger $ EventId eventId + in + ((event, trig), s1) + +newRef :: a -> R (DynRef a) newRef initial = do - ref <- liftIO $ newIORef initial + ioRef <- liftIO $ newIORef initial (event, push) <- newEvent let - modify = Modifier \u f -> do - (new, result) <- liftIO $ atomicModifyIORef' ref \old -> + modifier = Modifier \u f -> do + (new, result) <- liftIO $ atomicModifyIORef' ioRef \old -> let (new, result) = f old in (new, (new, result)) when u $ push new return result - dynamic = Dynamic (readIORef ref) event - return $ DynRef dynamic modify + dynamic = Dynamic (readIORef ioRef) event + return DynRef {dynamic, modifier} -- | Create a Dynamic that never changes its value constDyn :: a -> Dynamic a @@ -172,15 +246,15 @@ constDyn a = Dynamic (pure a) never -- | Event that will never fire never :: Event a -never = Event \_ _ -> return () +never = Event \ _ -> return () -- | Write new value into a 'DynRef' -- --- > ref <- newRef "Initial value" --- > transactionWrite ref "New value" +-- > ref <- newRef "Initial dynamic" +-- > transactionWrite ref "New dynamic" -- > readRef ref --- "New value" -writeRef :: DynRef a -> a -> Step () +-- "New dynamic" +writeRef :: DynRef a -> a -> R () writeRef ref a = modifyRef ref (const a) -- | Read the current value held by given 'DynRef' @@ -189,59 +263,37 @@ writeRef ref a = modifyRef ref (const a) -- > readRef ref -- "Hello there!" readRef :: MonadIO m => DynRef a -> m a -readRef = readDyn . dynref_dynamic +readRef = readDyn . (.dynamic) -- | Update a 'DynRef' by applying given function to the current value -- -- > ref <- newRef [1..3] -- > modifyRef ref $ fmap (*2) -- [2, 4, 6] -modifyRef :: DynRef a -> (a -> a) -> Step () +modifyRef :: DynRef a -> (a -> a) -> R () modifyRef (DynRef _ (Modifier mod)) f = mod True $ (,()) . f -- | Update a 'DynRef' with first field of the tuple and return back -- the second field. The name is intended to be similar to -- 'atomicModifyIORef' but there are no atomicity guarantees -- whatsoever -atomicModifyRef :: DynRef a -> (a -> (a, r)) -> Step r +atomicModifyRef :: DynRef a -> (a -> (a, r)) -> R r atomicModifyRef (DynRef _ (Modifier mod)) f = mod True f -- | Extract a 'Dynamic' out of 'DynRef' fromRef :: DynRef a -> Dynamic a -fromRef = dynref_dynamic +fromRef = (.dynamic) --- | Read the value held by a 'Dynamic' +-- | Read the dynamic held by a 'Dynamic' readDyn :: MonadIO m => Dynamic a -> m a -readDyn = liftIO . dynamic_read - --- | Extract the updates Event from a 'Dynamic' -updates :: Dynamic a -> Event a -updates = dynamic_updates - --- | Attach a listener to the event and return an action to detach the --- listener -subscribe :: MonadReactive m => Event a -> Callback a -> m () -subscribe (Event s) k = do - re <- askReactiveEnv - liftIO $ s re k +readDyn = liftIO . (.sample) -- | Executes an action currently held inside the 'Dynamic' and every --- time the value changes. -performDyn :: MonadReactive m => Dynamic (Step ()) -> m () +-- time the dynamic changes. +performDyn :: Dynamic (R ()) -> R () performDyn d = do - liftIO $ dynamic_read d >>= dynStep - subscribe (dynamic_updates d) id - --- | Apply a lens to the value inside 'DynRef' -lensMap :: forall s a. Lens' s a -> DynRef s -> DynRef a -lensMap l (DynRef sdyn (Modifier smod)) = - DynRef adyn (Modifier amod) - where - adyn = Dynamic - (fmap (getConst . l Const) $ dynamic_read sdyn) - (fmap (getConst . l Const) $ dynamic_updates sdyn) - amod :: forall r. Bool -> (a -> (a, r)) -> Step r - amod u f = smod u $ swap . l (swap . f) + join $ liftIO d.sample + d.updates.subscribe id -- | Return a 'Dynamic' for which updates only fire when the value -- actually changes according to Eq instance @@ -249,91 +301,83 @@ holdUniqDyn :: Eq a => Dynamic a -> Dynamic a holdUniqDyn = holdUniqDynBy (==) {-# INLINE holdUniqDyn #-} +-- TODO: The name could be mesleading because it works differently +-- compare to the holdUniqDynBy function in reflex. Unlike the +-- original this version will perform comparisons equal to +-- @number_of_updates × number_of_subscriptions@ as opposed to once +-- per update in reflex (I could be wrong in my understanding of +-- 'holdUniqDynBy' in Reflex) -- | Same as 'holdUniqDyn' but accepts arbitrary equality test -- function holdUniqDynBy :: (a -> a -> Bool) -> Dynamic a -> Dynamic a -holdUniqDynBy equalFn Dynamic{..} = Dynamic dynamic_read - (Event \e k -> do - old <- liftIO dynamic_read - oldRef <- liftIO (newIORef old) - unEvent dynamic_updates e \new -> do - old <- liftIO $ atomicModifyIORef' oldRef (new,) - unless (old `equalFn` new) $ k new - ) - --- | Execute the gives finalizers -applyFinalizer :: ReactiveEnv -> Map FinalizerKey FinalizerValue -> IO () -applyFinalizer ReactiveEnv{renv_subscriptions} finalizers = do - forM_ (Map.toList finalizers) \(k, v) -> case (k, v) of - (FinalizerEventId e, SubscriptionSet s) -> - modifyIORef' renv_subscriptions $ - flip Map.alter e $ mfilter (not . Prelude.null) . Just . deleteSubs s . fromMaybe [] - (_, CustomFinalizer io) -> - io - (_, _) -> - return () - where - deleteSubs _ss [] = [] - deleteSubs ss ((s, c):xs) - | Set.member s ss = xs - | otherwise = (s, c) : deleteSubs ss xs +holdUniqDynBy equalFn da = + let + updates = Event \k -> do + old <- liftIO da.sample + oldRef <- liftIO $ newIORef old + da.updates.subscribe \new -> do + old <- liftIO $ atomicModifyIORef' oldRef (new,) + unless (old `equalFn` new) $ k new + in + Dynamic {sample = da.sample, updates} + +-- | Produce a new Dynamic by applying a function to both the source +-- (Dynamic a) and previous value of itself +foldDynMaybe :: (a -> b -> Maybe b) -> b -> Dynamic a -> R (Dynamic b) +foldDynMaybe f initB dynA = do + initA <- liftIO dynA.sample + refB <- newRef $ fromMaybe initB $ f initA initB + dynA.updates.subscribe \newA -> do + oldB <- liftIO refB.dynamic.sample + forM_ (f newA oldB) $ writeRef refB + return refB.dynamic + +nextIntId :: ReactiveState -> (ReactiveState, Int) +nextIntId s = (s {id_supply = succ s.id_supply}, s.id_supply) -- | Alternative version if 'fmap' where given function will only be -- called once every time 'Dynamic a' value changes, whereas in 'fmap' -- it would be called once for each subscription per change event. As -- a general guideline, if the function @f! is inexpensive, choose -- @fmap f@. Otherwise, consider using @mapDyn f@. -mapDyn - :: MonadReactive m - => (a -> b) - -> Dynamic a - -> m (Dynamic b) -mapDyn fun adyn = do - initialA <- liftIO $ dynamic_read adyn +mapDyn :: (a -> b) -> Dynamic a -> R (Dynamic b) +mapDyn fun da = do + initialA <- liftIO $ da.sample latestA <- liftIO $ newIORef initialA latestB <- liftIO $ newIORef (fun initialA) - renv <- askReactiveEnv - eventId <- liftIO (nextQueueId renv) + eventId <- EventId <$> reactive (const nextIntId) let - updates = Event $ unsafeSubscribe eventId + updates = Event (unsafeSubscribe eventId) fire = defer eventId do newB <- liftIO $ fun <$> readIORef latestA liftIO $ writeIORef latestB newB - unsafeTrigger eventId renv newB - dynamic_updates adyn `subscribe` \newA -> do + unsafeTrigger eventId newB + da.updates.subscribe \newA -> do liftIO $ writeIORef latestA newA defer eventId fire return $ Dynamic (readIORef latestB) updates --- | Works same way as 'mapDyn' but applies to two dynamics -mapDyn2 - :: MonadReactive m - => (a -> b -> c) - -> Dynamic a - -> Dynamic b - -> m (Dynamic c) -mapDyn2 f adyn bdyn = do - unsafeMapDynN g [unsafeCoerce adyn, unsafeCoerce bdyn] - where - g [a, b] = return $ f (unsafeCoerce a) (unsafeCoerce b) - g _ = error "mapDyn2: impossible happend!" - --- | I hope three arguments will be enough for most cases if more --- needed it's easy to define this function in the application code --- with any required arity -mapDyn3 - :: MonadReactive m - => (a -> b -> c -> d) - -> Dynamic a - -> Dynamic b - -> Dynamic c - -> m (Dynamic d) -mapDyn3 f adyn bdyn cdyn = do - unsafeMapDynN g - [unsafeCoerce adyn, unsafeCoerce bdyn, unsafeCoerce cdyn] - where - g [a, b, c] = return $ f (unsafeCoerce a) (unsafeCoerce b) (unsafeCoerce c) - g _ = error "mapDyn3: impossible happend!" +mapDyn2 :: (a -> b -> c) -> Dynamic a -> Dynamic b -> R (Dynamic c) +mapDyn2 fun da db = do + initialA <- liftIO $ da.sample + initialB <- liftIO $ db.sample + latestA <- liftIO $ newIORef initialA + latestB <- liftIO $ newIORef initialB + latestC <- liftIO $ newIORef (fun initialA initialB) + eventId <- EventId <$> reactive (const nextIntId) + let + updates = Event (unsafeSubscribe eventId) + fire = defer eventId do + newC <- liftIO $ fun <$> (readIORef latestA) <*> (readIORef latestB) + liftIO $ writeIORef latestC newC + unsafeTrigger eventId newC + da.updates.subscribe \newA -> do + liftIO $ writeIORef latestA newA + defer eventId fire + db.updates.subscribe \newB -> do + liftIO $ writeIORef latestB newB + defer eventId fire + return $ Dynamic (readIORef latestC) updates -- | Takes a list of Dynamics and a function to generate the -- output. The positions of elements in the list of [Any] received by @@ -342,125 +386,75 @@ mapDyn3 f adyn bdyn cdyn = do -- function will fire at most once per transaction, and only if any of -- the input Dynamics change their values. unsafeMapDynN - :: MonadReactive m - => ([Any] -> IO a) + :: ([Any] -> IO a) -- ^ Construct the output value, from list of input values from -- corresponding positions of given Dynamics -> [Dynamic Any] -- ^ List of input Dynamics - -> m (Dynamic a) + -> R (Dynamic a) unsafeMapDynN fun dyns = do - renv <- askReactiveEnv - -- TODO: Try if list of IORefs is better than IORef of list - initialInputs <- liftIO $ mapM dynamic_read dyns + initialInputs <- liftIO $ mapM (.sample) dyns initialOutput <- liftIO $ fun initialInputs latestInputsRef <- liftIO $ newIORef initialInputs latestOutputRef <- liftIO $ newIORef initialOutput - eventId <- liftIO (nextQueueId renv) + eventId <- EventId <$> reactive (const nextIntId) let fire = defer eventId do newOutput <- liftIO $ fun =<< readIORef latestInputsRef liftIO $ writeIORef latestOutputRef newOutput - unsafeTrigger eventId renv newOutput - updates = Event $ unsafeSubscribe eventId + unsafeTrigger eventId newOutput + updates = Event (unsafeSubscribe eventId) updateList _ _ [] = [] updateList 0 a (_:xs) = a:xs updateList n a (x:xs) = x : updateList (pred n) a xs forM_ (zip [0..] dyns) \(i::Int, adyn) -> do - dynamic_updates adyn `subscribe` \newVal -> do + adyn.updates.subscribe \newVal -> do liftIO $ modifyIORef latestInputsRef $ updateList i newVal defer eventId fire return $ Dynamic (readIORef latestOutputRef) updates --- | Read and increment 'renv_id_generator' -nextQueueId :: ReactiveEnv -> IO QueueId -nextQueueId ReactiveEnv{renv_id_generator} = - atomicModifyIORef' renv_id_generator \eid -> (succ eid, eid) - --- | Defers a computation (typically an event firing) until the end of --- the current reactive transaction. This allows for the avoidance of --- double firing of events constructed from multiple other events. -defer :: QueueId -> Step () -> Step () -defer k act = - Step $ modify \(TransactState s) -> TransactState (Map.insert k act s) - --- | Run a reactive transaction. -dynStep :: MonadIO m => Step a -> m a -dynStep act = liftIO $ loop (TransactState Map.empty) act where - loop :: TransactState -> Step a -> IO a - loop rs (Step act) = do - (r, newRs) <- runStateT act rs - case popQueue newRs of - (Just newAct, newerRs) -> r <$ loop newerRs newAct - (Nothing, _newerRs) -> return r - popQueue intact@(TransactState m) = case Map.minViewWithKey m of - Just ((_, act), rest) -> (Just act, TransactState rest) - Nothing -> (Nothing, intact) - -runReactiveT :: ReactiveT m a -> ReactiveEnv -> m a -runReactiveT r = runReaderT (unReactiveT r) - -execReactiveT :: ReactiveEnv -> ReactiveT m a -> m a -execReactiveT = flip runReactiveT - -unsafeSubscribe :: QueueId -> ReactiveEnv -> Callback a -> IO () -unsafeSubscribe eventId e@ReactiveEnv{renv_subscriptions, renv_finalizers} k = do - subsId <- nextQueueId e - let - newCancel = (subsId, k . unsafeCoerce) - f (SubscriptionSet s1) (SubscriptionSet s2) = SubscriptionSet (s1 <> s2) - -- Unreacheable because FinalizerEventId always should map into - -- SubscriptionSet - f _ s = s - modifyIORef' renv_subscriptions $ - flip Map.alter eventId $ Just . (newCancel :) . fromMaybe [] - modifyIORef' renv_finalizers $ Map.insertWith f (FinalizerEventId eventId) - (SubscriptionSet (Set.singleton subsId)) - -unsafeTrigger :: QueueId -> ReactiveEnv -> a -> Step () -unsafeTrigger eventId ReactiveEnv{..} a = defer eventId do - subscriptions <- liftIO $ readIORef renv_subscriptions - let callbacks = fromMaybe [] $ Map.lookup eventId subscriptions - for_ callbacks $ ($ unsafeCoerce @_ @Any a) . snd - -instance Functor Event where - fmap f (Event s) = Event \e k -> s e . (. f) $ k +reactive :: (ReactiveScope -> ReactiveState -> (ReactiveState, a)) -> R a +reactive f = ReactiveT $ ReaderT \rs -> StateT $ pure . swap . f rs --- | Please be aware that in cases where both events fire during the --- same 'Step,' the one having a higher 'EventId' will win, which is --- very hard to predict, use with caution. -instance Semigroup a => Semigroup (Event a) where - (<>) (Event e1) (Event e2) = Event \e k -> mdo - e1 e (defer eventId . k) - e2 e (defer eventId . k) - eventId <- nextQueueId e - return () +reactive_ :: (ReactiveScope -> ReactiveState -> ReactiveState) -> R () +reactive_ f = ReactiveT $ ReaderT \rs -> StateT $ pure . ((),) . f rs -instance Semigroup a => Monoid (Event a) where - mempty = never - -instance Functor Dynamic where - fmap f (Dynamic s u) = Dynamic (fmap f s) (fmap f u) +type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s -instance Applicative Dynamic where - pure = constDyn - (<*>) df da = - let - updatesEvent = Event \e k -> mdo - let - fire newF newA = defer eventId do - f <- liftIO $ maybe (readDyn df) pure newF - a <- liftIO $ maybe (readDyn da) pure newA - k (f a) - unEvent (updates df) e \f -> fire (Just f) Nothing - unEvent (updates da) e \a -> fire Nothing (Just a) - eventId <- nextQueueId e - return () - in - Dynamic - { dynamic_read = liftA2 ($) (dynamic_read df) (dynamic_read da) - , dynamic_updates = updatesEvent - } - -instance Applicative m => HasReactiveEnv (ReactiveT m) where - askReactiveEnv = ReactiveT $ ReaderT pure +-- | Apply a lens to the value inside 'DynRef' +lensMap :: forall s a. Lens' s a -> DynRef s -> DynRef a +lensMap l s = + let + dynamic = Dynamic + (fmap (getConst . l Const) s.dynamic.sample) + (fmap (getConst . l Const) s.dynamic.updates) + modifier = Modifier \u f -> + unModifier s.modifier u $ swap . l (swap . f) + in + DynRef {dynamic, modifier} + +-- | Loop until transaction_queue is empty +trampoline :: R a -> R a +trampoline act = loop0 act where + loop0 :: R a -> R a + loop0 act = do + r <- act + loop1 =<< gets (.transaction_queue) + return r + loop1 :: Map EventId (R ()) -> R () + loop1 q = + case Map.minViewWithKey q of + Nothing -> return () + Just ((_, newAct), newQueue) -> do + modify \s -> s {transaction_queue = newQueue} + newAct + loop1 =<< gets (.transaction_queue) + +execReactiveT :: ReactiveScope -> ReactiveState -> ReactiveT m a -> m (a, ReactiveState) +execReactiveT scope state = flip runStateT state . flip runReaderT scope . unReactiveT + +class MonadReactive m where + reactiv :: (ReactiveScope -> ReactiveState -> (ReactiveState, a)) -> m a + +reactiv_ :: MonadReactive m => (ReactiveScope -> ReactiveState -> ReactiveState) -> m () +reactiv_ f = reactiv (\r s -> (,()) $ f r s) diff --git a/src/HtmlT/Types.hs b/src/HtmlT/Types.hs index d53e64c..f3feab6 100644 --- a/src/HtmlT/Types.hs +++ b/src/HtmlT/Types.hs @@ -24,12 +24,10 @@ data HtmlEnv = HtmlEnv , html_content_boundary :: Maybe ContentBoundary -- ^ Boundary defined by parent scope where new content should be -- attached, when Nothing whole parent element is available - , html_reactive_env :: ReactiveEnv - -- ^ Needed to implement 'HasReactiveEnv' } deriving Generic -- | Most applications will only need HtmlT IO, hence this shortcut -type Html = HtmlT IO +type Html = HtmlT (ReactiveT IO) -- | A newtype over JSVal which is an instance of Node -- https://developer.mozilla.org/en-US/docs/Web/API/Node @@ -71,6 +69,3 @@ instance (Semigroup a, Applicative m) => Semigroup (HtmlT m a) where instance (Monoid a, Applicative m) => Monoid (HtmlT m a) where mempty = HtmlT $ ReaderT \_ -> pure mempty - -instance Monad m => HasReactiveEnv (HtmlT m) where - askReactiveEnv = asks html_reactive_env diff --git a/src/Wasm/Compat/Marshal.hs b/src/Wasm/Compat/Marshal.hs index 6909f3b..5010b72 100644 --- a/src/Wasm/Compat/Marshal.hs +++ b/src/Wasm/Compat/Marshal.hs @@ -1,9 +1,11 @@ {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ForeignFunctionInterface #-} -{-# LANGUAGE JavaScriptFFI #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE UnboxedTuples #-} +#if defined(wasm32_HOST_ARCH) +{-# LANGUAGE JavaScriptFFI #-} +#endif module Wasm.Compat.Marshal where import Control.Monad @@ -160,7 +162,7 @@ js_arrayPush :: JSVal -> JSVal -> IO () = undefined js_arrayLength :: JSVal -> IO Int = undefined js_arrayIndex :: JSVal -> Int -> IO JSVal = undefined js_decodeUtf8 :: Ptr Word8 -> Int -> IO JSString = undefined -js_encodeUtf8 :: JSString -> Ptr Word8 -> Int -> IO () = undefined +js_encodeUtf8 :: JSString -> Ptr Word8 -> Int -> IO Int = undefined js_stringLength :: JSString -> IO Int = undefined #else From ba63efc852e879f8d2ddf3d1b5c3178c9b08fe3f Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sat, 16 Mar 2024 01:04:28 +0400 Subject: [PATCH 04/64] Upstream changes from htmlt-wasm --- examples/todomvc/TodoItem.hs | 30 +++--- examples/todomvc/TodoList.hs | 120 +++++++++++----------- examples/todomvc/Utils.hs | 7 +- examples/todomvc/todomvc.hs | 17 +++- htmlt.cabal | 40 ++++---- src/HtmlT/Base.hs | 116 ++++++++++------------ src/HtmlT/DOM.hs | 144 +++++++-------------------- src/HtmlT/Event.hs | 187 +++++++++++++++++++---------------- src/HtmlT/Internal.hs | 2 +- src/HtmlT/Main.hs | 46 ++++----- src/HtmlT/Types.hs | 3 +- 11 files changed, 319 insertions(+), 393 deletions(-) diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index fae17fe..31b2e0c 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -11,9 +11,9 @@ import Wasm.Compat.Prim import "this" Utils data TodoItemConfig = TodoItemConfig - { state_ref :: DynRef TodoItemState + { self :: DynRef TodoItemState , is_hidden_dyn :: Dynamic Bool - , ask_delete_item :: Step () + , ask_delete_item :: RX () } data TodoItemState = TodoItemState @@ -30,26 +30,26 @@ data TodoItemAction a where CheckedAction :: TodoItemConfig -> Bool -> TodoItemAction () KeydownAction :: TodoItemConfig -> Int -> TodoItemAction () -eval :: TodoItemAction a -> Step a +eval :: TodoItemAction a -> RX a eval = \case CancelAction cfg -> - modifyRef cfg.state_ref \s -> s{editing=Nothing} + modifyRef cfg.self \s -> s{editing=Nothing} CommitAction cfg -> do - state <- readRef cfg.state_ref + state <- readRef cfg.self case state.editing of Just "" -> cfg.ask_delete_item Just t -> - modifyRef cfg.state_ref \s -> s {editing=Nothing, title = t} + modifyRef cfg.self \s -> s {editing=Nothing, title = t} Nothing -> pure () InputAction cfg newVal -> - modifyRef cfg.state_ref \s -> s{editing = Just newVal} + modifyRef cfg.self \s -> s{editing = Just newVal} DoubleClickAction cfg targetEl -> do - modifyRef cfg.state_ref \s -> s {editing = Just s.title} + modifyRef cfg.self \s -> s {editing = Just s.title} liftIO $ js_todoItemInputFocus targetEl CheckedAction cfg isChecked -> do - modifyRef cfg.state_ref \s -> s{completed = isChecked} + modifyRef cfg.self \s -> s{completed = isChecked} KeydownAction cfg key -> case key of 13 {- Enter -} -> eval (CommitAction cfg) 27 {- Escape -} -> eval (CancelAction cfg) @@ -58,18 +58,18 @@ eval = \case html :: TodoItemConfig -> Html () html cfg = li_ do let - completedDyn = (.completed) <$> fromRef cfg.state_ref - editingDyn = isJust . (.editing) <$> fromRef cfg.state_ref - valueDyn = fromMaybe "" . (.editing) <$> fromRef cfg.state_ref + completedDyn = (.completed) <$> fromRef cfg.self + editingDyn = isJust . (.editing) <$> fromRef cfg.self + valueDyn = fromMaybe "" . (.editing) <$> fromRef cfg.self toggleClass "completed" completedDyn toggleClass "editing" editingDyn toggleClass "hidden" cfg.is_hidden_dyn div_ [class_ "view"] do on @DblClickWithTarget $ eval . DoubleClickAction cfg input_ [class_ "toggle", type_ "checkbox"] do - dynChecked $ (.completed) <$> fromRef cfg.state_ref + dynChecked $ (.completed) <$> fromRef cfg.self on @"checkbox/change" $ eval . CheckedAction cfg - label_ $ dynText $ (.title) <$> fromRef cfg.state_ref + label_ $ dynText $ (.title) <$> fromRef cfg.self button_ [class_ "destroy"] do on @"click" cfg.ask_delete_item input_ [class_ "edit", type_ "text"] do @@ -105,7 +105,7 @@ instance FromJSVal TodoItemState where data DblClickWithTarget instance IsEventName DblClickWithTarget where - type EventListenerCb DblClickWithTarget = JSVal -> Step () + type EventListenerCb DblClickWithTarget = JSVal -> RX () addEventListenerArgs = AddEventListenerArgs { event_name = "dblclick" , listener_options = defaultEventListenerOptions diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index 1f8c83d..31168a1 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -15,12 +15,12 @@ import "this" TodoItem qualified as TodoItem import "this" Utils data TodoListConfig = TodoListConfig - { state_ref :: DynRef TodoListState + { self :: DynRef TodoListState } data TodoListState = TodoListState { title :: Text - , items :: [TodoItem.TodoItemState] + , todos :: [TodoItem.TodoItemState] , filter :: Filter } deriving (Show, Eq, Generic) @@ -32,52 +32,54 @@ newtype LocalStorageTodoItems = LocalStorageTodoItems } deriving newtype (ToJSVal, FromJSVal) data TodoListAction a where - InitAction :: ReactiveEnv -> DynRef Text -> TodoListAction (DynRef TodoListState) - ToggleAllAction :: TodoListConfig -> Bool -> TodoListAction () - InputAction :: TodoListConfig -> Text -> TodoListAction () - CommitAction :: TodoListConfig -> TodoListAction () - KeydownAction :: TodoListConfig -> Int -> TodoListAction () - DeleteItemAction :: TodoListConfig -> Int -> TodoListAction () - ClearCompletedAction :: TodoListConfig -> TodoListAction () + UpdateFilter :: Filter -> TodoListAction () + PersistCurrentState :: TodoListAction () + ToggleAllAction :: Bool -> TodoListAction () + InputAction :: Text -> TodoListAction () + CommitAction :: TodoListAction () + KeydownAction :: Int -> TodoListAction () + DeleteItemAction :: Int -> TodoListAction () + ClearCompletedAction :: TodoListAction () -eval :: TodoListAction a -> Step a -eval = \case - InitAction renv urlHashRef -> do - let parseFilter' = fromMaybe All . parseFilter - todos <- fromMaybe [] . fmap unLocalStorageTodoItems <$> liftIO localStorageGet - initFilter <- parseFilter' <$> readRef urlHashRef - todosRef <- execReactiveT renv do - todosRef <- newRef $ TodoListState "" todos initFilter - subscribe (updates (fromRef urlHashRef)) $ - modifyRef todosRef . (\v s -> s{filter=v}) . parseFilter' - return todosRef - liftIO $ onBeforeUnload do - TodoListState{items} <- readRef todosRef - localStorageSet $ LocalStorageTodoItems items - return todosRef - ToggleAllAction cfg isChecked -> - modifyRef cfg.state_ref \s -> s - { items = - fmap (\i -> i {TodoItem.completed = isChecked}) s.items +new :: Filter -> RX (DynRef TodoListState) +new filter = do + todos <- fromMaybe [] . fmap unLocalStorageTodoItems <$> liftIO localStorageGet + newRef TodoListState + { todos + , filter + , title = "" + } + +eval :: TodoListConfig -> TodoListAction a -> RX a +eval cfg = \case + UpdateFilter filter -> + modifyRef cfg.self \s -> s {filter} + PersistCurrentState -> do + todosState <- readRef cfg.self + liftIO $ localStorageSet $ LocalStorageTodoItems todosState.todos + ToggleAllAction isChecked -> + modifyRef cfg.self \s -> s + { todos = + fmap (\i -> i {TodoItem.completed = isChecked}) s.todos } - InputAction cfg newVal -> do - modifyRef cfg.state_ref \s -> s {title = newVal} - CommitAction cfg -> do - title <- {- JSS.strip . -} (.title) <$> readRef cfg.state_ref + InputAction newVal -> do + modifyRef cfg.self \s -> s {title = newVal} + CommitAction -> do + title <- Text.strip . (.title) <$> readRef cfg.self case title of "" -> return () - t -> modifyRef cfg.state_ref \s -> s - { items = s.items <> [mkNewItem t] + t -> modifyRef cfg.self \s -> s + { todos = s.todos <> [mkNewItem t] , title = "" } - KeydownAction cfg key -> case key of - 13 {- Enter -} -> eval (CommitAction cfg) + KeydownAction key -> case key of + 13 {- Enter -} -> eval cfg CommitAction _ -> return () - DeleteItemAction cfg itemIx -> - modifyRef cfg.state_ref \s -> s {items = deleteIx itemIx s.items} - ClearCompletedAction cfg -> - modifyRef cfg.state_ref \s -> s - {items = (List.filter (not . TodoItem.completed)) s.items} + DeleteItemAction itemIx -> + modifyRef cfg.self \s -> s {todos = deleteIx itemIx s.todos} + ClearCompletedAction -> + modifyRef cfg.self \s -> s + {todos = (List.filter (not . TodoItem.completed)) s.todos} where deleteIx :: Int -> [a] -> [a] deleteIx _ [] = [] @@ -100,13 +102,13 @@ html cfg = do headerWidget = header_ [class_ "header"] do h1_ (text "todos") input_ [class_ "new-todo", placeholder_ "What needs to be done?", autofocus_ True] do - dynValue $ (.title) <$> fromRef cfg.state_ref - on @"input" $ eval . InputAction cfg - on @"keydown" $ eval . KeydownAction cfg + dynValue $ (.title) <$> fromRef cfg.self + on @"input" $ eval cfg . InputAction + on @"keydown" $ eval cfg . KeydownAction mainWidget = section_ [class_ "main"] do toggleClass "hidden" hiddenDyn input_ [id_ "toggle-all", class_ "toggle-all", type_ "checkbox"] do - on @"checkbox/change" $ eval . ToggleAllAction cfg + on @"checkbox/change" $ eval cfg . ToggleAllAction return () label_ do attr "for" "toggle-all" @@ -114,22 +116,22 @@ html cfg = do ul_ [class_ "todo-list"] do simpleList itemsDyn \idx todoRef -> TodoItem.html $ TodoItem.TodoItemConfig - { TodoItem.state_ref = todoRef - { dynref_modifier = todoItemModifier cfg idx todoRef.dynref_modifier + { TodoItem.self = todoRef + { modifier = todoItemModifier cfg idx todoRef.modifier } , TodoItem.is_hidden_dyn = - isTodoItemHidden <$> fromRef cfg.state_ref <*> fromRef todoRef - , TodoItem.ask_delete_item = eval (DeleteItemAction cfg idx) + isTodoItemHidden <$> fromRef cfg.self <*> fromRef todoRef + , TodoItem.ask_delete_item = eval cfg (DeleteItemAction idx) } footerWidget = footer_ [class_ "footer"] do toggleClass "hidden" hiddenDyn span_ [class_ "todo-count"] do strong_ $ dynText $ Text.pack . show <$> itemsLeftDyn - dynText $ pluralize " item left" " items left" <$> itemsLeftDyn + dynText $ pluralize " item left" " todos left" <$> itemsLeftDyn ul_ [class_ "filters"] do for_ [All, Active, Completed] filterWidget button_ [class_ "clear-completed"] do - on @"click" $ eval (ClearCompletedAction cfg) + on @"click" $ eval cfg ClearCompletedAction text "Clear completed" footerInfoWidget = footer_ [class_ "info"] do p_ "Double-click to edit a todo" @@ -144,16 +146,16 @@ html cfg = do toggleClass "selected" $ filterSelectedDyn flt text $ Text.pack $ show flt hiddenDyn = - Prelude.null . (.items) <$> fromRef cfg.state_ref + Prelude.null . (.todos) <$> fromRef cfg.self itemsLeftDyn = - countItemsLeft <$> fromRef cfg.state_ref + countItemsLeft <$> fromRef cfg.self filterSelectedDyn flt = - (==flt) . (.filter) <$> fromRef cfg.state_ref + (==flt) . (.filter) <$> fromRef cfg.self itemsDyn = - (.items) <$> fromRef cfg.state_ref - countItemsLeft TodoListState{items} = + (.todos) <$> fromRef cfg.self + countItemsLeft TodoListState{todos} = foldl (\acc TodoItem.TodoItemState{completed} -> - if not completed then acc + 1 else acc) 0 items + if not completed then acc + 1 else acc) 0 todos isTodoItemHidden listState itemState = case (listState.filter, itemState.completed) of (Active, True) -> True @@ -176,8 +178,8 @@ todoItemModifier cfg idx elemModifier = Modifier \upd f -> do -- widget for the sake of optimization needsUpdate = upd && (old.completed /= new.completed) -- Update the outer widget - unModifier (dynref_modifier cfg.state_ref) needsUpdate \old -> - (old {items = overIx idx (const new) old.items}, ()) + unModifier cfg.self.modifier needsUpdate \old -> + (old {todos = overIx idx (const new) old.todos}, ()) return result where overIx :: Int -> (a -> a) -> [a] -> [a] diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs index f533339..fecca52 100644 --- a/examples/todomvc/Utils.hs +++ b/examples/todomvc/Utils.hs @@ -11,14 +11,15 @@ import Data.Text (Text) import Wasm.Compat.Prim import Wasm.Compat.Marshal -mkUrlHashRef :: MonadReactive m => m (DynRef Text) +mkUrlHashRef :: RX (DynRef Text) mkUrlHashRef = do + reactiveEnv <- ask initial <- liftIO $ textFromJSString =<< js_readUrlHash routeRef <- newRef initial win <- getCurrentWindow popStateCb <- liftIO $ js_dynExport1 \_ -> - js_readUrlHash >>= textFromJSString >>= dynStep . writeRef routeRef - liftIO $ js_addEventListener win ((\(JSString j) -> j) $ toJSString "onpopstate") popStateCb + js_readUrlHash >>= textFromJSString >>= launchReactiveT reactiveEnv . writeRef routeRef + liftIO $ js_addEventListener win ((\(JSString j) -> j) $ toJSString "popstate") popStateCb return routeRef localStorageSet :: forall a m. (MonadIO m, ToJSVal a, Typeable a) => a -> m () diff --git a/examples/todomvc/todomvc.hs b/examples/todomvc/todomvc.hs index a453b25..7df4c3a 100644 --- a/examples/todomvc/todomvc.hs +++ b/examples/todomvc/todomvc.hs @@ -1,6 +1,7 @@ import Control.Monad import Control.Monad.Reader import HtmlT +import Data.Maybe import "this" TodoList qualified as TodoList import "this" Utils @@ -10,7 +11,15 @@ main = return () foreign export ccall wasm_main :: IO () wasm_main = void $ attachToBody do - renv <- asks (.html_reactive_env) - urlHashRef <- mkUrlHashRef - todosRef <- dynStep $ TodoList.eval (TodoList.InitAction renv urlHashRef) - TodoList.html $ TodoList.TodoListConfig todosRef + reactiveEnv <- lift ask + urlHashRef <- lift mkUrlHashRef + let parseFilter = fromMaybe TodoList.All . TodoList.parseFilter + filter <- parseFilter <$> readRef urlHashRef + todosListInst <- lift $ TodoList.new filter + let cfg = TodoList.TodoListConfig todosListInst + lift $ urlHashRef.dynamic.updates.subscribe \newUrl -> do + let newFilter = parseFilter newUrl + TodoList.eval cfg $ TodoList.UpdateFilter newFilter + liftIO $ onBeforeUnload $ launchReactiveT reactiveEnv $ + TodoList.eval cfg TodoList.PersistCurrentState + TodoList.html cfg diff --git a/htmlt.cabal b/htmlt.cabal index 06fc6c4..f89d8d3 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -133,26 +133,26 @@ executable htmlt-todomvc if !flag(examples) buildable: False -executable htmlt-simple-routing - import: htmlt-common - main-is: simple-routing.hs - hs-source-dirs: ./examples/simple-routing - ghc-options: - -no-hs-main -optl-mexec-model=reactor - -optl-Wl,--export=hs_init,--export=wasm_main - other-modules: - Assets - Router - Pages - Utils - build-depends: - base, - bytestring, - mtl, - htmlt, - text, - if !flag(examples) - buildable: False +-- executable htmlt-simple-routing +-- import: htmlt-common +-- main-is: simple-routing.hs +-- hs-source-dirs: ./examples/simple-routing +-- ghc-options: +-- -no-hs-main -optl-mexec-model=reactor +-- -optl-Wl,--export=hs_init,--export=wasm_main +-- other-modules: +-- Assets +-- Router +-- Pages +-- Utils +-- build-depends: +-- base, +-- bytestring, +-- mtl, +-- htmlt, +-- text, +-- if !flag(examples) +-- buildable: False -- executable htmlt-benchmarks -- import: htmlt-common diff --git a/src/HtmlT/Base.hs b/src/HtmlT/Base.hs index b19e1a7..dde8804 100644 --- a/src/HtmlT/Base.hs +++ b/src/HtmlT/Base.hs @@ -5,11 +5,9 @@ module HtmlT.Base where import Control.Monad import Control.Monad.Reader -import Control.Monad.Trans.Maybe -import Data.Foldable -import Data.IORef -import Data.Map qualified as Map import Data.Text +import Data.IORef +import Data.Foldable import HtmlT.DOM import HtmlT.Event @@ -54,7 +52,7 @@ dynText :: Dynamic Text -> Html () dynText d = do txt <- readDyn d textNode <- liftIO (createTextNode txt) - void $ subscribe (updates d) \new -> void $ liftIO do + lift $ d.updates.subscribe \new -> void $ liftIO do setTextValue textNode new insertNode textNode @@ -78,7 +76,7 @@ dynProp key dyn = do jKey <- liftIO $ textToJSString key el <- asks html_current_element let setup el t = toJSVal t >>= js_setProp el.unDOMElement jKey - performDyn $ liftIO . setup el <$> dyn + lift $ performDyn $ liftIO . setup el <$> dyn -- | Assign an attribute to the root element. Don't confuse attributes -- and properties @@ -92,7 +90,7 @@ attr k v = do dynAttr :: Text -> Dynamic Text -> Html () dynAttr k d = do el <- asks html_current_element - performDyn $ liftIO . setAttribute el k <$> d + lift $ performDyn $ liftIO . setAttribute el k <$> d -- | Assign CSS classes to the current root element. Compared to @prop -- "className"@ can be used multiple times for the same root @@ -117,7 +115,7 @@ dynAttr k d = do toggleClass :: Text -> Dynamic Bool -> Html () toggleClass cs dyn = do rootEl <- asks html_current_element - performDyn $ liftIO . setup rootEl cs <$> dyn + lift $ performDyn $ liftIO . setup rootEl cs <$> dyn where setup rootEl cs = \case True -> classListAdd rootEl cs @@ -135,7 +133,7 @@ toggleClass cs dyn = do toggleAttr :: Text -> Dynamic Bool -> Html () toggleAttr att dyn = do rootEl <- asks html_current_element - performDyn $ liftIO . setup rootEl att <$> dyn + lift $ performDyn $ liftIO . setup rootEl att <$> dyn where setup rootEl name = \case True -> setAttribute rootEl name "on" @@ -153,7 +151,7 @@ dynStyle :: Text -> Dynamic Text -> Html () dynStyle cssProp dyn = do rootEl <- asks html_current_element jCssProp <- liftIO $ textToJSString cssProp - performDyn $ liftIO . setup jCssProp rootEl <$> dyn + lift $ performDyn $ liftIO . setup jCssProp rootEl <$> dyn where setup jCssProp el t = do styleVal <- js_getProp el.unDOMElement $ toJSString "style" @@ -182,50 +180,56 @@ simpleList -- collection and dynamic data for that particular element -> Html () simpleList listDyn h = do - boundary <- insertBoundary - htmlEnv <- asks \h -> h {html_content_boundary = Just boundary} + outerBoundary <- insertBoundary + htmlEnv <- asks \h -> h {html_content_boundary = Just outerBoundary} + outerReactiveEnv <- lift ask prevValue <- liftIO $ newIORef [] elemEnvsRef <- liftIO $ newIORef ([] :: [ElemEnv a]) let - setup :: Int -> [a] -> [ElemEnv a] -> Step [ElemEnv a] + exec :: ElemEnv a -> Html x -> RX x + exec e = local (const e.ee_reactive_env) . + execHtmlT e.ee_html_env + setup :: Int -> [a] -> [ElemEnv a] -> RX [ElemEnv a] setup idx new existing = case (existing, new) of ([], []) -> return [] -- New list is longer, append new elements ([], x:xs) -> do - finalizers <- liftIO $ newIORef Map.empty - elementRef <- liftIO $ execReactiveT (html_reactive_env htmlEnv) $ newRef x - boundary <- liftIO $ execHtmlT htmlEnv insertBoundary + elementScope <- newReactiveScope + elementRef <- newRef x + elementBoundary <- execHtmlT htmlEnv insertBoundary let - elementEnv = htmlEnv - { html_reactive_env = (html_reactive_env htmlEnv) - { renv_finalizers = finalizers } - , html_content_boundary = Just boundary + elementHtmlEnv = htmlEnv + { html_content_boundary = Just elementBoundary + } + elementReactiveEnv = outerReactiveEnv + { scope = elementScope } - liftIO $ execHtmlT elementEnv $ h idx elementRef - let newElem = ElemEnv elementEnv elementRef - fmap (newElem:) $ setup (idx + 1) xs [] + let elementEnv = ElemEnv elementHtmlEnv elementReactiveEnv elementRef + exec elementEnv $ h idx elementRef + fmap (elementEnv:) $ setup (idx + 1) xs [] -- New list is shorter, delete the elements that no longer -- present in the new list (r:rs, []) -> do - liftIO $ finalizeElems True (r:rs) + finalizeElems True (r:rs) return [] -- Update child elements along the way (r:rs, y:ys) -> do writeRef (ee_dyn_ref r) y fmap (r:) $ setup (idx + 1) ys rs - finalizeElems remove = traverse_ \ElemEnv{ee_html_env} -> do + finalizeElems remove = traverse_ \ee -> do when remove $ - mapM_ removeBoundary $ html_content_boundary ee_html_env - let re = html_reactive_env ee_html_env - finalizers <- readIORef $ renv_finalizers re - applyFinalizer re finalizers + liftIO $ mapM_ removeBoundary $ ee.ee_html_env.html_content_boundary + freeScope ee.ee_reactive_env.scope updateList new = do old <- liftIO $ atomicModifyIORef' prevValue (new,) eenvs <- liftIO $ readIORef elemEnvsRef newEenvs <- setup 0 new eenvs liftIO $ writeIORef elemEnvsRef newEenvs - performDyn $ updateList <$> listDyn - void $ installFinalizer $ readIORef elemEnvsRef >>= finalizeElems False + cleanup = do + old <- liftIO $ readIORef elemEnvsRef + finalizeElems False old + lift $ performDyn $ fmap updateList listDyn + lift $ installFinalizer cleanup -- | First build a DOM with the widget that is currently held by the -- given Dynamic, then rebuild it every time Dynamic's value @@ -243,45 +247,25 @@ simpleList listDyn h = do dyn :: Dynamic (Html ()) -> Html () dyn d = do htmlEnv <- ask - childRef <- liftIO (newIORef Nothing) boundary <- insertBoundary + newScope <- lift newReactiveScope + initialVal <- readDyn d let - finalizeEnv newEnv = do - readIORef childRef >>= \case - Just HtmlEnv{html_reactive_env} -> do - finalizers <- atomicModifyIORef' (renv_finalizers html_reactive_env) (Map.empty,) - applyFinalizer html_reactive_env finalizers - Nothing -> return () - writeIORef childRef newEnv - setup html = liftIO do - finalizers <- newIORef Map.empty - let - newEnv = htmlEnv - { html_reactive_env = (html_reactive_env htmlEnv) - { renv_finalizers = finalizers } - , html_content_boundary = Just boundary - } - finalizeEnv (Just newEnv) - clearBoundary boundary - execHtmlT newEnv html - installFinalizer (finalizeEnv Nothing) - performDyn $ setup <$> d - --- | Run an action before the current node is detached from the DOM -installFinalizer :: MonadReactive m => IO () -> m FinalizerKey -installFinalizer fin = do - renv <- askReactiveEnv - finalizerId <- liftIO $ nextQueueId renv - let finalizerKey = FinalizerQueueId finalizerId - liftIO $ modifyIORef renv.renv_finalizers $ - Map.insert finalizerKey $ CustomFinalizer fin - return finalizerKey + update html = do + liftIO $ clearBoundary boundary + html + exec = local (\s -> s {scope = newScope}) . + execHtmlT htmlEnv {html_content_boundary = Just boundary} + lift $ exec $ update initialVal + lift $ d.updates.subscribe \newVal -> do + freeScope newScope + exec $ update newVal -- | Attach resulting DOM to the given node instead of -- 'html_current_element'. Might be useful for implementing modal -- dialogs, tooltips etc. Similar to what called portals in React -- ecosystem -portal :: MonadIO m => DOMElement -> HtmlT m a -> HtmlT m a +portal :: DOMElement -> Html a -> Html a portal newRootEl html = do boundary <- local (\e -> e { html_current_element = newRootEl @@ -291,7 +275,7 @@ portal newRootEl html = do { html_current_element = newRootEl , html_content_boundary = Just boundary }) html - installFinalizer $ removeBoundary boundary + lift $ installFinalizer $ liftIO $ removeBoundary boundary return result -- | Parse given text as HTML and attach the resulting tree to @@ -304,9 +288,9 @@ portal newRootEl html = do -- > unsafeHtml "\ -- > \\ -- > \" -unsafeHtml :: MonadIO m => Text -> HtmlT m () +unsafeHtml :: Text -> Html () unsafeHtml htmlText = do henv <- ask - let anchor = fmap boundary_end henv.html_content_boundary + let anchor = fmap (.boundary_end) henv.html_content_boundary liftIO $ unsafeInsertHtml henv.html_current_element anchor htmlText diff --git a/src/HtmlT/DOM.hs b/src/HtmlT/DOM.hs index e1feb11..fe66f7e 100644 --- a/src/HtmlT/DOM.hs +++ b/src/HtmlT/DOM.hs @@ -10,20 +10,15 @@ Functions and definitions to manipulate and query the DOM tree #endif module HtmlT.DOM where -import Control.Monad import Control.Monad.Reader -import Control.Monad.Trans.Maybe -import Data.Coerce +import Data.Kind +import Data.Text import GHC.Exts as Exts -import GHC.Generics hiding (R) -import Unsafe.Coerce -import Wasm.Compat.Prim -import Wasm.Compat.Marshal -import HtmlT.Types +import GHC.Generics hiding (RX) import HtmlT.Event -import Data.Text - -import Data.Kind +import HtmlT.Types +import Wasm.Compat.Marshal +import Wasm.Compat.Prim data EventListenerOptions = EventListenerOptions { prevent_default :: Bool @@ -42,7 +37,7 @@ on k = addEventListener (addEventListenerArgs @eventName) k data AddEventListenerArgs callback = AddEventListenerArgs { event_name :: Text , listener_options :: EventListenerOptions - , mk_callback :: callback -> JSVal -> R () + , mk_callback :: callback -> JSVal -> RX () } deriving (Generic) addEventListener :: AddEventListenerArgs callback -> callback -> Html () @@ -53,13 +48,13 @@ addEventListener args k = do -- | EventTarget.addEventListener() -- https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener addEventListenerTarget - :: MonadIO m - => JSVal + :: JSVal -> AddEventListenerArgs callback -> callback - -> m () + -> Html () addEventListenerTarget target args k = do - cb <- liftIO $ js_dynExport1 $ trampoline . args.mk_callback k + e <- lift ask + cb <- liftIO $ js_dynExport1 $ launchReactiveT e . args.mk_callback k jEventName <- liftIO $ toJSVal args.event_name -- jscb <- withopts hscb liftIO $ js_addEventListener target jEventName cb @@ -74,63 +69,63 @@ class IsEventName eventName where addEventListenerArgs :: AddEventListenerArgs (EventListenerCb eventName) instance IsEventName "click" where - type EventListenerCb "click" = R () + type EventListenerCb "click" = RX () addEventListenerArgs = pointerEventArgs "click" instance IsEventName "mousedown" where - type EventListenerCb "mousedown" = R () + type EventListenerCb "mousedown" = RX () addEventListenerArgs = pointerEventArgs "mousedown" instance IsEventName "mouseup" where - type EventListenerCb "mouseup" = R () + type EventListenerCb "mouseup" = RX () addEventListenerArgs = pointerEventArgs "mouseup" instance IsEventName "dblclick" where - type EventListenerCb "dblclick" = R () + type EventListenerCb "dblclick" = RX () addEventListenerArgs = pointerEventArgs "dblclick" instance IsEventName "submit" where - type EventListenerCb "submit" = R () + type EventListenerCb "submit" = RX () addEventListenerArgs = submitEventArgs instance IsEventName "input" where - type EventListenerCb "input" = Text -> R () + type EventListenerCb "input" = Text -> RX () addEventListenerArgs = inputEventArgs instance IsEventName "keydown" where - type EventListenerCb "keydown" = Int -> R () + type EventListenerCb "keydown" = Int -> RX () addEventListenerArgs = keyboardEventArgs "keydown" instance IsEventName "keyup" where - type EventListenerCb "keyup" = Int -> R () + type EventListenerCb "keyup" = Int -> RX () addEventListenerArgs = keyboardEventArgs "keyup" instance IsEventName "focus" where - type EventListenerCb "focus" = R () + type EventListenerCb "focus" = RX () addEventListenerArgs = pointerEventArgs "focus" instance IsEventName "blur" where - type EventListenerCb "blur" = R () + type EventListenerCb "blur" = RX () addEventListenerArgs = pointerEventArgs "blur" instance IsEventName "input/blur" where - type EventListenerCb "input/blur" = Text -> R () + type EventListenerCb "input/blur" = Text -> RX () addEventListenerArgs = inputEventArgs {event_name = "blur"} instance IsEventName "input/focus" where - type EventListenerCb "input/focus" = Text -> R () + type EventListenerCb "input/focus" = Text -> RX () addEventListenerArgs = inputEventArgs {event_name = "focus"} instance IsEventName "checkbox/change" where - type EventListenerCb "checkbox/change" = Bool -> R () + type EventListenerCb "checkbox/change" = Bool -> RX () addEventListenerArgs = checkboxChangeEventArgs instance IsEventName "select/change" where - type EventListenerCb "select/change" = Text -> R () + type EventListenerCb "select/change" = Text -> RX () addEventListenerArgs = selectChangeEventArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event -pointerEventArgs :: Text -> AddEventListenerArgs (R ()) +pointerEventArgs :: Text -> AddEventListenerArgs (RX ()) pointerEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -138,7 +133,7 @@ pointerEventArgs event_name = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event -submitEventArgs :: AddEventListenerArgs (R ()) +submitEventArgs :: AddEventListenerArgs (RX ()) submitEventArgs = AddEventListenerArgs { event_name = "submit" , listener_options = defaultSubmitOptions @@ -148,7 +143,7 @@ submitEventArgs = AddEventListenerArgs defaultSubmitOptions = EventListenerOptions True True -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event -inputEventArgs :: AddEventListenerArgs (Text -> R ()) +inputEventArgs :: AddEventListenerArgs (Text -> RX ()) inputEventArgs = AddEventListenerArgs { event_name = "input" , listener_options = defaultEventListenerOptions @@ -160,7 +155,7 @@ inputEventArgs = AddEventListenerArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardEventArgs :: Text -> AddEventListenerArgs (Int -> R ()) +keyboardEventArgs :: Text -> AddEventListenerArgs (Int -> RX ()) keyboardEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -173,7 +168,7 @@ keyboardEventArgs event_name = AddEventListenerArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event -focusEventArgs :: Text -> AddEventListenerArgs (R ()) +focusEventArgs :: Text -> AddEventListenerArgs (RX ()) focusEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -181,7 +176,7 @@ focusEventArgs event_name = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -checkboxChangeEventArgs :: AddEventListenerArgs (Bool -> R ()) +checkboxChangeEventArgs :: AddEventListenerArgs (Bool -> RX ()) checkboxChangeEventArgs = AddEventListenerArgs { event_name = "change" , listener_options = defaultEventListenerOptions @@ -192,7 +187,7 @@ checkboxChangeEventArgs = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -selectChangeEventArgs :: AddEventListenerArgs (Text -> R ()) +selectChangeEventArgs :: AddEventListenerArgs (Text -> RX ()) selectChangeEventArgs = AddEventListenerArgs { event_name = "change" , listener_options = defaultEventListenerOptions @@ -222,7 +217,7 @@ data Location = Location } deriving stock (Show, Eq, Generic) -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event -popstateEventArgs :: AddEventListenerArgs (Location -> R ()) +popstateEventArgs :: AddEventListenerArgs (Location -> RX ()) popstateEventArgs = AddEventListenerArgs { event_name = "popstate" , listener_options = defaultEventListenerOptions @@ -371,13 +366,6 @@ data MouseDelta = MouseDelta , md_delta_z :: Int } deriving stock (Eq, Show, Generic) --- mouseDeltaDecoder :: MonadIO m => JSVal -> MaybeT m MouseDelta --- mouseDeltaDecoder mouseEvent = do --- md_delta_x <- propDecoder "deltaX" mouseEvent --- md_delta_y <- propDecoder "deltaY" mouseEvent --- md_delta_z <- propDecoder "deltaZ" mouseEvent --- return MouseDelta {..} - -- | Pair of two values, might denote either a size or coordinates in -- different contexts data Point a = Point @@ -385,72 +373,6 @@ data Point a = Point , pt_y :: a } deriving stock (Eq, Show, Ord, Functor, Generic) --- -- | Read clientX and clientY properties from MouseEvent --- -- https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent --- clientXYDecoder :: MonadIO m => JSVal -> MaybeT m (Point Int) --- clientXYDecoder mouseEvent = do --- pt_x <- propDecoder "clientX" mouseEvent --- pt_y <- propDecoder "clientY" mouseEvent --- return Point {..} - --- -- | Read offsetX and offsetY properties from MouseEvent --- -- https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent --- offsetXYDecoder :: MonadIO m => JSVal -> MaybeT m (Point Int) --- offsetXYDecoder mouseEvent = do --- pt_x <- propDecoder "offsetX" mouseEvent --- pt_y <- propDecoder "offsetY" mouseEvent --- return Point {..} - --- -- | Read pageX and pageY properties from MouseEvent --- -- https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent --- pageXYDecoder :: MonadIO m => JSVal -> MaybeT m (Point Int) --- pageXYDecoder mouseEvent = do --- pt_x <- propDecoder "pageX" mouseEvent --- pt_y <- propDecoder "pageY" mouseEvent --- return Point {..} - --- -- | Collection of altKey, ctrlKey, metaKey and shiftKey properties --- -- from KeyboardEvent --- data KeyModifiers = KeyModifiers --- { kmod_alt_key :: Bool --- , kmod_ctrl_key :: Bool --- , kmod_meta_key :: Bool --- , kmod_shift_key :: Bool --- } deriving stock (Eq, Show, Generic) - --- -- | Read altKey, ctrlKey, metaKey and shiftKey properties from --- -- KeyboardEvent --- -- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent --- keyModifiersDecoder :: MonadIO m => JSVal -> MaybeT m KeyModifiers --- keyModifiersDecoder keyEvent = do --- kmod_alt_key <- propDecoder "altKey" keyEvent --- kmod_ctrl_key <- propDecoder "ctrlKey" keyEvent --- kmod_meta_key <- propDecoder "metaKey" keyEvent --- kmod_shift_key <- propDecoder "shiftKey" keyEvent --- return KeyModifiers {..} - --- -- | Read keyCode properties from KeyboardEvent --- -- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode --- keyCodeDecoder :: MonadIO m => JSVal -> MaybeT m Int --- keyCodeDecoder = propDecoder "keyCode" - --- -- | Collection of some useful information from KeyboardEvent --- data KeyboardEvent = KeyboardEvent --- { ke_modifiers :: KeyModifiers --- , ke_key :: Maybe JSString --- , ke_key_code :: Int --- , ke_repeat :: Bool --- } deriving stock (Generic) - --- -- | Read information from KeyboardEvent --- keyboardEventDecoder :: MonadIO m => JSVal -> MaybeT m KeyboardEvent --- keyboardEventDecoder keyEvent = do --- ke_modifiers <- keyModifiersDecoder keyEvent --- ke_key <- propDecoder "key" keyEvent --- ke_key_code <- propDecoder "keyCode" keyEvent --- ke_repeat <- propDecoder "repeat" keyEvent --- return KeyboardEvent {..} - errorGhcjsOnly :: a errorGhcjsOnly = error "Only GHCJS is supported" diff --git a/src/HtmlT/Event.hs b/src/HtmlT/Event.hs index c755080..2b64f9b 100644 --- a/src/HtmlT/Event.hs +++ b/src/HtmlT/Event.hs @@ -25,23 +25,38 @@ import Data.Set qualified as Set import Data.Tuple import GHC.Exts import GHC.Fingerprint -import GHC.Generics hiding (R) +import GHC.Generics import Unsafe.Coerce import Data.List qualified as List +import Data.Function data ReactiveEnv = ReactiveEnv { scope :: ReactiveScope , reactive_state_ref :: IORef ReactiveState } deriving (Generic) +newReactiveEnv :: IO ReactiveEnv +newReactiveEnv = do + let scope = ReactiveScope emptyReactiveState.id_supply + reactive_state_ref <- newIORef emptyReactiveState + return ReactiveEnv {reactive_state_ref, scope} + data ReactiveState = ReactiveState - { subscriptions :: Map EventId [(ReactiveScope, Any -> R ())] + { subscriptions :: Map EventId [(ReactiveScope, Any -> RX ())] , scopes :: Map ReactiveScope ReactiveNode - , transaction_queue :: Map EventId (R ()) + , transaction_queue :: Map EventId (RX ()) , id_supply :: Int -- ^ Id supply for EventId and ReactiveScope } deriving (Generic) +emptyReactiveState :: ReactiveState +emptyReactiveState = ReactiveState + { subscriptions = Map.empty + , scopes = Map.empty + , transaction_queue = Map.empty + , id_supply = 0 + } + newtype EventId = EventId { unEventId :: Int } deriving newtype (Eq, Ord, Show, Num, Enum) @@ -50,20 +65,20 @@ newtype ReactiveScope = ReactiveScope { unReactiveScope :: Int } -- | Represents a stream of event occurrences of type @a@. Its actual -- representation is simply a function that subscribes to the event -newtype Event a = Event { subscribe :: (a -> R ()) -> R () } +newtype Event a = Event { subscribe :: (a -> RX ()) -> RX () } instance Functor Event where fmap f (Event s) = Event \k -> s . (. f) $ k --- | Contains a value that is subject to change over time. Provides --- operations for reading the current value ('readDyn') and --- subscribing to its future changes ('updates'). +-- | Represens a value that changes over time. Provides operations for +-- sampling the current value — 'readDyn' and for listening to future +-- changes 'updates'. data Dynamic a = Dynamic { sample :: IO a - -- ^ Read current value. Use public alias 'readDyn' instead + -- ^ Read current value held by Dynamic , updates :: Event a - -- ^ Event that fires when the value changes. Use public alias - -- 'updates' instead + -- ^ Event fires every time value changes, carries the new value of + -- the Dynamic } deriving stock Generic instance Functor Dynamic where @@ -108,43 +123,37 @@ data DynRef a = DynRef -- cases when you know that all changes already been reflected in -- the DOM newtype Modifier a = Modifier - { unModifier :: forall r. Bool -> (a -> (a, r)) -> R r + { unModifier :: forall r. Bool -> (a -> (a, r)) -> RX r } --- | Minimal implementation for 'HasReactiveEnv' -newtype ReactiveT m a = ReactiveT - { unReactiveT :: ReaderT ReactiveScope (StateT ReactiveState m) a - } - deriving newtype ( - Functor, Applicative, Monad, MonadIO, MonadFix, MonadCatch, MonadThrow, - MonadMask, MonadState ReactiveState, MonadReader ReactiveScope - ) - -newtype ReactivT m a = ReactivT - { unReactivT :: ReaderT ReactiveEnv m a +newtype RX a = RX + { unRX :: ReaderT ReactiveEnv IO a } deriving newtype ( Functor, Applicative, Monad, MonadIO, MonadFix, MonadCatch, MonadThrow, MonadMask, MonadReader ReactiveEnv ) -type Callback a = a -> R () +instance MonadReactive RX where + reactive f = RX $ ReaderT $ \e -> + liftIO $ atomicModifyIORef' e.reactive_state_ref $ f e.scope + {-# INLINE reactive #-} -type R = ReactiveT IO +type Callback a = a -> RX () -type Subscriptions = Map EventId [(ReactiveScope, Any -> R ())] +type Subscriptions = Map EventId [(ReactiveScope, Any -> RX ())] type Finalizers = Map ReactiveScope ReactiveNode data ReactiveNode = ReactiveNode { nodes :: [ReactiveScope] , parent :: Maybe ReactiveScope - , finalizers :: [R ()] + , finalizers :: [RX ()] } deriving stock Generic -freeScope :: ReactiveScope -> R () +freeScope :: ReactiveScope -> RX () freeScope rscope = do - mRemovedNode <- state $ swap . freeScopeFn rscope + mRemovedNode <- reactive $ const $ freeScopeFn rscope forM_ mRemovedNode \n -> do sequence_ n.finalizers forM_ n.nodes freeScope @@ -177,7 +186,7 @@ freeScopeFn rscope s = filterSubscriptions ((s, c):xs) | s == rscope = xs | otherwise = (s, c) : filterSubscriptions xs -unsafeSubscribeFn :: EventId -> (a -> R ()) -> ReactiveScope -> ReactiveState -> ReactiveState +unsafeSubscribeFn :: EventId -> (a -> RX ()) -> ReactiveScope -> ReactiveState -> ReactiveState unsafeSubscribeFn eid k rs s = let insertSubscription (Just xs) = Just $ (rs, k . unsafeCoerce):xs @@ -185,48 +194,55 @@ unsafeSubscribeFn eid k rs s = in s {subscriptions = Map.alter insertSubscription eid s.subscriptions } -unsafeSubscribe :: EventId -> (a -> R ()) -> R () -unsafeSubscribe eid k = ask >>= \rs -> modify (unsafeSubscribeFn eid k rs) +unsafeSubscribe :: EventId -> (a -> RX ()) -> RX () +unsafeSubscribe eid k = reactive_ (unsafeSubscribeFn eid k) -installFinalizer :: R () -> ReactiveScope -> ReactiveState -> ReactiveState -installFinalizer fin rs s = +installFinalizerFn :: RX () -> ReactiveScope -> ReactiveState -> ReactiveState +installFinalizerFn fin rs s = let insertFin (Just n) = Just $ n { finalizers = fin : n.finalizers} insertFin Nothing = Nothing in s {scopes = Map.alter insertFin rs s.scopes } -unsafeTrigger :: EventId -> a -> R () -unsafeTrigger eid a = defer eid do - callbacks <- gets $ fromMaybe [] . - Map.lookup eid . (.subscriptions) - forM_ callbacks $ ($ unsafeCoerce @_ @Any a) . snd +installFinalizer :: RX () -> RX () +installFinalizer fin = reactive_ (installFinalizerFn fin) + +unsafeTrigger :: EventId -> a -> RX () +unsafeTrigger eid a = do + defer eid do + callbacks <- reactive \_ s -> + (s, s.subscriptions & Map.lookup eid & fromMaybe []) + forM_ callbacks $ ($ unsafeCoerce @_ @Any a) . snd -newReactiveScopeFn :: ReactiveScope -> ReactiveState -> (ReactiveScope, ReactiveState) +newReactiveScopeFn :: ReactiveScope -> ReactiveState -> (ReactiveState, ReactiveScope) newReactiveScopeFn parent s0 = let (s1, intId) = nextIntId s0 rscope = ReactiveScope intId scopes = Map.insert rscope (ReactiveNode [] (Just parent) []) s1.scopes in - (rscope, s1 {scopes}) + (s1 {scopes}, rscope) + +newReactiveScope :: RX ReactiveScope +newReactiveScope = reactive newReactiveScopeFn -- | Defers a computation (typically an event firing) until the end of -- the current reactive transaction. This allows for the avoidance of -- double firing of events constructed from multiple other events. -defer :: EventId -> R () -> R () -defer k act = modify \s -> s {transaction_queue = Map.insert k act s.transaction_queue} +defer :: EventId -> RX () -> RX () +defer k act = reactive_ \_ s -> s {transaction_queue = Map.insert k act s.transaction_queue} -newEvent :: R (Event a, a -> R ()) -newEvent = state \s0 -> +newEvent :: RX (Event a, a -> RX ()) +newEvent = reactive \_ s0 -> let (s1, eventId) = nextIntId s0 event = Event $ unsafeSubscribe $ EventId eventId trig = unsafeTrigger $ EventId eventId in - ((event, trig), s1) + (s1, (event, trig)) -newRef :: a -> R (DynRef a) +newRef :: a -> RX (DynRef a) newRef initial = do ioRef <- liftIO $ newIORef initial (event, push) <- newEvent @@ -254,7 +270,7 @@ never = Event \ _ -> return () -- > transactionWrite ref "New dynamic" -- > readRef ref -- "New dynamic" -writeRef :: DynRef a -> a -> R () +writeRef :: DynRef a -> a -> RX () writeRef ref a = modifyRef ref (const a) -- | Read the current value held by given 'DynRef' @@ -270,14 +286,14 @@ readRef = readDyn . (.dynamic) -- > ref <- newRef [1..3] -- > modifyRef ref $ fmap (*2) -- [2, 4, 6] -modifyRef :: DynRef a -> (a -> a) -> R () +modifyRef :: DynRef a -> (a -> a) -> RX () modifyRef (DynRef _ (Modifier mod)) f = mod True $ (,()) . f -- | Update a 'DynRef' with first field of the tuple and return back -- the second field. The name is intended to be similar to -- 'atomicModifyIORef' but there are no atomicity guarantees -- whatsoever -atomicModifyRef :: DynRef a -> (a -> (a, r)) -> R r +atomicModifyRef :: DynRef a -> (a -> (a, r)) -> RX r atomicModifyRef (DynRef _ (Modifier mod)) f = mod True f -- | Extract a 'Dynamic' out of 'DynRef' @@ -290,7 +306,7 @@ readDyn = liftIO . (.sample) -- | Executes an action currently held inside the 'Dynamic' and every -- time the dynamic changes. -performDyn :: Dynamic (R ()) -> R () +performDyn :: Dynamic (RX ()) -> RX () performDyn d = do join $ liftIO d.sample d.updates.subscribe id @@ -301,12 +317,6 @@ holdUniqDyn :: Eq a => Dynamic a -> Dynamic a holdUniqDyn = holdUniqDynBy (==) {-# INLINE holdUniqDyn #-} --- TODO: The name could be mesleading because it works differently --- compare to the holdUniqDynBy function in reflex. Unlike the --- original this version will perform comparisons equal to --- @number_of_updates × number_of_subscriptions@ as opposed to once --- per update in reflex (I could be wrong in my understanding of --- 'holdUniqDynBy' in Reflex) -- | Same as 'holdUniqDyn' but accepts arbitrary equality test -- function holdUniqDynBy :: (a -> a -> Bool) -> Dynamic a -> Dynamic a @@ -323,7 +333,7 @@ holdUniqDynBy equalFn da = -- | Produce a new Dynamic by applying a function to both the source -- (Dynamic a) and previous value of itself -foldDynMaybe :: (a -> b -> Maybe b) -> b -> Dynamic a -> R (Dynamic b) +foldDynMaybe :: (a -> b -> Maybe b) -> b -> Dynamic a -> RX (Dynamic b) foldDynMaybe f initB dynA = do initA <- liftIO dynA.sample refB <- newRef $ fromMaybe initB $ f initA initB @@ -338,9 +348,9 @@ nextIntId s = (s {id_supply = succ s.id_supply}, s.id_supply) -- | Alternative version if 'fmap' where given function will only be -- called once every time 'Dynamic a' value changes, whereas in 'fmap' -- it would be called once for each subscription per change event. As --- a general guideline, if the function @f! is inexpensive, choose +-- a general guideline, if the function @f@ is inexpensive, choose -- @fmap f@. Otherwise, consider using @mapDyn f@. -mapDyn :: (a -> b) -> Dynamic a -> R (Dynamic b) +mapDyn :: (a -> b) -> Dynamic a -> RX (Dynamic b) mapDyn fun da = do initialA <- liftIO $ da.sample latestA <- liftIO $ newIORef initialA @@ -357,7 +367,7 @@ mapDyn fun da = do defer eventId fire return $ Dynamic (readIORef latestB) updates -mapDyn2 :: (a -> b -> c) -> Dynamic a -> Dynamic b -> R (Dynamic c) +mapDyn2 :: (a -> b -> c) -> Dynamic a -> Dynamic b -> RX (Dynamic c) mapDyn2 fun da db = do initialA <- liftIO $ da.sample initialB <- liftIO $ db.sample @@ -391,7 +401,7 @@ unsafeMapDynN -- corresponding positions of given Dynamics -> [Dynamic Any] -- ^ List of input Dynamics - -> R (Dynamic a) + -> RX (Dynamic a) unsafeMapDynN fun dyns = do initialInputs <- liftIO $ mapM (.sample) dyns initialOutput <- liftIO $ fun initialInputs @@ -403,7 +413,7 @@ unsafeMapDynN fun dyns = do newOutput <- liftIO $ fun =<< readIORef latestInputsRef liftIO $ writeIORef latestOutputRef newOutput unsafeTrigger eventId newOutput - updates = Event (unsafeSubscribe eventId) + updates = Event $ unsafeSubscribe eventId updateList _ _ [] = [] updateList 0 a (_:xs) = a:xs updateList n a (x:xs) = x : updateList (pred n) a xs @@ -413,12 +423,6 @@ unsafeMapDynN fun dyns = do defer eventId fire return $ Dynamic (readIORef latestOutputRef) updates -reactive :: (ReactiveScope -> ReactiveState -> (ReactiveState, a)) -> R a -reactive f = ReactiveT $ ReaderT \rs -> StateT $ pure . swap . f rs - -reactive_ :: (ReactiveScope -> ReactiveState -> ReactiveState) -> R () -reactive_ f = ReactiveT $ ReaderT \rs -> StateT $ pure . ((),) . f rs - type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s -- | Apply a lens to the value inside 'DynRef' @@ -434,27 +438,36 @@ lensMap l s = DynRef {dynamic, modifier} -- | Loop until transaction_queue is empty -trampoline :: R a -> R a +trampoline :: RX a -> RX a trampoline act = loop0 act where - loop0 :: R a -> R a - loop0 act = do - r <- act - loop1 =<< gets (.transaction_queue) + loop0 :: RX a -> RX a + loop0 before = do + r <- before + mcont <- popQueue + forM_ mcont loop1 return r - loop1 :: Map EventId (R ()) -> R () - loop1 q = - case Map.minViewWithKey q of - Nothing -> return () - Just ((_, newAct), newQueue) -> do - modify \s -> s {transaction_queue = newQueue} - newAct - loop1 =<< gets (.transaction_queue) - -execReactiveT :: ReactiveScope -> ReactiveState -> ReactiveT m a -> m (a, ReactiveState) -execReactiveT scope state = flip runStateT state . flip runReaderT scope . unReactiveT + loop1 :: RX () -> RX () + loop1 before = do + before + mcont <- popQueue + forM_ mcont loop1 + popQueue :: RX (Maybe (RX ())) + popQueue = reactive \_ s -> + case Map.minViewWithKey s.transaction_queue of + Nothing -> (s, Nothing) + Just ((_, r), newQueue) -> (s {transaction_queue = newQueue}, Just r) + +launchReactiveT :: ReactiveEnv -> RX a -> IO a +launchReactiveT e = execReactiveT e . trampoline + +execReactiveT :: ReactiveEnv -> RX a -> IO a +execReactiveT e = flip runReaderT e . unRX + +runReactiveT :: RX a -> ReactiveEnv -> IO a +runReactiveT = flip execReactiveT class MonadReactive m where - reactiv :: (ReactiveScope -> ReactiveState -> (ReactiveState, a)) -> m a + reactive :: (ReactiveScope -> ReactiveState -> (ReactiveState, a)) -> m a -reactiv_ :: MonadReactive m => (ReactiveScope -> ReactiveState -> ReactiveState) -> m () -reactiv_ f = reactiv (\r s -> (,()) $ f r s) +reactive_ :: MonadReactive m => (ReactiveScope -> ReactiveState -> ReactiveState) -> m () +reactive_ f = reactive (\r s -> (,()) $ f r s) diff --git a/src/HtmlT/Internal.hs b/src/HtmlT/Internal.hs index 0c39110..0fab4e4 100644 --- a/src/HtmlT/Internal.hs +++ b/src/HtmlT/Internal.hs @@ -2,7 +2,6 @@ module HtmlT.Internal where import Control.Monad.Reader import GHC.Generics -import Wasm.Compat.Prim import HtmlT.Event import HtmlT.Types @@ -11,6 +10,7 @@ import HtmlT.DOM -- | Auxiliary type helps to implement 'simpleList' data ElemEnv a = ElemEnv { ee_html_env :: HtmlEnv + , ee_reactive_env :: ReactiveEnv , ee_dyn_ref :: DynRef a } deriving Generic diff --git a/src/HtmlT/Main.hs b/src/HtmlT/Main.hs index 4ab705a..74ce53d 100644 --- a/src/HtmlT/Main.hs +++ b/src/HtmlT/Main.hs @@ -1,27 +1,23 @@ -- | Start and stop browser application module HtmlT.Main where -import Control.Monad -import Data.IORef import GHC.Generics -import Wasm.Compat.Prim - import HtmlT.DOM import HtmlT.Event import HtmlT.Types -data StartOpts = StartOpts - { startopts_reactive_env :: ReactiveEnv +data AttachOptions = AttachOptions + { reactive_env :: ReactiveEnv -- ^ Typically the program should only have one instance of -- 'ReactiveEnv', so when there are multiple running 'HtmlT' -- applications, use this field to share existing 'ReactiveEnv' -- between all of them - , startopts_root_element :: DOMElement + , root_element :: DOMElement -- ^ HTMLElement where to attach the elements created by the -- application - , startopts_wait_document_load :: Bool + , wait_document_load :: Bool -- ^ If True block IO action until main document is fully loaded - , startopts_unload_call_finalizers :: Bool + , unload_call_finalizers :: Bool -- ^ If True run finalizers on @beforeunload@ event. This happens -- just before browser tab is closed, the code in finalizers should -- only consist of non-blocking IO @@ -30,39 +26,40 @@ data StartOpts = StartOpts -- | Needed to manually finalize and detach the application data RunningApp = RunningApp { runapp_html_env :: HtmlEnv + , runapp_reactive_env :: ReactiveEnv , runapp_boundary :: ContentBoundary } deriving Generic -- | Start 'HtmlT' application applying customizations described by --- StartOpts argument -attachOptions :: StartOpts -> Html a -> IO (a, RunningApp) -attachOptions StartOpts{..} render = mdo +-- AttachOptions argument +attachWithOptions :: AttachOptions -> Html a -> IO (a, RunningApp) +attachWithOptions opt app = mdo -- TODO: doesn't work with javascript-backend - -- when startopts_wait_document_load + -- when wait_document_load -- js_waitDocumentLoad begin <- createComment "ContentBoundary {{" end <- createComment "}}" - appendChild startopts_root_element begin - appendChild startopts_root_element end + appendChild opt.root_element begin + appendChild opt.root_element end + reactiveEnv <- newReactiveEnv let boundary = ContentBoundary begin end htmlEnv = HtmlEnv - { html_current_element = startopts_root_element + { html_current_element = opt.root_element , html_content_boundary = Just boundary - , html_reactive_env = startopts_reactive_env } - runApp = RunningApp htmlEnv boundary - result <- execHtmlT htmlEnv render - when startopts_unload_call_finalizers $ onBeforeUnload $ do - finalizers <- readIORef $ renv_finalizers startopts_reactive_env - applyFinalizer startopts_reactive_env finalizers + runApp = RunningApp htmlEnv reactiveEnv boundary + result <- launchReactiveT reactiveEnv $ execHtmlT htmlEnv app + -- when opt.unload_call_finalizers $ onBeforeUnload $ do + -- finalizers <- readIORef $ renv_finalizers reactive_env + -- applyFinalizer reactive_env finalizers return (result, runApp) -- | Start the application and attach it to the given HTMLElement attachTo :: DOMElement -> Html a -> IO (a, RunningApp) attachTo rootEl html = do renv <- newReactiveEnv - attachOptions (StartOpts renv rootEl True True) html + attachWithOptions (AttachOptions renv rootEl True True) html -- | Start the application and attach it to current element attachToBody :: Html a -> IO (a, RunningApp) @@ -73,6 +70,5 @@ attachToBody html = do -- | Run finalizers and detach created elements from the DOM detach :: RunningApp -> IO () detach app = do - finalizers <- readIORef app.runapp_html_env.html_reactive_env.renv_finalizers - applyFinalizer app.runapp_html_env.html_reactive_env finalizers + launchReactiveT app.runapp_reactive_env $ freeScope app.runapp_reactive_env.scope removeBoundary app.runapp_boundary diff --git a/src/HtmlT/Types.hs b/src/HtmlT/Types.hs index f3feab6..dc36011 100644 --- a/src/HtmlT/Types.hs +++ b/src/HtmlT/Types.hs @@ -26,8 +26,7 @@ data HtmlEnv = HtmlEnv -- attached, when Nothing whole parent element is available } deriving Generic --- | Most applications will only need HtmlT IO, hence this shortcut -type Html = HtmlT (ReactiveT IO) +type Html = HtmlT RX -- | A newtype over JSVal which is an instance of Node -- https://developer.mozilla.org/en-US/docs/Web/API/Node From a9a5ff8ff1dd8761808179f8b75b5bc18eb58050 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sat, 16 Mar 2024 14:45:42 +0400 Subject: [PATCH 05/64] Rename --- examples/todomvc/TodoItem.hs | 6 +-- examples/todomvc/TodoList.hs | 4 +- examples/todomvc/Utils.hs | 2 +- src/HtmlT/Base.hs | 4 +- src/HtmlT/DOM.hs | 48 +++++++++++------------ src/HtmlT/Event.hs | 76 ++++++++++++++++++------------------ src/HtmlT/Types.hs | 2 +- 7 files changed, 72 insertions(+), 70 deletions(-) diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index 31b2e0c..1eca558 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -13,7 +13,7 @@ import "this" Utils data TodoItemConfig = TodoItemConfig { self :: DynRef TodoItemState , is_hidden_dyn :: Dynamic Bool - , ask_delete_item :: RX () + , ask_delete_item :: RI () } data TodoItemState = TodoItemState @@ -30,7 +30,7 @@ data TodoItemAction a where CheckedAction :: TodoItemConfig -> Bool -> TodoItemAction () KeydownAction :: TodoItemConfig -> Int -> TodoItemAction () -eval :: TodoItemAction a -> RX a +eval :: TodoItemAction a -> RI a eval = \case CancelAction cfg -> modifyRef cfg.self \s -> s{editing=Nothing} @@ -105,7 +105,7 @@ instance FromJSVal TodoItemState where data DblClickWithTarget instance IsEventName DblClickWithTarget where - type EventListenerCb DblClickWithTarget = JSVal -> RX () + type EventListenerCb DblClickWithTarget = JSVal -> RI () addEventListenerArgs = AddEventListenerArgs { event_name = "dblclick" , listener_options = defaultEventListenerOptions diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index 31168a1..bf5ac3a 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -41,7 +41,7 @@ data TodoListAction a where DeleteItemAction :: Int -> TodoListAction () ClearCompletedAction :: TodoListAction () -new :: Filter -> RX (DynRef TodoListState) +new :: Filter -> RI (DynRef TodoListState) new filter = do todos <- fromMaybe [] . fmap unLocalStorageTodoItems <$> liftIO localStorageGet newRef TodoListState @@ -50,7 +50,7 @@ new filter = do , title = "" } -eval :: TodoListConfig -> TodoListAction a -> RX a +eval :: TodoListConfig -> TodoListAction a -> RI a eval cfg = \case UpdateFilter filter -> modifyRef cfg.self \s -> s {filter} diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs index fecca52..86626f8 100644 --- a/examples/todomvc/Utils.hs +++ b/examples/todomvc/Utils.hs @@ -11,7 +11,7 @@ import Data.Text (Text) import Wasm.Compat.Prim import Wasm.Compat.Marshal -mkUrlHashRef :: RX (DynRef Text) +mkUrlHashRef :: RI (DynRef Text) mkUrlHashRef = do reactiveEnv <- ask initial <- liftIO $ textFromJSString =<< js_readUrlHash diff --git a/src/HtmlT/Base.hs b/src/HtmlT/Base.hs index dde8804..1d59962 100644 --- a/src/HtmlT/Base.hs +++ b/src/HtmlT/Base.hs @@ -186,10 +186,10 @@ simpleList listDyn h = do prevValue <- liftIO $ newIORef [] elemEnvsRef <- liftIO $ newIORef ([] :: [ElemEnv a]) let - exec :: ElemEnv a -> Html x -> RX x + exec :: ElemEnv a -> Html x -> RI x exec e = local (const e.ee_reactive_env) . execHtmlT e.ee_html_env - setup :: Int -> [a] -> [ElemEnv a] -> RX [ElemEnv a] + setup :: Int -> [a] -> [ElemEnv a] -> RI [ElemEnv a] setup idx new existing = case (existing, new) of ([], []) -> return [] -- New list is longer, append new elements diff --git a/src/HtmlT/DOM.hs b/src/HtmlT/DOM.hs index fe66f7e..26f5ff5 100644 --- a/src/HtmlT/DOM.hs +++ b/src/HtmlT/DOM.hs @@ -14,7 +14,7 @@ import Control.Monad.Reader import Data.Kind import Data.Text import GHC.Exts as Exts -import GHC.Generics hiding (RX) +import GHC.Generics hiding (RI) import HtmlT.Event import HtmlT.Types import Wasm.Compat.Marshal @@ -37,7 +37,7 @@ on k = addEventListener (addEventListenerArgs @eventName) k data AddEventListenerArgs callback = AddEventListenerArgs { event_name :: Text , listener_options :: EventListenerOptions - , mk_callback :: callback -> JSVal -> RX () + , mk_callback :: callback -> JSVal -> RI () } deriving (Generic) addEventListener :: AddEventListenerArgs callback -> callback -> Html () @@ -69,63 +69,63 @@ class IsEventName eventName where addEventListenerArgs :: AddEventListenerArgs (EventListenerCb eventName) instance IsEventName "click" where - type EventListenerCb "click" = RX () + type EventListenerCb "click" = RI () addEventListenerArgs = pointerEventArgs "click" instance IsEventName "mousedown" where - type EventListenerCb "mousedown" = RX () + type EventListenerCb "mousedown" = RI () addEventListenerArgs = pointerEventArgs "mousedown" instance IsEventName "mouseup" where - type EventListenerCb "mouseup" = RX () + type EventListenerCb "mouseup" = RI () addEventListenerArgs = pointerEventArgs "mouseup" instance IsEventName "dblclick" where - type EventListenerCb "dblclick" = RX () + type EventListenerCb "dblclick" = RI () addEventListenerArgs = pointerEventArgs "dblclick" instance IsEventName "submit" where - type EventListenerCb "submit" = RX () + type EventListenerCb "submit" = RI () addEventListenerArgs = submitEventArgs instance IsEventName "input" where - type EventListenerCb "input" = Text -> RX () + type EventListenerCb "input" = Text -> RI () addEventListenerArgs = inputEventArgs instance IsEventName "keydown" where - type EventListenerCb "keydown" = Int -> RX () + type EventListenerCb "keydown" = Int -> RI () addEventListenerArgs = keyboardEventArgs "keydown" instance IsEventName "keyup" where - type EventListenerCb "keyup" = Int -> RX () + type EventListenerCb "keyup" = Int -> RI () addEventListenerArgs = keyboardEventArgs "keyup" instance IsEventName "focus" where - type EventListenerCb "focus" = RX () + type EventListenerCb "focus" = RI () addEventListenerArgs = pointerEventArgs "focus" instance IsEventName "blur" where - type EventListenerCb "blur" = RX () + type EventListenerCb "blur" = RI () addEventListenerArgs = pointerEventArgs "blur" instance IsEventName "input/blur" where - type EventListenerCb "input/blur" = Text -> RX () + type EventListenerCb "input/blur" = Text -> RI () addEventListenerArgs = inputEventArgs {event_name = "blur"} instance IsEventName "input/focus" where - type EventListenerCb "input/focus" = Text -> RX () + type EventListenerCb "input/focus" = Text -> RI () addEventListenerArgs = inputEventArgs {event_name = "focus"} instance IsEventName "checkbox/change" where - type EventListenerCb "checkbox/change" = Bool -> RX () + type EventListenerCb "checkbox/change" = Bool -> RI () addEventListenerArgs = checkboxChangeEventArgs instance IsEventName "select/change" where - type EventListenerCb "select/change" = Text -> RX () + type EventListenerCb "select/change" = Text -> RI () addEventListenerArgs = selectChangeEventArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event -pointerEventArgs :: Text -> AddEventListenerArgs (RX ()) +pointerEventArgs :: Text -> AddEventListenerArgs (RI ()) pointerEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -133,7 +133,7 @@ pointerEventArgs event_name = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event -submitEventArgs :: AddEventListenerArgs (RX ()) +submitEventArgs :: AddEventListenerArgs (RI ()) submitEventArgs = AddEventListenerArgs { event_name = "submit" , listener_options = defaultSubmitOptions @@ -143,7 +143,7 @@ submitEventArgs = AddEventListenerArgs defaultSubmitOptions = EventListenerOptions True True -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event -inputEventArgs :: AddEventListenerArgs (Text -> RX ()) +inputEventArgs :: AddEventListenerArgs (Text -> RI ()) inputEventArgs = AddEventListenerArgs { event_name = "input" , listener_options = defaultEventListenerOptions @@ -155,7 +155,7 @@ inputEventArgs = AddEventListenerArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardEventArgs :: Text -> AddEventListenerArgs (Int -> RX ()) +keyboardEventArgs :: Text -> AddEventListenerArgs (Int -> RI ()) keyboardEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -168,7 +168,7 @@ keyboardEventArgs event_name = AddEventListenerArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event -focusEventArgs :: Text -> AddEventListenerArgs (RX ()) +focusEventArgs :: Text -> AddEventListenerArgs (RI ()) focusEventArgs event_name = AddEventListenerArgs { event_name , listener_options = defaultEventListenerOptions @@ -176,7 +176,7 @@ focusEventArgs event_name = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -checkboxChangeEventArgs :: AddEventListenerArgs (Bool -> RX ()) +checkboxChangeEventArgs :: AddEventListenerArgs (Bool -> RI ()) checkboxChangeEventArgs = AddEventListenerArgs { event_name = "change" , listener_options = defaultEventListenerOptions @@ -187,7 +187,7 @@ checkboxChangeEventArgs = AddEventListenerArgs } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -selectChangeEventArgs :: AddEventListenerArgs (Text -> RX ()) +selectChangeEventArgs :: AddEventListenerArgs (Text -> RI ()) selectChangeEventArgs = AddEventListenerArgs { event_name = "change" , listener_options = defaultEventListenerOptions @@ -217,7 +217,7 @@ data Location = Location } deriving stock (Show, Eq, Generic) -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event -popstateEventArgs :: AddEventListenerArgs (Location -> RX ()) +popstateEventArgs :: AddEventListenerArgs (Location -> RI ()) popstateEventArgs = AddEventListenerArgs { event_name = "popstate" , listener_options = defaultEventListenerOptions diff --git a/src/HtmlT/Event.hs b/src/HtmlT/Event.hs index 2b64f9b..731cabb 100644 --- a/src/HtmlT/Event.hs +++ b/src/HtmlT/Event.hs @@ -42,9 +42,9 @@ newReactiveEnv = do return ReactiveEnv {reactive_state_ref, scope} data ReactiveState = ReactiveState - { subscriptions :: Map EventId [(ReactiveScope, Any -> RX ())] + { subscriptions :: Map EventId [(ReactiveScope, Any -> RI ())] , scopes :: Map ReactiveScope ReactiveNode - , transaction_queue :: Map EventId (RX ()) + , transaction_queue :: Map EventId (RI ()) , id_supply :: Int -- ^ Id supply for EventId and ReactiveScope } deriving (Generic) @@ -65,7 +65,7 @@ newtype ReactiveScope = ReactiveScope { unReactiveScope :: Int } -- | Represents a stream of event occurrences of type @a@. Its actual -- representation is simply a function that subscribes to the event -newtype Event a = Event { subscribe :: (a -> RX ()) -> RX () } +newtype Event a = Event { subscribe :: (a -> RI ()) -> RI () } instance Functor Event where fmap f (Event s) = Event \k -> s . (. f) $ k @@ -123,35 +123,37 @@ data DynRef a = DynRef -- cases when you know that all changes already been reflected in -- the DOM newtype Modifier a = Modifier - { unModifier :: forall r. Bool -> (a -> (a, r)) -> RX r + { unModifier :: forall r. Bool -> (a -> (a, r)) -> RI r } -newtype RX a = RX - { unRX :: ReaderT ReactiveEnv IO a +newtype ReactiveT m a = ReactiveT + { unReactiveT :: ReaderT ReactiveEnv m a } deriving newtype ( Functor, Applicative, Monad, MonadIO, MonadFix, MonadCatch, MonadThrow, MonadMask, MonadReader ReactiveEnv ) -instance MonadReactive RX where - reactive f = RX $ ReaderT $ \e -> +instance MonadIO m => MonadReactive (ReactiveT m) where + reactive f = ReactiveT $ ReaderT $ \e -> liftIO $ atomicModifyIORef' e.reactive_state_ref $ f e.scope {-# INLINE reactive #-} -type Callback a = a -> RX () +type RI = ReactiveT IO -type Subscriptions = Map EventId [(ReactiveScope, Any -> RX ())] +type Callback a = a -> RI () + +type Subscriptions = Map EventId [(ReactiveScope, Any -> RI ())] type Finalizers = Map ReactiveScope ReactiveNode data ReactiveNode = ReactiveNode { nodes :: [ReactiveScope] , parent :: Maybe ReactiveScope - , finalizers :: [RX ()] + , finalizers :: [RI ()] } deriving stock Generic -freeScope :: ReactiveScope -> RX () +freeScope :: ReactiveScope -> RI () freeScope rscope = do mRemovedNode <- reactive $ const $ freeScopeFn rscope forM_ mRemovedNode \n -> do @@ -186,7 +188,7 @@ freeScopeFn rscope s = filterSubscriptions ((s, c):xs) | s == rscope = xs | otherwise = (s, c) : filterSubscriptions xs -unsafeSubscribeFn :: EventId -> (a -> RX ()) -> ReactiveScope -> ReactiveState -> ReactiveState +unsafeSubscribeFn :: EventId -> (a -> RI ()) -> ReactiveScope -> ReactiveState -> ReactiveState unsafeSubscribeFn eid k rs s = let insertSubscription (Just xs) = Just $ (rs, k . unsafeCoerce):xs @@ -194,10 +196,10 @@ unsafeSubscribeFn eid k rs s = in s {subscriptions = Map.alter insertSubscription eid s.subscriptions } -unsafeSubscribe :: EventId -> (a -> RX ()) -> RX () +unsafeSubscribe :: EventId -> (a -> RI ()) -> RI () unsafeSubscribe eid k = reactive_ (unsafeSubscribeFn eid k) -installFinalizerFn :: RX () -> ReactiveScope -> ReactiveState -> ReactiveState +installFinalizerFn :: RI () -> ReactiveScope -> ReactiveState -> ReactiveState installFinalizerFn fin rs s = let insertFin (Just n) = Just $ n { finalizers = fin : n.finalizers} @@ -205,10 +207,10 @@ installFinalizerFn fin rs s = in s {scopes = Map.alter insertFin rs s.scopes } -installFinalizer :: RX () -> RX () +installFinalizer :: RI () -> RI () installFinalizer fin = reactive_ (installFinalizerFn fin) -unsafeTrigger :: EventId -> a -> RX () +unsafeTrigger :: EventId -> a -> RI () unsafeTrigger eid a = do defer eid do callbacks <- reactive \_ s -> @@ -224,16 +226,16 @@ newReactiveScopeFn parent s0 = in (s1 {scopes}, rscope) -newReactiveScope :: RX ReactiveScope +newReactiveScope :: RI ReactiveScope newReactiveScope = reactive newReactiveScopeFn -- | Defers a computation (typically an event firing) until the end of -- the current reactive transaction. This allows for the avoidance of -- double firing of events constructed from multiple other events. -defer :: EventId -> RX () -> RX () +defer :: EventId -> RI () -> RI () defer k act = reactive_ \_ s -> s {transaction_queue = Map.insert k act s.transaction_queue} -newEvent :: RX (Event a, a -> RX ()) +newEvent :: RI (Event a, a -> RI ()) newEvent = reactive \_ s0 -> let (s1, eventId) = nextIntId s0 @@ -242,7 +244,7 @@ newEvent = reactive \_ s0 -> in (s1, (event, trig)) -newRef :: a -> RX (DynRef a) +newRef :: a -> RI (DynRef a) newRef initial = do ioRef <- liftIO $ newIORef initial (event, push) <- newEvent @@ -270,7 +272,7 @@ never = Event \ _ -> return () -- > transactionWrite ref "New dynamic" -- > readRef ref -- "New dynamic" -writeRef :: DynRef a -> a -> RX () +writeRef :: DynRef a -> a -> RI () writeRef ref a = modifyRef ref (const a) -- | Read the current value held by given 'DynRef' @@ -286,14 +288,14 @@ readRef = readDyn . (.dynamic) -- > ref <- newRef [1..3] -- > modifyRef ref $ fmap (*2) -- [2, 4, 6] -modifyRef :: DynRef a -> (a -> a) -> RX () +modifyRef :: DynRef a -> (a -> a) -> RI () modifyRef (DynRef _ (Modifier mod)) f = mod True $ (,()) . f -- | Update a 'DynRef' with first field of the tuple and return back -- the second field. The name is intended to be similar to -- 'atomicModifyIORef' but there are no atomicity guarantees -- whatsoever -atomicModifyRef :: DynRef a -> (a -> (a, r)) -> RX r +atomicModifyRef :: DynRef a -> (a -> (a, r)) -> RI r atomicModifyRef (DynRef _ (Modifier mod)) f = mod True f -- | Extract a 'Dynamic' out of 'DynRef' @@ -306,7 +308,7 @@ readDyn = liftIO . (.sample) -- | Executes an action currently held inside the 'Dynamic' and every -- time the dynamic changes. -performDyn :: Dynamic (RX ()) -> RX () +performDyn :: Dynamic (RI ()) -> RI () performDyn d = do join $ liftIO d.sample d.updates.subscribe id @@ -333,7 +335,7 @@ holdUniqDynBy equalFn da = -- | Produce a new Dynamic by applying a function to both the source -- (Dynamic a) and previous value of itself -foldDynMaybe :: (a -> b -> Maybe b) -> b -> Dynamic a -> RX (Dynamic b) +foldDynMaybe :: (a -> b -> Maybe b) -> b -> Dynamic a -> RI (Dynamic b) foldDynMaybe f initB dynA = do initA <- liftIO dynA.sample refB <- newRef $ fromMaybe initB $ f initA initB @@ -350,7 +352,7 @@ nextIntId s = (s {id_supply = succ s.id_supply}, s.id_supply) -- it would be called once for each subscription per change event. As -- a general guideline, if the function @f@ is inexpensive, choose -- @fmap f@. Otherwise, consider using @mapDyn f@. -mapDyn :: (a -> b) -> Dynamic a -> RX (Dynamic b) +mapDyn :: (a -> b) -> Dynamic a -> RI (Dynamic b) mapDyn fun da = do initialA <- liftIO $ da.sample latestA <- liftIO $ newIORef initialA @@ -367,7 +369,7 @@ mapDyn fun da = do defer eventId fire return $ Dynamic (readIORef latestB) updates -mapDyn2 :: (a -> b -> c) -> Dynamic a -> Dynamic b -> RX (Dynamic c) +mapDyn2 :: (a -> b -> c) -> Dynamic a -> Dynamic b -> RI (Dynamic c) mapDyn2 fun da db = do initialA <- liftIO $ da.sample initialB <- liftIO $ db.sample @@ -401,7 +403,7 @@ unsafeMapDynN -- corresponding positions of given Dynamics -> [Dynamic Any] -- ^ List of input Dynamics - -> RX (Dynamic a) + -> RI (Dynamic a) unsafeMapDynN fun dyns = do initialInputs <- liftIO $ mapM (.sample) dyns initialOutput <- liftIO $ fun initialInputs @@ -438,32 +440,32 @@ lensMap l s = DynRef {dynamic, modifier} -- | Loop until transaction_queue is empty -trampoline :: RX a -> RX a +trampoline :: RI a -> RI a trampoline act = loop0 act where - loop0 :: RX a -> RX a + loop0 :: RI a -> RI a loop0 before = do r <- before mcont <- popQueue forM_ mcont loop1 return r - loop1 :: RX () -> RX () + loop1 :: RI () -> RI () loop1 before = do before mcont <- popQueue forM_ mcont loop1 - popQueue :: RX (Maybe (RX ())) + popQueue :: RI (Maybe (RI ())) popQueue = reactive \_ s -> case Map.minViewWithKey s.transaction_queue of Nothing -> (s, Nothing) Just ((_, r), newQueue) -> (s {transaction_queue = newQueue}, Just r) -launchReactiveT :: ReactiveEnv -> RX a -> IO a +launchReactiveT :: ReactiveEnv -> RI a -> IO a launchReactiveT e = execReactiveT e . trampoline -execReactiveT :: ReactiveEnv -> RX a -> IO a -execReactiveT e = flip runReaderT e . unRX +execReactiveT :: ReactiveEnv -> ReactiveT m a -> m a +execReactiveT e = flip runReaderT e . unReactiveT -runReactiveT :: RX a -> ReactiveEnv -> IO a +runReactiveT :: ReactiveT m a -> ReactiveEnv -> m a runReactiveT = flip execReactiveT class MonadReactive m where diff --git a/src/HtmlT/Types.hs b/src/HtmlT/Types.hs index dc36011..d00d5f6 100644 --- a/src/HtmlT/Types.hs +++ b/src/HtmlT/Types.hs @@ -26,7 +26,7 @@ data HtmlEnv = HtmlEnv -- attached, when Nothing whole parent element is available } deriving Generic -type Html = HtmlT RX +type Html = HtmlT RI -- | A newtype over JSVal which is an instance of Node -- https://developer.mozilla.org/en-US/docs/Web/API/Node From 962f7262baf0fcaec2f44615d6af872aee5f5fc6 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 18 Mar 2024 22:06:42 +0400 Subject: [PATCH 06/64] evalRawJavaScript --- examples/counter/counter.hs | 27 ++++++++++-------- htmlt.cabal | 25 ++++++++++------- jsbits/jsffi.js | 55 +++++++++++-------------------------- src/HtmlT/Main.hs | 8 +++--- src/HtmlT/Types.hs | 1 + src/Wasm/Compat/Marshal.hs | 12 ++++++++ 6 files changed, 63 insertions(+), 65 deletions(-) diff --git a/examples/counter/counter.hs b/examples/counter/counter.hs index f3fb5a1..8808f9b 100644 --- a/examples/counter/counter.hs +++ b/examples/counter/counter.hs @@ -1,32 +1,35 @@ import Control.Monad -import Control.Monad.Trans.Maybe import HtmlT -import JavaScript.Compat.String qualified as JSS import Text.Read (readMaybe) +import Data.Text qualified as Text +import Data.Function ((&)) +import Control.Monad.Trans +import Control.Monad.Reader +import Control.Concurrent app :: Html () app = do -- First create a 'DynRef - counterRef <- newRef @Int 0 + counterRef <- lift $ newRef @Int 0 div_ do input_ [type_ "number"] do -- Show the value inside - dynProp "value" $ JSS.pack . show <$> fromRef counterRef + dynProp "value" $ Text.pack . show <$> fromRef counterRef -- Parse and update the value on each InputEvent - on "input" $ decodeEvent intDecoder $ writeRef counterRef + on @"input" \inp -> + readMaybe (Text.unpack inp) & mapM_ (writeRef counterRef) br_ -- Decrease the value on each click button_ do - on_ "click" $ modifyRef counterRef pred + on @"click" $ modifyRef counterRef pred text "-" -- Increase the value on each click button_ do - on_ "click" $ modifyRef counterRef succ + on @"click" $ modifyRef counterRef succ text "+" - where - intDecoder = - valueDecoder >=> MaybeT . pure . readMaybe . JSS.unpack + +foreign export ccall wasm_main :: IO () +wasm_main = void $ attachToBody app main :: IO () -main = - void $ attachToBody app +main = return () diff --git a/htmlt.cabal b/htmlt.cabal index f89d8d3..58ffab1 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -103,16 +103,21 @@ library ghc-experimental, ghc-prim, --- executable htmlt-counter --- import: htmlt-common --- main-is: counter.hs --- hs-source-dirs: ./examples/counter --- build-depends: --- base, --- htmlt, --- transformers, --- if !flag(examples) --- buildable: False +executable htmlt-counter + import: htmlt-common + main-is: counter.hs + hs-source-dirs: ./examples/counter + ghc-options: + -no-hs-main -optl-mexec-model=reactor + -optl-Wl,--export=hs_init,--export=wasm_main + build-depends: + base, + htmlt, + text, + mtl, + transformers, + if !flag(examples) + buildable: False executable htmlt-todomvc import: htmlt-common diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index 7d653c4..b5c1e00 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -98,53 +98,30 @@ newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v), getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), -ZC0ZCmainZCUtilsZC: ($1,$2,$3,$4,$5,$6) => ((function(k1, v1, k2, v2, k3, v3){ var res = {}; res[k1] = v1; res[k2] = v2; res[k3] = v3; return res; })($1,$2,$3,$4,$5,$6)), -ZC1ZCmainZCUtilsZC: () => (location.hash), -ZC2ZCmainZCUtilsZC: ($1) => {var itemText = localStorage.getItem($1); return itemText ? JSON.parse(itemText) : null;}, -ZC3ZCmainZCUtilsZC: ($1) => (console.log($1)), -ZC4ZCmainZCUtilsZC: ($1,$2) => {localStorage.setItem($1, JSON.stringify($2));}, -ZC5ZCmainZCUtilsZC: ($1) => (setTimeout(function() { var inputEl = $1.parentNode.parentNode.querySelector('input.edit'); inputEl.focus(); }, 0)), +ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziConcziInternalZC: async ($1) => (new Promise(res => setTimeout(res, $1 / 1000))), +ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => (`${$1.stack ? $1.stack : $1}`), +ZC1ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2) => ((new TextDecoder('utf-8', {fatal: true})).decode(new Uint8Array(__exports.memory.buffer, $1, $2))), +ZC2ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written), +ZC3ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => ($1.length), +ZC4ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => {if (!__ghc_wasm_jsffi_finalization_registry.unregister($1)) { throw new WebAssembly.RuntimeError('js_callback_unregister'); }}, +ZC18ZCghczminternalZCGHCziInternalziWasmziPrimziImportsZC: ($1,$2) => ($1.then(() => __exports.rts_promiseResolveUnit($2), err => __exports.rts_promiseReject($2, err))), +ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), +ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), +ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, +ZC21ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => (__ghc_wasm_jsffi_finalization_registry.register($1, $2, $1)), +ZC1ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1.length), +ZC2ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written), +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ((new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)))), +ZC9ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), +ZC14ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => {if ($1 === undefined || $1 === null) return 0; if (typeof $1 === 'boolean') return 1; if (typeof $1 === 'number') return 2; if (typeof $1 === 'string') return 3; if (Array.isArray($1)) return 4; return 5;}, ZC1ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: async ($1,$2,$3) => ($1.addEventListener($2, $3)), ZC3ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC2ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC($1,a1)), ZC4ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => {$1[$2] = $3;}, -ZC7ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {if ($1.parentNode) $1.parentNode.removeChild($1); if ($2.parentNode) $2.parentNode.removeChild($2);}, -ZC8ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {for (;;){ if (!$2.previousSibling || !$2.previousSibling.parentNode || $2.previousSibling === $1 ) break; $2.previousSibling.parentNode.removeChild($2.previousSibling); }}, ZC9ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: () => (window.document.body), -ZC11ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: () => {return window}, -ZC12ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: async ($1) => (window.addEventListener('beforeunload', $1)), -ZC13ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {$1.nodeValue = $2;}, -ZC14ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {$1.classList.remove($2);}, -ZC15ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => {$1.classList.add($2);}, ZC16ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createComment($1)), ZC17ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createTextNode($1)), ZC19ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createElement($1)), -ZC23ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => ($1.setAttribute($2, $3)), ZC24ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => ($1.insertBefore($2, $3)), ZC25ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => ($1.appendChild($2)), -ZC0ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1.length), -ZC1ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written), -ZC2ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ((new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)))), -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), -ZC4ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1.length), -ZC5ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1.push($2)), -ZC6ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: () => ([]), -ZC8ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), -ZC9ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => (($1 ? true : false)), -ZC11ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1), -ZC12ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1), -ZC13ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => {if ($1 === undefined || $1 === null) return 0; if (typeof $1 === 'boolean') return 1; if (typeof $1 === 'number') return 2; if (typeof $1 === 'string') return 3; if (Array.isArray($1)) return 4; return 5;}, -ZC14ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => (($1 === null || $1 === undefined)), -ZC17ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: () => (null), -ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), -ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), -ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, -ZC21ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => (__ghc_wasm_jsffi_finalization_registry.register($1, $2, $1)), -ZC18ZCghczminternalZCGHCziInternalziWasmziPrimziImportsZC: ($1,$2) => ($1.then(() => __exports.rts_promiseResolveUnit($2), err => __exports.rts_promiseReject($2, err))), -ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => (`${$1.stack ? $1.stack : $1}`), -ZC1ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2) => ((new TextDecoder('utf-8', {fatal: true})).decode(new Uint8Array(__exports.memory.buffer, $1, $2))), -ZC2ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written), -ZC3ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => ($1.length), -ZC4ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => {if (!__ghc_wasm_jsffi_finalization_registry.unregister($1)) { throw new WebAssembly.RuntimeError('js_callback_unregister'); }}, -ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziConcziInternalZC: async ($1) => (new Promise(res => setTimeout(res, $1 / 1000))), }; }; diff --git a/src/HtmlT/Main.hs b/src/HtmlT/Main.hs index 74ce53d..2bba32b 100644 --- a/src/HtmlT/Main.hs +++ b/src/HtmlT/Main.hs @@ -57,15 +57,15 @@ attachWithOptions opt app = mdo -- | Start the application and attach it to the given HTMLElement attachTo :: DOMElement -> Html a -> IO (a, RunningApp) -attachTo rootEl html = do +attachTo root html = do renv <- newReactiveEnv - attachWithOptions (AttachOptions renv rootEl True True) html + attachWithOptions (AttachOptions renv root True True) html -- | Start the application and attach it to current element attachToBody :: Html a -> IO (a, RunningApp) attachToBody html = do - bodyEl <- getCurrentBody - attachTo bodyEl html + body <- getCurrentBody + attachTo body html -- | Run finalizers and detach created elements from the DOM detach :: RunningApp -> IO () diff --git a/src/HtmlT/Types.hs b/src/HtmlT/Types.hs index d00d5f6..9495a53 100644 --- a/src/HtmlT/Types.hs +++ b/src/HtmlT/Types.hs @@ -6,6 +6,7 @@ import Data.Coerce import Data.String import GHC.Generics import HtmlT.Event +import Data.Text import Control.Monad.Fix import Wasm.Compat.Prim diff --git a/src/Wasm/Compat/Marshal.hs b/src/Wasm/Compat/Marshal.hs index 5010b72..39074eb 100644 --- a/src/Wasm/Compat/Marshal.hs +++ b/src/Wasm/Compat/Marshal.hs @@ -142,6 +142,14 @@ textFromJSString j = IO \s0 -> (# s4, arr #) = unsafeFreezeByteArray# marr s3 in (# s4, (Text (ByteArray arr) 0 tlen) #) +newtype RawJavaScript = RawJavaScript {unRawJavaScript :: Text} + +evalRawJavaScript :: RawJavaScript -> IO JSVal +evalRawJavaScript rjs = do + let Text (ByteArray arr) off len = rjs.unRawJavaScript + addr = byteArrayContents# arr + js_evalRawJavaScript (Ptr addr `plusPtr` off) len + #if !defined(wasm32_HOST_ARCH) js_true :: JSVal = undefined @@ -164,6 +172,7 @@ js_arrayIndex :: JSVal -> Int -> IO JSVal = undefined js_decodeUtf8 :: Ptr Word8 -> Int -> IO JSString = undefined js_encodeUtf8 :: JSString -> Ptr Word8 -> Int -> IO Int = undefined js_stringLength :: JSString -> IO Int = undefined +js_evalRawJavaScript :: Ptr Word8 -> Int -> IO JSString = undefined #else @@ -215,4 +224,7 @@ foreign import javascript unsafe foreign import javascript unsafe "$1.length" js_stringLength :: JSString -> IO Int +foreign import javascript unsafe + "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)))" + js_evalRawJavaScript :: Ptr Word8 -> Int -> IO JSVal #endif From 63c02964ad757fe53b1e173c775c6ddbff8393c3 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 20 Mar 2024 18:12:34 +0400 Subject: [PATCH 07/64] evalJavaScriptN --- src/Wasm/Compat/Marshal.hs | 60 ++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/src/Wasm/Compat/Marshal.hs b/src/Wasm/Compat/Marshal.hs index 39074eb..b534ea8 100644 --- a/src/Wasm/Compat/Marshal.hs +++ b/src/Wasm/Compat/Marshal.hs @@ -144,11 +144,45 @@ textFromJSString j = IO \s0 -> newtype RawJavaScript = RawJavaScript {unRawJavaScript :: Text} -evalRawJavaScript :: RawJavaScript -> IO JSVal -evalRawJavaScript rjs = do +evalJavaScript :: RawJavaScript -> IO JSVal +evalJavaScript rjs = do let Text (ByteArray arr) off len = rjs.unRawJavaScript addr = byteArrayContents# arr - js_evalRawJavaScript (Ptr addr `plusPtr` off) len + js_evalJavaScript (Ptr addr `plusPtr` off) len + +evalJavaScript1 :: ToJSVal arg0 => arg0 -> RawJavaScript -> IO JSVal +evalJavaScript1 arg0 rjs = do + a0 <- toJSVal arg0 + let Text (ByteArray arr) off len = rjs.unRawJavaScript + addr = byteArrayContents# arr + js_evalJavaScript1 a0 (Ptr addr `plusPtr` off) len + +evalJavaScript2 :: (ToJSVal arg0, ToJSVal arg1) => arg0 -> arg1 -> RawJavaScript -> IO JSVal +evalJavaScript2 arg0 arg1 rjs = do + a0 <- toJSVal arg0 + a1 <- toJSVal arg1 + let Text (ByteArray arr) off len = rjs.unRawJavaScript + addr = byteArrayContents# arr + js_evalJavaScript2 a0 a1 (Ptr addr `plusPtr` off) len + +evalJavaScript3 :: (ToJSVal arg0, ToJSVal arg1, ToJSVal arg2) => arg0 -> arg1 -> arg2 -> RawJavaScript -> IO JSVal +evalJavaScript3 arg0 arg1 arg2 rjs = do + a0 <- toJSVal arg0 + a1 <- toJSVal arg1 + a2 <- toJSVal arg2 + let Text (ByteArray arr) off len = rjs.unRawJavaScript + addr = byteArrayContents# arr + js_evalJavaScript3 a0 a1 a2 (Ptr addr `plusPtr` off) len + +evalJavaScript4 :: (ToJSVal arg0, ToJSVal arg1, ToJSVal arg2, ToJSVal arg3) => arg0 -> arg1 -> arg2 -> arg3 -> RawJavaScript -> IO JSVal +evalJavaScript4 arg0 arg1 arg2 arg3 rjs = do + a0 <- toJSVal arg0 + a1 <- toJSVal arg1 + a2 <- toJSVal arg2 + a3 <- toJSVal arg3 + let Text (ByteArray arr) off len = rjs.unRawJavaScript + addr = byteArrayContents# arr + js_evalJavaScript4 a0 a1 a2 a3 (Ptr addr `plusPtr` off) len #if !defined(wasm32_HOST_ARCH) @@ -172,7 +206,11 @@ js_arrayIndex :: JSVal -> Int -> IO JSVal = undefined js_decodeUtf8 :: Ptr Word8 -> Int -> IO JSString = undefined js_encodeUtf8 :: JSString -> Ptr Word8 -> Int -> IO Int = undefined js_stringLength :: JSString -> IO Int = undefined -js_evalRawJavaScript :: Ptr Word8 -> Int -> IO JSString = undefined +js_evalJavaScript :: Ptr Word8 -> Int -> IO JSVal = undefined +js_evalJavaScript1 :: JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined +js_evalJavaScript2 :: JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined +js_evalJavaScript3 :: JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined +js_evalJavaScript4 :: JSVal -> JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined #else @@ -226,5 +264,17 @@ foreign import javascript unsafe js_stringLength :: JSString -> IO Int foreign import javascript unsafe "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)))" - js_evalRawJavaScript :: Ptr Word8 -> Int -> IO JSVal + js_evalJavaScript :: Ptr Word8 -> Int -> IO JSVal +foreign import javascript unsafe + "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)))($1)" + js_evalJavaScript1 :: JSVal -> Ptr Word8 -> Int -> IO JSVal +foreign import javascript unsafe + "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $3, $4)))($1, $2)" + js_evalJavaScript2 :: JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal +foreign import javascript unsafe + "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)))($1, $2, $3)" + js_evalJavaScript3 :: JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal +foreign import javascript unsafe + "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $5, $6)))($1, $2, $3, $4)" + js_evalJavaScript4 :: JSVal -> JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal #endif From 48a133d06ade186c9d3cd8e5a71ceeaea348b36b Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 21 Mar 2024 13:53:14 +0400 Subject: [PATCH 08/64] WIP --- default.nix | 51 +++++- examples/charts/Charts.hs | 98 +++++++++++ examples/charts/PairSelector.hs | 47 ++++++ examples/charts/charts.hs | 8 + htmlt.cabal | 85 ++++++---- jsbits/jsffi.js | 32 ++-- shell.nix | 2 +- src/HtmlT/Sketch.hs | 288 ++++++++++++++++++++++++++++++++ src/HtmlT/Sketch/FFI.hs | 106 ++++++++++++ 9 files changed, 658 insertions(+), 59 deletions(-) create mode 100644 examples/charts/Charts.hs create mode 100644 examples/charts/PairSelector.hs create mode 100644 examples/charts/charts.hs create mode 100644 src/HtmlT/Sketch.hs create mode 100644 src/HtmlT/Sketch/FFI.hs diff --git a/default.nix b/default.nix index c3d1eea..24f33c8 100644 --- a/default.nix +++ b/default.nix @@ -1,12 +1,49 @@ { pkgs ? import (builtins.fetchTarball { url = "https://github.com/NixOS/nixpkgs/archive/f4429fde23e1fb20ee27f264e74c28c619d2cebb.tar.gz"; }) {} -}: { - shell = { - x86_64 = pkgs.mkShell { - buildInputs = [ - pkgs.haskell.compiler.ghcHEAD - ]; +}: + +let + inherit (pkgs.haskell.lib) doJailbreak; + + haskellPackages = pkgs.haskell.packages.ghcHEAD.override { + overrides = self: super: { + mkDerivation = args: super.mkDerivation ({ + doCheck = false; + doBenchmark = false; + doHoogle = true; + doHaddock = true; + enableLibraryProfiling = false; + enableExecutableProfiling = false; + } // args); + + htmlt = self.callCabal2nix "htmlt" ./. {}; + + + # th-compat = self.callCabal2nix "th-compat" ./packages/th-compat {}; + tagged = self.callCabal2nix "tagged" ../fullstack-app/packages/tagged {}; + th-abstraction = self.callCabal2nix "th-abstraction" ./packages/th-abstraction {}; + vector = self.callCabal2nix "vector" ./packages/vector/vector {}; + vector-stream = self.callCabal2nix "vector-stream" ./packages/vector/vector-stream {}; + unordered-containers = self.callCabal2nix "unordered-containers" ./packages/unordered-containers {}; + # text-short = self.callCabal2nix "text-short" ./packages/text-short {}; + generic-deriving = doJailbreak super.generic-deriving; + bifunctors = doJailbreak super.bifunctors; + semigroupoids = doJailbreak super.semigroupoids; + th-lift = doJailbreak super.th-lift; + th-expand-syns = doJailbreak super.th-expand-syns; + invariant = doJailbreak super.invariant; + free = doJailbreak super.free; + th-compat = doJailbreak super.th-compat; + lens = doJailbreak super.lens; }; }; -} + + result = { + pkgs = haskellPackages; + shell = pkgs.mkShell { + inputsFrom = [haskellPackages.htmlt.env]; + }; + }; +in + result diff --git a/examples/charts/Charts.hs b/examples/charts/Charts.hs new file mode 100644 index 0000000..866f550 --- /dev/null +++ b/examples/charts/Charts.hs @@ -0,0 +1,98 @@ +module Charts where + +import Data.Proxy +import Control.Monad.State +import Data.Text (Text) +import Data.Text qualified as Text +import GHC.Generics + +import HtmlT.Sketch +import HtmlT.Sketch.FFI +import PairSelector qualified as PairSelector + +------------------------------------------------------- +-- EXAMPLE OF APPLICATION FEATURING FINANCIAL CHARTS -- +------------------------------------------------------- + +data ChartState = ChartState + { main_transform :: Transform2D + , mouse_position :: Point + , counter :: Int + , pair_selector_instance :: PairSelector.PairSelectorState + } deriving (Show, Eq, Generic) + +new :: IO ChartState +new = do + pair_selector_instance <- PairSelector.new + return ChartState + { main_transform = Transform2D 0 0 0 0 + , mouse_position = Point 0 0 + , counter = 0 + , pair_selector_instance + } + +html :: BuilderM ChartState () +html = do + el "style" [] $ text styles + div_ [("className", "Charts-root")] do + h1_ [] $ text "Canvas with candle chart" + div_ [] do + embedFld @"pair_selector_instance" PairSelector.html + div_ [] do + button_ [] do + text "Click this button" + on "click" \_ -> do + modifyFld @"counter" (+ 1) + button_ [] do + text "Print state" + on "click" \_ -> do + s <- get + consoleLog $ Text.pack $ show s.position + span_ [] $ dynText $ \s -> "You clicked " <> Text.pack (show s.counter) <> " times" + canvas_ [("className", "Charts-canvas")] $ return () + +styles :: Text +styles = "\ + \.Charts-root {\ + \ max-width: 900;\ + \ width: 100%\ + \ padding: 16px;\ + \ margin: 0 auto;\ + \}\ + \.Charts-canvas {\ + \ width: 100%;\ + \ height: 550px;\ + \ border: solid 1px black;\ + \}\ + \ " + +data Transform2D = Transform2D + { a :: Double -- ^ X scaling + , c :: Double -- ^ X translation + , e :: Double -- ^ Y scaling + , f :: Double -- ^ Y translation + } deriving (Show, Eq, Generic) + +data Point = Point + { point_x :: Double + , point_y :: Double + } deriving (Eq, Show, Generic) + +setMouseCoords :: Point -> Edit ChartState +setMouseCoords p = Fld (Proxy @"mouse_position") (Ins p) + + +moveScreen :: Double -> Jet ChartState -> Jet ChartState +moveScreen dir old = + let + beg = negate old.position.main_transform.c / old.position.main_transform.a + end = (w - old.position.main_transform.c) / old.position.main_transform.a + inc = (end - beg) * dir + w = 1000 + c = old.position.main_transform.c - + (inc * old.position.main_transform.a) + new = old.position + { main_transform = old.position.main_transform {c} + } + in + Jet new (Fld (Proxy @"main_transform") (Fld (Proxy @"c") (Ins c)) : old.velocity) diff --git a/examples/charts/PairSelector.hs b/examples/charts/PairSelector.hs new file mode 100644 index 0000000..939ba17 --- /dev/null +++ b/examples/charts/PairSelector.hs @@ -0,0 +1,47 @@ +module PairSelector where + +import Data.Proxy +import Data.Text (Text) +import Data.Text qualified as Text +import Data.Function hiding (on) +import GHC.Generics + +import HtmlT.Sketch +import HtmlT.Sketch.FFI + +data TradingPair = TradingPair + { base :: Text + , quote :: Text + , exchange :: Text + } deriving (Show, Eq, Generic) + +data PairSelectorState = PairSelectorState + { selected_pair :: Maybe TradingPair + , options :: [TradingPair] + } deriving (Show, Eq, Generic) + +new :: IO PairSelectorState +new = + return PairSelectorState + { selected_pair = Nothing + , options = [] + } + +html :: BuilderM PairSelectorState () +html = do + el "style" [] $ text styles + div_ [("className", "PairSelector-root")] do + button_ [] do + text "Select pair" + on "click" \_ -> do + modifyFld @"selected_pair" $ \case + Just _ -> Nothing + Nothing -> Just $ TradingPair "BTC" "USDT" "MEXC" + span_ [] $ dynText \s -> s.selected_pair & maybe + "Nothing selected" + (("Selected pair: " <>) . Text.pack . show) + +styles :: Text +styles = "\ + \ \ + \ " diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs new file mode 100644 index 0000000..749c90b --- /dev/null +++ b/examples/charts/charts.hs @@ -0,0 +1,8 @@ +import HtmlT.Sketch +import "this" Charts qualified as Charts + +main :: IO () +main = return () + +foreign export ccall wasm_main :: IO () +wasm_main = Charts.new >>= flip attach Charts.html diff --git a/htmlt.cabal b/htmlt.cabal index 58ffab1..f8ec6df 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -78,17 +78,19 @@ common htmlt-common library import: htmlt-common - hs-source-dirs: src + hs-source-dirs: src ./examples/charts exposed-modules: - HtmlT - HtmlT.Base - HtmlT.DOM - HtmlT.Element - HtmlT.Event - HtmlT.Internal - HtmlT.Main - HtmlT.Property - HtmlT.Types + -- HtmlT + -- HtmlT.Base + -- HtmlT.DOM + -- HtmlT.Element + -- HtmlT.Event + -- HtmlT.Internal + -- HtmlT.Main + -- HtmlT.Property + -- HtmlT.Types + HtmlT.Sketch + HtmlT.Sketch.FFI Wasm.Compat.Prim Wasm.Compat.Marshal @@ -102,39 +104,58 @@ library transformers, ghc-experimental, ghc-prim, + generic-lens, -executable htmlt-counter - import: htmlt-common - main-is: counter.hs - hs-source-dirs: ./examples/counter - ghc-options: - -no-hs-main -optl-mexec-model=reactor - -optl-Wl,--export=hs_init,--export=wasm_main - build-depends: - base, - htmlt, - text, - mtl, - transformers, - if !flag(examples) - buildable: False +-- executable htmlt-counter +-- import: htmlt-common +-- main-is: counter.hs +-- hs-source-dirs: ./examples/counter +-- ghc-options: +-- -no-hs-main -optl-mexec-model=reactor +-- -optl-Wl,--export=hs_init,--export=wasm_main +-- build-depends: +-- base, +-- htmlt, +-- text, +-- mtl, +-- transformers, +-- if !flag(examples) +-- buildable: False -executable htmlt-todomvc +-- executable htmlt-todomvc +-- import: htmlt-common +-- main-is: todomvc.hs +-- hs-source-dirs: ./examples/todomvc +-- ghc-options: +-- -no-hs-main -optl-mexec-model=reactor +-- -optl-Wl,--export=hs_init,--export=wasm_main +-- other-modules: +-- TodoItem +-- TodoList +-- Utils +-- build-depends: +-- base, +-- htmlt, +-- text, +-- mtl, +-- if !flag(examples) +-- buildable: False + +executable htmlt-charts import: htmlt-common - main-is: todomvc.hs - hs-source-dirs: ./examples/todomvc + main-is: charts.hs + hs-source-dirs: ./examples/charts ghc-options: -no-hs-main -optl-mexec-model=reactor -optl-Wl,--export=hs_init,--export=wasm_main - other-modules: - TodoItem - TodoList - Utils build-depends: base, htmlt, text, mtl, + other-modules: + Charts + PairSelector if !flag(examples) buildable: False diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index b5c1e00..f9648f9 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -98,30 +98,24 @@ newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v), getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), -ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziConcziInternalZC: async ($1) => (new Promise(res => setTimeout(res, $1 / 1000))), +ZC0ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, +ZC2ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC1ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC($1,a1)), +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3,$4) => {var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); $1.addEventListener(e, $4);}, +ZC4ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: () => (document.body), +ZC5ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); $1[k] = v;}, +ZC6ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, +ZC7ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); $1.appendChild(n); return n;}, +ZC8ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); $1.appendChild(n); return n;}, +ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), +ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), +ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, +ZC21ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => (__ghc_wasm_jsffi_finalization_registry.register($1, $2, $1)), ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => (`${$1.stack ? $1.stack : $1}`), ZC1ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2) => ((new TextDecoder('utf-8', {fatal: true})).decode(new Uint8Array(__exports.memory.buffer, $1, $2))), ZC2ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written), ZC3ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => ($1.length), ZC4ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => {if (!__ghc_wasm_jsffi_finalization_registry.unregister($1)) { throw new WebAssembly.RuntimeError('js_callback_unregister'); }}, +ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziConcziInternalZC: async ($1) => (new Promise(res => setTimeout(res, $1 / 1000))), ZC18ZCghczminternalZCGHCziInternalziWasmziPrimziImportsZC: ($1,$2) => ($1.then(() => __exports.rts_promiseResolveUnit($2), err => __exports.rts_promiseReject($2, err))), -ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), -ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), -ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, -ZC21ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => (__ghc_wasm_jsffi_finalization_registry.register($1, $2, $1)), -ZC1ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => ($1.length), -ZC2ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written), -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ((new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)))), -ZC9ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1,$2) => ($1[$2]), -ZC14ZChtmltzm0zi1zi0zi0zminplaceZCWasmziCompatziMarshalZC: ($1) => {if ($1 === undefined || $1 === null) return 0; if (typeof $1 === 'boolean') return 1; if (typeof $1 === 'number') return 2; if (typeof $1 === 'string') return 3; if (Array.isArray($1)) return 4; return 5;}, -ZC1ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: async ($1,$2,$3) => ($1.addEventListener($2, $3)), -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC2ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC($1,a1)), -ZC4ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => {$1[$2] = $3;}, -ZC9ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: () => (window.document.body), -ZC16ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createComment($1)), -ZC17ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createTextNode($1)), -ZC19ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1) => (document.createElement($1)), -ZC24ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2,$3) => ($1.insertBefore($2, $3)), -ZC25ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziDOMZC: ($1,$2) => ($1.appendChild($2)), }; }; diff --git a/shell.nix b/shell.nix index ffda97a..82fb296 100644 --- a/shell.nix +++ b/shell.nix @@ -1 +1 @@ -(import ./default.nix {}).shell.x86_64 +(import ./default.nix {}).shell diff --git a/src/HtmlT/Sketch.hs b/src/HtmlT/Sketch.hs new file mode 100644 index 0000000..453e059 --- /dev/null +++ b/src/HtmlT/Sketch.hs @@ -0,0 +1,288 @@ + module HtmlT.Sketch where + +import Control.Monad.State +import Control.Monad.Reader +import Control.Monad.Identity +import Data.Foldable +import Data.Typeable +import Data.Tuple +import Data.IORef +import Control.Monad +import GHC.TypeLits +import Data.Text (Text) +import Data.List qualified as List +import Data.Proxy +import Data.Generics.Product.Fields +import Data.Generics.Internal.VL hiding (build) +import Data.Generics.Sum.Constructors + +import HtmlT.Sketch.FFI +import Wasm.Compat.Prim + +-------------------------- +-- DIFFING AND PATCHING -- +-------------------------- + +data Edit a where + Ins :: a -> Edit a + Fld :: (HasField' f s a, KnownSymbol f, Typeable a) => Proxy f -> Edit a -> Edit s + Ctor :: AsConstructor' ctor s a => Proxy ctor -> Edit a -> Edit s + Ix :: Int -> Edit e -> Edit [e] + Splice :: Int -> Int -> [e] -> Edit [e] + +data SyncOp s where + TextOp :: JSVal -> (s -> Text) -> SyncOp s + PropOp :: JSVal -> Text -> (s -> Text) -> SyncOp s + MapOp :: (Jet s -> Jet t) -> SyncOp t -> SyncOp s + +data Jet a = Jet { position :: a, velocity :: [Edit a] } + +type SyncPlan s = [SyncOp s] + +emptySyncPlan :: SyncPlan s +emptySyncPlan = [] + +data Layout s where + Embed :: (ModifierFn s -> ModifierFn t) -> (Jet s -> Jet t) -> [Layout t] -> Layout s + TextNode :: Text -> Layout s + DynText :: (s -> Text) -> Layout s + ElemNode :: Text -> [(Text, Text)] -> [Layout s] -> Layout s + EventListener :: Text -> (JSVal -> TransitionM s ()) -> Layout s + -- DynNode :: (Jet s -> Jet (Layout s)) -> Layout s + -- SimpleList :: (Jet s -> Jet [a]) -> (Edit [a] -> Edit s) -> Layout a -> Layout s + +patch :: Edit s -> s -> s +patch e s = case e of + Ins s -> s + Fld p e -> pfield p e s + where + pfield :: forall f s a. HasField' f s a => Proxy f -> Edit a -> s -> s + pfield _ e s = over (field' @f) (patch e) s + Ctor p e -> pctor p e s + where + pctor :: forall ctor s a. AsConstructor' ctor s a => Proxy ctor -> Edit a -> s -> s + pctor _ e s = over (_Ctor' @ctor) (patch e) s + Ix i e -> go i e s + where + go :: Int -> Edit e -> [e] -> [e] + go 0 e (x:xs) = patch e x : xs + go _ _ [] = [] + go n e (x:xs) = x : go (n - 1) e xs + Splice ix remove insert -> go insert ix s + where + go :: [e] -> Int -> [e] -> [e] + go ins 0 xs = ins <> List.drop remove xs + go ins n (x:xs) = x : go ins (n - 1) xs + go _ _ [] = [] + +----------------- +-- CORE TYPES -- +----------------- + +newtype BuilderM s a = BuilderM { unBuilderM :: StateT [Layout s] Identity a } + deriving newtype (Functor, Applicative, Monad, MonadState [Layout s]) + +newtype TransitionM s a = TransitionM { unTransitionM :: ReaderT (ModifierFn s) IO a } + deriving newtype (Functor, Applicative, Monad, MonadIO) + +instance MonadState (Jet s) (TransitionM s) where + state f = TransitionM $ ReaderT \(ModifierFn mf) -> mf (swap . f) + +newtype ModifierFn s = ModifierFn {unModifierFn :: forall a. (Jet s -> (Jet s, a)) -> IO a } + +---------------------- +-- STATE MANAGEMENT -- +---------------------- + +edit :: Edit s -> TransitionM s () +edit e = modify \j -> Jet (patch e j.position) (e : j.velocity) + +modifyFld :: forall f s a m. + ( HasField' f s a + , KnownSymbol f + , Typeable a + , MonadState (Jet s) m + ) => + (a -> a) -> + m () +modifyFld f = modify f0 where + f0 :: Jet s -> Jet s + f0 j = Jet s' (e : j.velocity) where + s' = over (field' @f) f j.position + e = Fld (Proxy @f) (Ins (getField @f s')) + +mapModifierFn :: forall s a. + (Edit a -> Edit s) -> + (Jet s -> Jet a) -> + ModifierFn s -> + ModifierFn a +mapModifierFn g f (ModifierFn ms) = ModifierFn f0 where + f0 :: forall x. (Jet a -> (Jet a, x)) -> IO x + f0 fa = ms (f1 fa) + + f1 :: forall x. (Jet a -> (Jet a, x)) -> Jet s -> (Jet s, x) + f1 fa js = (js', x) where + (ja, x) = fa (f js) + js' = Jet js.position (fmap g ja.velocity <> js.velocity) + +refModifier :: forall s. (Jet s -> IO ()) -> IORef s -> ModifierFn s +refModifier up ref = ModifierFn m0 where + m0 :: forall x. (Jet s -> (Jet s, x)) -> IO x + m0 f = do + (x, jet) <- atomicModifyIORef' ref $ m1 f + up jet + return x + + m1 :: forall x. (Jet s -> (Jet s, x)) -> s -> (s, (x, Jet s)) + m1 f s = let (js', x) = f (Jet s []) in (js'.position, (x, js')) + +fldModifierFn :: forall f s a. + ( HasField' f s a + , KnownSymbol f + , Typeable a + ) => + ModifierFn s -> + ModifierFn a +fldModifierFn (ModifierFn ms) = ModifierFn f0 where + f0 :: forall x. (Jet a -> (Jet a, x)) -> IO x + f0 fa = ms (f1 fa) + + f1 :: forall x. (Jet a -> (Jet a, x)) -> Jet s -> (Jet s, x) + f1 fa js = (js', x) where + a = getField @f js.position + s' = setField @f ja.position js.position + (ja, x) = fa (Jet a []) + js' = Jet s' (fmap (Fld (Proxy @f)) ja.velocity <> js.velocity) + +fldJet :: forall f s a. + ( HasField' f s a + , KnownSymbol f + , Typeable a + ) => + Jet s -> Jet a +fldJet js = Jet (getField @f js.position) (fltc js.velocity) where + fltc :: [Edit s] -> [Edit a] + fltc [] = [] + fltc ((Fld p e) : xs) + | Just e' <- chkfld p e = e' : fltc xs + | otherwise = fltc xs + fltc (_ : xs) = fltc xs + + chkfld :: forall f' a'. + ( HasField' f' s a' + , KnownSymbol f' + , Typeable a' + ) => + Proxy f' -> Edit a' -> Maybe (Edit a) + chkfld _ e + | Just Refl <- eqT @f' @f + , Just Refl <- eqT @a' @a = Just e + | otherwise = Nothing + +embedFld :: forall f s a x. + ( HasField' f s a + , KnownSymbol f + , Typeable a + ) => + BuilderM a x -> + BuilderM s x +embedFld b = BuilderM $ StateT $ \l -> Identity (x, (Embed f g l':l)) where + (x, l') = runIdentity $ runStateT b.unBuilderM [] + f = fldModifierFn @f + g = fldJet @f + +------------------ +-- BUILDING DOM -- +------------------ + +el :: Text -> [(Text, Text)] -> BuilderM s a -> BuilderM s a +el tagName attrs children = do + let (res, layout) = runIdentity $ runStateT children.unBuilderM [] + modify (ElemNode tagName attrs layout :) + return res + +text :: Text -> BuilderM s () +text content = modify (TextNode content :) + +dynText :: (s -> Text) -> BuilderM s () +dynText f = modify (DynText f :) + +div_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a +div_ = el "div" + +canvas_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a +canvas_ = el "div" + +span_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a +span_ = el "div" + +h1_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a +h1_ = el "h1" + +button_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a +button_ = el "button" + +select_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a +select_ = el "select" + +on :: Text -> (JSVal -> TransitionM s ()) -> BuilderM s () +on e l = modify (EventListener e l :) + +----------------------------- +-- STARTING AN APPLICATION -- +----------------------------- + +build :: + ModifierFn s -> + [Layout s] -> + s -> + JSVal -> + SyncPlan s -> + IO (SyncPlan s) +build m = go0 . List.reverse where + go0 [] _ _ p = return p + go0 (x:xs) s r p = do { p' <- go1 m x s r p; go0 xs s r p' } + + go1 :: forall s. + ModifierFn s -> + Layout s -> + s -> + JSVal -> + SyncPlan s -> + IO (SyncPlan s) + go1 m (Embed f g l) s r p = do + p' <- build (f m) l ((g (Jet s [])).position) r [] + return $ fmap (MapOp g) p' <> p + go1 m (TextNode t) s r p = + insertText r t >> return p + go1 m (DynText f) s r p = do + textNode <- liftIO $ insertText r $ f s + return $ TextOp textNode f : p + go1 m (ElemNode tagName attrs children) s r p = do + el <- insertElement r tagName + forM_ attrs \(k, v) -> setProperty el k v + -- TODO: Could use insertBefore() to avoid reversing the list! + foldM (\p h -> go1 m h s el p) p $ List.reverse children + go1 m (EventListener eventName listenr) s r p = do + jlisnr <- js_dynExport \event -> flip runReaderT m $ unTransitionM $ listenr event + addEventListener r eventName jlisnr + return p + +sync :: SyncPlan s -> Jet s -> IO () +sync [] _ = return () +sync (x:xs) s = go x s >> sync xs s where + go :: forall s. SyncOp s -> Jet s -> IO () + go (MapOp f op0) s = do + let t = f s + unless (List.null t.velocity) $ go op0 t + go (TextOp textNode f) s = updateTextContent textNode $ f s.position + go (PropOp elemNode propName f) s = setProperty elemNode propName $ f s.position + +attach :: s -> BuilderM s a -> IO a +attach s html = mdo + stateRef <- newIORef s + body <- documentBody + let (res, layout) = runIdentity $ runStateT html.unBuilderM [] + let mod = refModifier (sync plan) stateRef + plan <- build mod layout s body [] + return res diff --git a/src/HtmlT/Sketch/FFI.hs b/src/HtmlT/Sketch/FFI.hs new file mode 100644 index 0000000..d307e5d --- /dev/null +++ b/src/HtmlT/Sketch/FFI.hs @@ -0,0 +1,106 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE ForeignFunctionInterface #-} +{-# LANGUAGE MagicHash #-} + +#if defined(wasm32_HOST_ARCH) +{-# LANGUAGE JavaScriptFFI #-} +#endif +module HtmlT.Sketch.FFI where + +import Control.Monad.IO.Class +import Wasm.Compat.Prim +import GHC.Ptr +import Data.Word +import GHC.Prim +import Data.Text.Internal +import Data.Array.Byte + + +insertText :: JSVal -> Text -> IO JSVal +insertText root (Text (ByteArray arr) off len) = do + let addr = byteArrayContents# arr + js_insertText root (Ptr addr `plusPtr` off) len + +insertElement :: JSVal -> Text -> IO JSVal +insertElement root (Text (ByteArray arr) off len) = do + let addr = byteArrayContents# arr + js_insertElement root (Ptr addr `plusPtr` off) len + +updateTextContent :: JSVal -> Text -> IO () +updateTextContent root (Text (ByteArray arr) off len) = do + let addr = byteArrayContents# arr + js_updateTextContent root (Ptr addr `plusPtr` off) len + +setProperty :: JSVal -> Text -> Text -> IO () +setProperty root (Text (ByteArray arr0) off0 len0) (Text (ByteArray arr1) off1 len1) = do + let addr0 = byteArrayContents# arr0 + let addr1 = byteArrayContents# arr1 + js_setProperty root (Ptr addr0 `plusPtr` off0) len0 (Ptr addr1 `plusPtr` off1) len1 + +addEventListener :: JSVal -> Text -> JSVal -> IO () +addEventListener root (Text (ByteArray arr) off len) lisnr = do + let addr = byteArrayContents# arr + js_addEventListener root (Ptr addr `plusPtr` off) len lisnr + +consoleLog :: MonadIO m => Text -> m () +consoleLog (Text (ByteArray arr) off len) = liftIO do + let addr = byteArrayContents# arr + js_consoleLog (Ptr addr `plusPtr` off) len + +#if !defined(wasm32_HOST_ARCH) +js_insertText :: JSVal -> Ptr Word8 -> Int -> IO JSVal +js_insertText = undefined + +js_insertElement :: JSVal -> Ptr Word8 -> Int -> IO JSVal +js_insertElement = undefined + +js_updateTextContent :: JSVal -> Ptr Word8 -> Int -> IO () +js_updateTextContent = undefined + +js_setProperty :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () +js_setProperty = undefined + +js_addEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () +js_addEventListener = undefined + +js_dynExport :: (JSVal -> IO ()) -> IO JSVal +js_dynExport = undefined + +documentBody :: IO JSVal +documentBody = undefined + +js_consoleLog :: Ptr Word8 -> Int -> IO () +js_consoleLog = undefined + +#else +foreign import javascript unsafe + "var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ + var n = document.createTextNode(c);\ + $1.appendChild(n);\ + return n;" + js_insertText :: JSVal -> Ptr Word8 -> Int -> IO JSVal +foreign import javascript unsafe + "var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ + var n = document.createElement(t);\ + $1.appendChild(n);\ + return n;" + js_insertElement :: JSVal -> Ptr Word8 -> Int -> IO JSVal +foreign import javascript unsafe + "$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));" + js_updateTextContent :: JSVal -> Ptr Word8 -> Int -> IO () +foreign import javascript unsafe + "var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ + var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5));\ + $1[k] = v;" + js_setProperty :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () +foreign import javascript unsafe "document.body" documentBody :: IO JSVal +foreign import javascript unsafe + "var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ + $1.addEventListener(e, $4);" + js_addEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () +foreign import javascript "wrapper" js_dynExport :: (JSVal -> IO ()) -> IO JSVal +foreign import javascript unsafe + "console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));" + js_consoleLog :: Ptr Word8 -> Int -> IO () +#endif From 2baeb49735a893211f80821a7adc1f97d11e9d9a Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 21 Mar 2024 17:14:25 +0400 Subject: [PATCH 09/64] WIP --- examples/charts/App.hs | 32 ++++++ examples/charts/charts.hs | 4 +- src/HtmlT/Sketch.hs | 203 +++++++++++++++++++++++--------------- 3 files changed, 159 insertions(+), 80 deletions(-) create mode 100644 examples/charts/App.hs diff --git a/examples/charts/App.hs b/examples/charts/App.hs new file mode 100644 index 0000000..23f196e --- /dev/null +++ b/examples/charts/App.hs @@ -0,0 +1,32 @@ +module App where + +import Charts qualified as Charts +import Control.Monad.State +import Data.Proxy +import Data.Text (Text) +import Data.Text qualified as Text +import GHC.Generics +import HtmlT.Sketch +import HtmlT.Sketch.FFI + + +data AppState = AppState + { charts_instance :: Charts.ChartState + } deriving (Show, Eq, Generic) + +new :: IO AppState +new = do + charts_instance <- Charts.new + return AppState + { charts_instance + } + +html :: BuilderM AppState () +html = do + el "style" [] $ text styles + embedFld @"charts_instance" Charts.html + +styles :: Text +styles = "\ + \ \ + \ " diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs index 749c90b..4e5daa7 100644 --- a/examples/charts/charts.hs +++ b/examples/charts/charts.hs @@ -1,8 +1,8 @@ import HtmlT.Sketch -import "this" Charts qualified as Charts +import "this" App qualified as App main :: IO () main = return () foreign export ccall wasm_main :: IO () -wasm_main = Charts.new >>= flip attach Charts.html +wasm_main = App.new >>= flip attach App.html diff --git a/src/HtmlT/Sketch.hs b/src/HtmlT/Sketch.hs index 453e059..618d1ee 100644 --- a/src/HtmlT/Sketch.hs +++ b/src/HtmlT/Sketch.hs @@ -1,20 +1,23 @@ - module HtmlT.Sketch where +module HtmlT.Sketch where -import Control.Monad.State -import Control.Monad.Reader +import Control.Monad import Control.Monad.Identity +import Control.Monad.Reader +import Control.Monad.State import Data.Foldable -import Data.Typeable -import Data.Tuple -import Data.IORef -import Control.Monad -import GHC.TypeLits -import Data.Text (Text) -import Data.List qualified as List -import Data.Proxy -import Data.Generics.Product.Fields import Data.Generics.Internal.VL hiding (build) +import Data.Generics.Product.Fields import Data.Generics.Sum.Constructors +import Data.IORef +import Data.List qualified as List +import Data.Text (Text) +import Data.Tuple +import Data.Typeable +import Data.Map (Map) +import Data.Map qualified as Map +import GHC.Generics +import GHC.Exts hiding (build) +import GHC.TypeLits import HtmlT.Sketch.FFI import Wasm.Compat.Prim @@ -25,25 +28,75 @@ import Wasm.Compat.Prim data Edit a where Ins :: a -> Edit a - Fld :: (HasField' f s a, KnownSymbol f, Typeable a) => Proxy f -> Edit a -> Edit s - Ctor :: AsConstructor' ctor s a => Proxy ctor -> Edit a -> Edit s + Fld :: + ( HasField' f s a + , KnownSymbol f + , Typeable a + ) => + Proxy f -> Edit a -> Edit s + Ctor :: + ( AsConstructor' ctor s a + , KnownSymbol ctor + , Typeable a + ) => Proxy ctor -> Edit a -> Edit s + Sum :: SumCtor ctor s a => Edit a -> Edit s Ix :: Int -> Edit e -> Edit [e] Splice :: Int -> Int -> [e] -> Edit [e] -data SyncOp s where - TextOp :: JSVal -> (s -> Text) -> SyncOp s - PropOp :: JSVal -> Text -> (s -> Text) -> SyncOp s - MapOp :: (Jet s -> Jet t) -> SyncOp t -> SyncOp s +type SyncPlan s = [SyncOp s] -data Jet a = Jet { position :: a, velocity :: [Edit a] } +class SumCtor ctor s a | ctor s -> a -type SyncPlan s = [SyncOp s] +instance SumCtor "In1" (Sum a b) a + +instance SumCtor "In2" (Sum a b) b -emptySyncPlan :: SyncPlan s -emptySyncPlan = [] +patch :: Edit s -> s -> s +patch (Ins s) _ = s +patch (Fld p e) s = pfld p e s where + pfld :: forall f s a. HasField' f s a => Proxy f -> Edit a -> s -> s + pfld _ e s = over (field' @f) (patch e) s +patch (Ctor p e) s = pctor p e s where + pctor :: forall ctor s a. AsConstructor' ctor s a => Proxy ctor -> Edit a -> s -> s + pctor _ e s = over (_Ctor' @ctor) (patch e) s +patch (Ix i e) s = go i e s where + go :: Int -> Edit e -> [e] -> [e] + go 0 e (x:xs) = patch e x : xs + go _ _ [] = [] + go n e (x:xs) = x : go (n - 1) e xs +patch (Splice i rem ins) s = go ins i s where + go :: [e] -> Int -> [e] -> [e] + go ins 0 xs = ins <> List.drop rem xs + go ins n (x:xs) = x : go ins (n - 1) xs + go _ _ [] = [] + +------------------------------------------------------------ +-- INCREMENTAL OPTICS USED FOR EMBEDDING COMPONENT STATES -- +------------------------------------------------------------ + +data IncOptic s a where + FldLens :: + ( HasField' f s a + , KnownSymbol f + , Typeable a + ) => Proxy f -> IncOptic s a + IxTrav :: + Int -> IncOptic [a] a + CtorPrism :: + ( AsConstructor' ctor s a + , KnownSymbol ctor + , Typeable a + ) => Proxy ctor -> IncOptic s a + Comp :: IncOptic s x -> IncOptic x a -> IncOptic s a + +type IncGetter s a = Jet s -> Jet a + +----------------- +-- CORE TYPES -- +----------------- data Layout s where - Embed :: (ModifierFn s -> ModifierFn t) -> (Jet s -> Jet t) -> [Layout t] -> Layout s + EmbedNode :: (ModifierFn s -> ModifierFn t) -> (Jet s -> Jet t) -> [Layout t] -> Layout s TextNode :: Text -> Layout s DynText :: (s -> Text) -> Layout s ElemNode :: Text -> [(Text, Text)] -> [Layout s] -> Layout s @@ -51,33 +104,12 @@ data Layout s where -- DynNode :: (Jet s -> Jet (Layout s)) -> Layout s -- SimpleList :: (Jet s -> Jet [a]) -> (Edit [a] -> Edit s) -> Layout a -> Layout s -patch :: Edit s -> s -> s -patch e s = case e of - Ins s -> s - Fld p e -> pfield p e s - where - pfield :: forall f s a. HasField' f s a => Proxy f -> Edit a -> s -> s - pfield _ e s = over (field' @f) (patch e) s - Ctor p e -> pctor p e s - where - pctor :: forall ctor s a. AsConstructor' ctor s a => Proxy ctor -> Edit a -> s -> s - pctor _ e s = over (_Ctor' @ctor) (patch e) s - Ix i e -> go i e s - where - go :: Int -> Edit e -> [e] -> [e] - go 0 e (x:xs) = patch e x : xs - go _ _ [] = [] - go n e (x:xs) = x : go (n - 1) e xs - Splice ix remove insert -> go insert ix s - where - go :: [e] -> Int -> [e] -> [e] - go ins 0 xs = ins <> List.drop remove xs - go ins n (x:xs) = x : go ins (n - 1) xs - go _ _ [] = [] +data SyncOp s where + TextOp :: JSVal -> (s -> Text) -> SyncOp s + PropOp :: JSVal -> Text -> (s -> Text) -> SyncOp s + MapOp :: (Jet s -> Jet t) -> SyncOp t -> SyncOp s ------------------ --- CORE TYPES -- ------------------ +data Jet a = Jet { position :: a, velocity :: [Edit a] } newtype BuilderM s a = BuilderM { unBuilderM :: StateT [Layout s] Identity a } deriving newtype (Functor, Applicative, Monad, MonadState [Layout s]) @@ -126,15 +158,15 @@ mapModifierFn g f (ModifierFn ms) = ModifierFn f0 where js' = Jet js.position (fmap g ja.velocity <> js.velocity) refModifier :: forall s. (Jet s -> IO ()) -> IORef s -> ModifierFn s -refModifier up ref = ModifierFn m0 where - m0 :: forall x. (Jet s -> (Jet s, x)) -> IO x - m0 f = do - (x, jet) <- atomicModifyIORef' ref $ m1 f +refModifier up ref = ModifierFn f0 where + f0 :: forall x. (Jet s -> (Jet s, x)) -> IO x + f0 f = do + (x, jet) <- atomicModifyIORef' ref $ f1 f up jet return x - m1 :: forall x. (Jet s -> (Jet s, x)) -> s -> (s, (x, Jet s)) - m1 f s = let (js', x) = f (Jet s []) in (js'.position, (x, js')) + f1 :: forall x. (Jet s -> (Jet s, x)) -> s -> (s, (x, Jet s)) + f1 f s = let (js', x) = f (Jet s []) in (js'.position, (x, js')) fldModifierFn :: forall f s a. ( HasField' f s a @@ -179,18 +211,6 @@ fldJet js = Jet (getField @f js.position) (fltc js.velocity) where , Just Refl <- eqT @a' @a = Just e | otherwise = Nothing -embedFld :: forall f s a x. - ( HasField' f s a - , KnownSymbol f - , Typeable a - ) => - BuilderM a x -> - BuilderM s x -embedFld b = BuilderM $ StateT $ \l -> Identity (x, (Embed f g l':l)) where - (x, l') = runIdentity $ runStateT b.unBuilderM [] - f = fldModifierFn @f - g = fldJet @f - ------------------ -- BUILDING DOM -- ------------------ @@ -228,9 +248,33 @@ select_ = el "select" on :: Text -> (JSVal -> TransitionM s ()) -> BuilderM s () on e l = modify (EventListener e l :) ------------------------------ --- STARTING AN APPLICATION -- ------------------------------ +-------------------------- +-- COMPONENT EMBEDDING -- +-------------------------- + +embedFld :: forall f s a x. + ( HasField' f s a + , KnownSymbol f + , Typeable a + ) => + BuilderM a x -> + BuilderM s x +embedFld b = BuilderM $ StateT st where + st l = Identity (x, (n:l)) + n = EmbedNode (fldModifierFn @f) (fldJet @f) l' + (x, l') = runIdentity $ runStateT b.unBuilderM [] + +data Sum a b = In1 a | In2 b deriving Generic + +embedSum :: + BuilderM a x -> + BuilderM b x -> + BuilderM (Sum a b) x +embedSum b = undefined + +-------------------------- +-- START AN APPLICATION -- +-------------------------- build :: ModifierFn s -> @@ -243,14 +287,7 @@ build m = go0 . List.reverse where go0 [] _ _ p = return p go0 (x:xs) s r p = do { p' <- go1 m x s r p; go0 xs s r p' } - go1 :: forall s. - ModifierFn s -> - Layout s -> - s -> - JSVal -> - SyncPlan s -> - IO (SyncPlan s) - go1 m (Embed f g l) s r p = do + go1 m (EmbedNode f g l) s r p = do p' <- build (f m) l ((g (Jet s [])).position) r [] return $ fmap (MapOp g) p' <> p go1 m (TextNode t) s r p = @@ -286,3 +323,13 @@ attach s html = mdo let mod = refModifier (sync plan) stateRef plan <- build mod layout s body [] return res + +------------------------------- +-- REATIVE STUFF RESURRECTED -- +------------------------------- + +data IncRef t a where + TipRef :: RefId -> IORef a -> IncRef t a + MapRef :: IncOptic s a -> IncRef t a + +type RefId = Int From 0e9a8346c7f95e87b3b5daf8c451af84bb5000b8 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 21 Mar 2024 20:09:46 +0400 Subject: [PATCH 10/64] WIP --- examples/charts/App.hs | 4 +- examples/charts/Charts.hs | 4 +- examples/charts/PairSelector.hs | 4 +- examples/charts/charts.hs | 2 +- examples/counter/counter.hs | 35 - examples/simple-routing/Assets.hs | 4242 --------------------- examples/simple-routing/Pages.hs | 219 -- examples/simple-routing/Router.hs | 185 - examples/simple-routing/Utils.hs | 82 - examples/simple-routing/simple-routing.hs | 72 - examples/todomvc/TodoItem.hs | 113 - examples/todomvc/TodoList.hs | 586 --- examples/todomvc/Utils.hs | 80 - examples/todomvc/todomvc.hs | 25 - htmlt.cabal | 4 +- jsbits/jsffi.js | 16 +- src/HtmlT.hs | 15 - src/HtmlT/Base.hs | 296 -- src/HtmlT/DOM.hs | 518 --- src/HtmlT/Element.hs | 403 -- src/HtmlT/Event.hs | 475 --- src/HtmlT/Internal.hs | 44 - src/HtmlT/Main.hs | 74 - src/HtmlT/Property.hs | 368 -- src/HtmlT/Types.hs | 71 - src/{HtmlT => }/Sketch.hs | 37 +- src/{HtmlT => }/Sketch/FFI.hs | 2 +- 27 files changed, 49 insertions(+), 7927 deletions(-) delete mode 100644 examples/counter/counter.hs delete mode 100644 examples/simple-routing/Assets.hs delete mode 100644 examples/simple-routing/Pages.hs delete mode 100644 examples/simple-routing/Router.hs delete mode 100644 examples/simple-routing/Utils.hs delete mode 100644 examples/simple-routing/simple-routing.hs delete mode 100644 examples/todomvc/TodoItem.hs delete mode 100644 examples/todomvc/TodoList.hs delete mode 100644 examples/todomvc/Utils.hs delete mode 100644 examples/todomvc/todomvc.hs delete mode 100644 src/HtmlT.hs delete mode 100644 src/HtmlT/Base.hs delete mode 100644 src/HtmlT/DOM.hs delete mode 100644 src/HtmlT/Element.hs delete mode 100644 src/HtmlT/Event.hs delete mode 100644 src/HtmlT/Internal.hs delete mode 100644 src/HtmlT/Main.hs delete mode 100644 src/HtmlT/Property.hs delete mode 100644 src/HtmlT/Types.hs rename src/{HtmlT => }/Sketch.hs (92%) rename src/{HtmlT => }/Sketch/FFI.hs (99%) diff --git a/examples/charts/App.hs b/examples/charts/App.hs index 23f196e..c2c92cf 100644 --- a/examples/charts/App.hs +++ b/examples/charts/App.hs @@ -6,8 +6,8 @@ import Data.Proxy import Data.Text (Text) import Data.Text qualified as Text import GHC.Generics -import HtmlT.Sketch -import HtmlT.Sketch.FFI +import Sketch +import Sketch.FFI data AppState = AppState diff --git a/examples/charts/Charts.hs b/examples/charts/Charts.hs index 866f550..adcd3b5 100644 --- a/examples/charts/Charts.hs +++ b/examples/charts/Charts.hs @@ -6,8 +6,8 @@ import Data.Text (Text) import Data.Text qualified as Text import GHC.Generics -import HtmlT.Sketch -import HtmlT.Sketch.FFI +import Sketch +import Sketch.FFI import PairSelector qualified as PairSelector ------------------------------------------------------- diff --git a/examples/charts/PairSelector.hs b/examples/charts/PairSelector.hs index 939ba17..48ba0ce 100644 --- a/examples/charts/PairSelector.hs +++ b/examples/charts/PairSelector.hs @@ -6,8 +6,8 @@ import Data.Text qualified as Text import Data.Function hiding (on) import GHC.Generics -import HtmlT.Sketch -import HtmlT.Sketch.FFI +import Sketch +import Sketch.FFI data TradingPair = TradingPair { base :: Text diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs index 4e5daa7..01333be 100644 --- a/examples/charts/charts.hs +++ b/examples/charts/charts.hs @@ -1,4 +1,4 @@ -import HtmlT.Sketch +import Sketch import "this" App qualified as App main :: IO () diff --git a/examples/counter/counter.hs b/examples/counter/counter.hs deleted file mode 100644 index 8808f9b..0000000 --- a/examples/counter/counter.hs +++ /dev/null @@ -1,35 +0,0 @@ -import Control.Monad -import HtmlT -import Text.Read (readMaybe) -import Data.Text qualified as Text -import Data.Function ((&)) -import Control.Monad.Trans -import Control.Monad.Reader -import Control.Concurrent - -app :: Html () -app = do - -- First create a 'DynRef - counterRef <- lift $ newRef @Int 0 - div_ do - input_ [type_ "number"] do - -- Show the value inside - dynProp "value" $ Text.pack . show <$> fromRef counterRef - -- Parse and update the value on each InputEvent - on @"input" \inp -> - readMaybe (Text.unpack inp) & mapM_ (writeRef counterRef) - br_ - -- Decrease the value on each click - button_ do - on @"click" $ modifyRef counterRef pred - text "-" - -- Increase the value on each click - button_ do - on @"click" $ modifyRef counterRef succ - text "+" - -foreign export ccall wasm_main :: IO () -wasm_main = void $ attachToBody app - -main :: IO () -main = return () diff --git a/examples/simple-routing/Assets.hs b/examples/simple-routing/Assets.hs deleted file mode 100644 index 42d4549..0000000 --- a/examples/simple-routing/Assets.hs +++ /dev/null @@ -1,4242 +0,0 @@ -module Assets where - -import GHC.Generics -import Wasm.Compat.Prim -import Data.Text - -data Country = Country - { title :: Text - , code :: Text - , wiki_href :: Text - , population :: Int - , flag_icon :: Maybe Text - , region :: Text - , subregion :: Text - } deriving Generic - -countries :: [Country] -countries = - [ Country "China" "CN" "https://en.wikipedia.org/wiki/China" 1433783686 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Flag_of_the_People%27s_Republic_of_China.svg/23px-Flag_of_the_People%27s_Republic_of_China.svg.png") "Asia" "Eastern Asia" - , Country "India" "IN" "https://en.wikipedia.org/wiki/India" 1366417754 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/4/41/Flag_of_India.svg/23px-Flag_of_India.svg.png") "Asia" "Southern Asia" - , Country "United States" "us" "https://en.wikipedia.org/wiki/United_States" 329064917 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/23px-Flag_of_the_United_States.svg.png") "Americas" "Northern America" - , Country "Indonesia" "ID" "https://en.wikipedia.org/wiki/Indonesia" 270625568 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/Flag_of_Indonesia.svg/23px-Flag_of_Indonesia.svg.png") "Asia" "South-eastern Asia" - , Country "Pakistan" "PK" "https://en.wikipedia.org/wiki/Pakistan" 216565318 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Flag_of_Pakistan.svg/23px-Flag_of_Pakistan.svg.png") "Asia" "Southern Asia" - , Country "Brazil" "BR" "https://en.wikipedia.org/wiki/Brazil" 211049527 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/0/05/Flag_of_Brazil.svg/22px-Flag_of_Brazil.svg.png") "Americas" "South America" - , Country "Nigeria" "NG" "https://en.wikipedia.org/wiki/Nigeria" 200963599 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/79/Flag_of_Nigeria.svg/23px-Flag_of_Nigeria.svg.png") "Africa" "Western Africa" - , Country "Bangladesh" "BD" "https://en.wikipedia.org/wiki/Bangladesh" 163046161 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Flag_of_Bangladesh.svg/23px-Flag_of_Bangladesh.svg.png") "Asia" "Southern Asia" - , Country "Russia" "RU" "https://en.wikipedia.org/wiki/Russia" 145872256 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/f/f3/Flag_of_Russia.svg/23px-Flag_of_Russia.svg.png") "Europe" "Eastern Europe" - , Country "Mexico" "MX" "https://en.wikipedia.org/wiki/Mexico" 127575529 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Flag_of_Mexico.svg/23px-Flag_of_Mexico.svg.png") "Americas" "Central America" - , Country "Japan" "JP" "https://en.wikipedia.org/wiki/Japan" 126860301 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/9/9e/Flag_of_Japan.svg/23px-Flag_of_Japan.svg.png") "Asia" "Eastern Asia" - , Country "Ethiopia" "ET" "https://en.wikipedia.org/wiki/Ethiopia" 112078730 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/Flag_of_Ethiopia.svg/23px-Flag_of_Ethiopia.svg.png") "Africa" "Eastern Africa" - , Country "Philippines" "PH" "https://en.wikipedia.org/wiki/Philippines" 108116615 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/Flag_of_the_Philippines.svg/23px-Flag_of_the_Philippines.svg.png") "Asia" "South-eastern Asia" - , Country "Egypt" "EG" "https://en.wikipedia.org/wiki/Egypt" 100388073 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Flag_of_Egypt.svg/23px-Flag_of_Egypt.svg.png") "Africa" "Northern Africa" - , Country "Vietnam" "VN" "https://en.wikipedia.org/wiki/Vietnam" 96462106 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Flag_of_Vietnam.svg/23px-Flag_of_Vietnam.svg.png") "Asia" "South-eastern Asia" - , Country "DR Congo" "CD" "https://en.wikipedia.org/wiki/Democratic_Republic_of_the_Congo" 86790567 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Flag_of_the_Democratic_Republic_of_the_Congo.svg/20px-Flag_of_the_Democratic_Republic_of_the_Congo.svg.png") "Africa" "Middle Africa" - , Country "Germany" "DE" "https://en.wikipedia.org/wiki/Germany" 83517045 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/b/ba/Flag_of_Germany.svg/23px-Flag_of_Germany.svg.png") "Europe" "Western Europe" - , Country "Turkey" "TR" "https://en.wikipedia.org/wiki/Turkey" 83429615 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/Flag_of_Turkey.svg/23px-Flag_of_Turkey.svg.png") "Asia" "Western Asia" - , Country "Iran" "IR" "https://en.wikipedia.org/wiki/Iran" 82913906 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Flag_of_Iran.svg/23px-Flag_of_Iran.svg.png") "Asia" "Southern Asia" - , Country "Thailand" "TH" "https://en.wikipedia.org/wiki/Thailand" 69037513 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Flag_of_Thailand.svg/23px-Flag_of_Thailand.svg.png") "Asia" "South-eastern Asia" - , Country "United Kingdom" "UK" "https://en.wikipedia.org/wiki/United_Kingdom" 67530172 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/a/ae/Flag_of_the_United_Kingdom.svg/23px-Flag_of_the_United_Kingdom.svg.png") "Europe" "Northern Europe" - , Country "France" "FR" "https://en.wikipedia.org/wiki/France" 65129728 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/c/c3/Flag_of_France.svg/23px-Flag_of_France.svg.png") "Europe" "Western Europe" - , Country "Italy" "IT" "https://en.wikipedia.org/wiki/Italy" 60550075 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/0/03/Flag_of_Italy.svg/23px-Flag_of_Italy.svg.png") "Europe" "Southern Europe" - , Country "South Africa" "ZA" "https://en.wikipedia.org/wiki/South_Africa" 58558270 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Flag_of_South_Africa.svg/23px-Flag_of_South_Africa.svg.png") "Africa" "Southern Africa" - , Country "Tanzania" "TZ" "https://en.wikipedia.org/wiki/Tanzania" 58005463 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Flag_of_Tanzania.svg/23px-Flag_of_Tanzania.svg.png") "Africa" "Eastern Africa" - , Country "Myanmar" "MM" "https://en.wikipedia.org/wiki/Myanmar" 54045420 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/Flag_of_Myanmar.svg/23px-Flag_of_Myanmar.svg.png") "Asia" "South-eastern Asia" - , Country "Kenya" "KE" "https://en.wikipedia.org/wiki/Kenya" 52573973 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Flag_of_Kenya.svg/23px-Flag_of_Kenya.svg.png") "Africa" "Eastern Africa" - , Country "South Korea" "KR" "https://en.wikipedia.org/wiki/South_Korea" 51225308 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/Flag_of_South_Korea.svg/23px-Flag_of_South_Korea.svg.png") "Asia" "Eastern Asia" - , Country "Colombia" "CO" "https://en.wikipedia.org/wiki/Colombia" 50339443 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Flag_of_Colombia.svg/23px-Flag_of_Colombia.svg.png") "Americas" "South America" - , Country "Spain" "ES" "https://en.wikipedia.org/wiki/Spain" 46736776 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/9/9a/Flag_of_Spain.svg/23px-Flag_of_Spain.svg.png") "Europe" "Southern Europe" - , Country "Argentina" "AR" "https://en.wikipedia.org/wiki/Argentina" 44780677 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Flag_of_Argentina.svg/23px-Flag_of_Argentina.svg.png") "Americas" "South America" - , Country "Uganda" "UG" "https://en.wikipedia.org/wiki/Uganda" 44269594 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Flag_of_Uganda.svg/23px-Flag_of_Uganda.svg.png") "Africa" "Eastern Africa" - , Country "Ukraine" "UA" "https://en.wikipedia.org/wiki/Ukraine" 43993638 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Flag_of_Ukraine.svg/23px-Flag_of_Ukraine.svg.png") "Europe" "Eastern Europe" - , Country "Algeria" "DZ" "https://en.wikipedia.org/wiki/Algeria" 43053054 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Flag_of_Algeria.svg/23px-Flag_of_Algeria.svg.png") "Africa" "Northern Africa" - , Country "Sudan" "SD" "https://en.wikipedia.org/wiki/Sudan" 42813238 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Sudan.svg/23px-Flag_of_Sudan.svg.png") "Africa" "Northern Africa" - , Country "Iraq" "IQ" "https://en.wikipedia.org/wiki/Iraq" 39309783 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Flag_of_Iraq.svg/23px-Flag_of_Iraq.svg.png") "Asia" "Western Asia" - , Country "Afghanistan" "AF" "https://en.wikipedia.org/wiki/Afghanistan" 38041754 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Flag_of_the_Taliban.svg/23px-Flag_of_the_Taliban.svg.png") "Asia" "Southern Asia" - , Country "Poland" "PL" "https://en.wikipedia.org/wiki/Poland" 37887768 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/1/12/Flag_of_Poland.svg/23px-Flag_of_Poland.svg.png") "Europe" "Eastern Europe" - , Country "Canada" "CA" "https://en.wikipedia.org/wiki/Canada" 37411047 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Flag_of_Canada_%28Pantone%29.svg/23px-Flag_of_Canada_%28Pantone%29.svg.png") "Americas" "Northern America" - , Country "Morocco" "MA" "https://en.wikipedia.org/wiki/Morocco" 36471769 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Flag_of_Morocco.svg/23px-Flag_of_Morocco.svg.png") "Africa" "Northern Africa" - , Country "Saudi Arabia" "SA" "https://en.wikipedia.org/wiki/Saudi_Arabia" 34268528 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Flag_of_Saudi_Arabia.svg/23px-Flag_of_Saudi_Arabia.svg.png") "Asia" "Western Asia" - , Country "Uzbekistan" "UZ" "https://en.wikipedia.org/wiki/Uzbekistan" 32981716 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Flag_of_Uzbekistan.svg/23px-Flag_of_Uzbekistan.svg.png") "Asia" "Central Asia" - , Country "Peru" "PE" "https://en.wikipedia.org/wiki/Peru" 32510453 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Flag_of_Peru.svg/23px-Flag_of_Peru.svg.png") "Americas" "South America" - , Country "Malaysia" "MY" "https://en.wikipedia.org/wiki/Malaysia" 31949777 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Flag_of_Malaysia.svg/23px-Flag_of_Malaysia.svg.png") "Asia" "South-eastern Asia" - , Country "Angola" "AO" "https://en.wikipedia.org/wiki/Angola" 31825295 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Flag_of_Angola.svg/23px-Flag_of_Angola.svg.png") "Africa" "Middle Africa" - , Country "Mozambique" "MZ" "https://en.wikipedia.org/wiki/Mozambique" 30366036 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Flag_of_Mozambique.svg/23px-Flag_of_Mozambique.svg.png") "Africa" "Eastern Africa" - , Country "Yemen" "YE" "https://en.wikipedia.org/wiki/Yemen" 29161922 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Flag_of_Yemen.svg/23px-Flag_of_Yemen.svg.png") "Asia" "Western Asia" - , Country "Ghana" "GH" "https://en.wikipedia.org/wiki/Ghana" 28833629 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Flag_of_Ghana.svg/23px-Flag_of_Ghana.svg.png") "Africa" "Western Africa" - , Country "Nepal" "NP" "https://en.wikipedia.org/wiki/Nepal" 28608710 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9b/Flag_of_Nepal.svg/16px-Flag_of_Nepal.svg.png") "Asia" "Southern Asia" - , Country "Venezuela" "VE" "https://en.wikipedia.org/wiki/Venezuela" 28515829 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Flag_of_Venezuela.svg/23px-Flag_of_Venezuela.svg.png") "Americas" "South America" - , Country "Madagascar" "MG" "https://en.wikipedia.org/wiki/Madagascar" 26969307 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Flag_of_Madagascar.svg/23px-Flag_of_Madagascar.svg.png") "Africa" "Eastern Africa" - , Country "North Korea" "KP" "https://en.wikipedia.org/wiki/North_Korea" 25666161 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Flag_of_North_Korea.svg/23px-Flag_of_North_Korea.svg.png") "Asia" "Eastern Asia" - , Country "Ivory Coast" "CI" "https://en.wikipedia.org/wiki/Ivory_Coast" 25716544 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Flag_of_C%C3%B4te_d%27Ivoire.svg/23px-Flag_of_C%C3%B4te_d%27Ivoire.svg.png") "Africa" "Western Africa" - , Country "Cameroon" "CM" "https://en.wikipedia.org/wiki/Cameroon" 25876380 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/Flag_of_Cameroon.svg/23px-Flag_of_Cameroon.svg.png") "Africa" "Middle Africa" - , Country "Australia" "AU" "https://en.wikipedia.org/wiki/Australia" 25203198 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/88/Flag_of_Australia_%28converted%29.svg/23px-Flag_of_Australia_%28converted%29.svg.png") "Oceania" "Australia and New Zealand" - , Country "Taiwan" "TW" "https://en.wikipedia.org/wiki/Taiwan" 23773876 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Flag_of_the_Republic_of_China.svg/23px-Flag_of_the_Republic_of_China.svg.png") "Asia" "Eastern Asia" - , Country "Niger" "NE" "https://en.wikipedia.org/wiki/Niger" 23310715 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/Flag_of_Niger.svg/18px-Flag_of_Niger.svg.png") "Africa" "Western Africa" - , Country "Sri Lanka" "LK" "https://en.wikipedia.org/wiki/Sri_Lanka" 21323733 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Flag_of_Sri_Lanka.svg/23px-Flag_of_Sri_Lanka.svg.png") "Asia" "Southern Asia" - , Country "Burkina Faso" "BF" "https://en.wikipedia.org/wiki/Burkina_Faso" 20321378 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Flag_of_Burkina_Faso.svg/23px-Flag_of_Burkina_Faso.svg.png") "Africa" "Western Africa" - , Country "Mali" "ML" "https://en.wikipedia.org/wiki/Mali" 19658031 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Flag_of_Mali.svg/23px-Flag_of_Mali.svg.png") "Africa" "Western Africa" - , Country "Romania" "RO" "https://en.wikipedia.org/wiki/Romania" 19364557 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Flag_of_Romania.svg/23px-Flag_of_Romania.svg.png") "Europe" "Eastern Europe" - , Country "Malawi" "MW" "https://en.wikipedia.org/wiki/Malawi" 18628747 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Flag_of_Malawi.svg/23px-Flag_of_Malawi.svg.png") "Africa" "Eastern Africa" - , Country "Chile" "CL" "https://en.wikipedia.org/wiki/Chile" 18952038 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Flag_of_Chile.svg/23px-Flag_of_Chile.svg.png") "Americas" "South America" - , Country "Kazakhstan" "KZ" "https://en.wikipedia.org/wiki/Kazakhstan" 18551427 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Flag_of_Kazakhstan.svg/23px-Flag_of_Kazakhstan.svg.png") "Asia" "Central Asia" - , Country "Zambia" "ZM" "https://en.wikipedia.org/wiki/Zambia" 17861030 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Flag_of_Zambia.svg/23px-Flag_of_Zambia.svg.png") "Africa" "Eastern Africa" - , Country "Guatemala" "GT" "https://en.wikipedia.org/wiki/Guatemala" 17581472 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Flag_of_Guatemala.svg/23px-Flag_of_Guatemala.svg.png") "Americas" "Central America" - , Country "Ecuador" "EC" "https://en.wikipedia.org/wiki/Ecuador" 17373662 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Flag_of_Ecuador.svg/23px-Flag_of_Ecuador.svg.png") "Americas" "South America" - , Country "Netherlands" "NL" "https://en.wikipedia.org/wiki/Netherlands" 17097130 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Flag_of_the_Netherlands.svg/23px-Flag_of_the_Netherlands.svg.png") "Europe" "Western Europe" - , Country "Syria" "SY" "https://en.wikipedia.org/wiki/Syria" 17070135 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Flag_of_Syria.svg/23px-Flag_of_Syria.svg.png") "Asia" "Western Asia" - , Country "Cambodia" "KH" "https://en.wikipedia.org/wiki/Cambodia" 16486542 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Flag_of_Cambodia.svg/23px-Flag_of_Cambodia.svg.png") "Asia" "South-eastern Asia" - , Country "Senegal" "SN" "https://en.wikipedia.org/wiki/Senegal" 16296364 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Flag_of_Senegal.svg/23px-Flag_of_Senegal.svg.png") "Africa" "Western Africa" - , Country "Chad" "TD" "https://en.wikipedia.org/wiki/Chad" 15946876 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Flag_of_Chad.svg/23px-Flag_of_Chad.svg.png") "Africa" "Middle Africa" - , Country "Somalia" "SO" "https://en.wikipedia.org/wiki/Somalia" 15442905 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Flag_of_Somalia.svg/23px-Flag_of_Somalia.svg.png") "Africa" "Eastern Africa" - , Country "Zimbabwe" "ZW" "https://en.wikipedia.org/wiki/Zimbabwe" 14645468 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Flag_of_Zimbabwe.svg/23px-Flag_of_Zimbabwe.svg.png") "Africa" "Eastern Africa" - , Country "Guinea" "GN" "https://en.wikipedia.org/wiki/Guinea" 12771246 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ed/Flag_of_Guinea.svg/23px-Flag_of_Guinea.svg.png") "Africa" "Western Africa" - , Country "Rwanda" "RW" "https://en.wikipedia.org/wiki/Rwanda" 12626950 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Flag_of_Rwanda.svg/23px-Flag_of_Rwanda.svg.png") "Africa" "Eastern Africa" - , Country "Benin" "BJ" "https://en.wikipedia.org/wiki/Benin" 11801151 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/Flag_of_Benin.svg/23px-Flag_of_Benin.svg.png") "Africa" "Western Africa" - , Country "Tunisia" "TN" "https://en.wikipedia.org/wiki/Tunisia" 11694719 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/ce/Flag_of_Tunisia.svg/23px-Flag_of_Tunisia.svg.png") "Africa" "Northern Africa" - , Country "Belgium" "BE" "https://en.wikipedia.org/wiki/Belgium" 11539328 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Flag_of_Belgium_%28civil%29.svg/23px-Flag_of_Belgium_%28civil%29.svg.png") "Europe" "Western Europe" - , Country "Bolivia" "BO" "https://en.wikipedia.org/wiki/Bolivia" 11513100 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Bandera_de_Bolivia_%28Estado%29.svg/22px-Bandera_de_Bolivia_%28Estado%29.svg.png") "Americas" "South America" - , Country "Cuba" "CU" "https://en.wikipedia.org/wiki/Cuba" 11333483 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Flag_of_Cuba.svg/23px-Flag_of_Cuba.svg.png") "Americas" "Caribbean" - , Country "Haiti" "HT" "https://en.wikipedia.org/wiki/Haiti" 11263770 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Flag_of_Haiti.svg/23px-Flag_of_Haiti.svg.png") "Americas" "Caribbean" - , Country "South Sudan" "SS" "https://en.wikipedia.org/wiki/South_Sudan" 11062113 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Flag_of_South_Sudan.svg/23px-Flag_of_South_Sudan.svg.png") "Africa" "Eastern Africa" - , Country "Burundi" "BI" "https://en.wikipedia.org/wiki/Burundi" 10864245 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/50/Flag_of_Burundi.svg/23px-Flag_of_Burundi.svg.png") "Africa" "Eastern Africa" - , Country "Dominican Republic" "DO" "https://en.wikipedia.org/wiki/Dominican_Republic" 10738958 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/Flag_of_the_Dominican_Republic.svg/23px-Flag_of_the_Dominican_Republic.svg.png") "Americas" "Caribbean" - , Country "Czech Republic" "CZ" "https://en.wikipedia.org/wiki/Czech_Republic" 10689209 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/Flag_of_the_Czech_Republic.svg/23px-Flag_of_the_Czech_Republic.svg.png") "Europe" "Eastern Europe" - , Country "Greece" "GR" "https://en.wikipedia.org/wiki/Greece" 10473455 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Flag_of_Greece.svg/23px-Flag_of_Greece.svg.png") "Europe" "Southern Europe" - , Country "Portugal" "PT" "https://en.wikipedia.org/wiki/Portugal" 10226187 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Flag_of_Portugal.svg/23px-Flag_of_Portugal.svg.png") "Europe" "Southern Europe" - , Country "Jordan" "JO" "https://en.wikipedia.org/wiki/Jordan" 10101694 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/Flag_of_Jordan.svg/23px-Flag_of_Jordan.svg.png") "Asia" "Western Asia" - , Country "Azerbaijan" "AZ" "https://en.wikipedia.org/wiki/Azerbaijan" 10047718 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Flag_of_Azerbaijan.svg/23px-Flag_of_Azerbaijan.svg.png") "Asia" "Western Asia" - , Country "Sweden" "SE" "https://en.wikipedia.org/wiki/Sweden" 10036379 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/4/4c/Flag_of_Sweden.svg/23px-Flag_of_Sweden.svg.png") "Europe" "Northern Europe" - , Country "United Arab Emirates" "AE" "https://en.wikipedia.org/wiki/United_Arab_Emirates" 9770529 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/Flag_of_the_United_Arab_Emirates.svg/23px-Flag_of_the_United_Arab_Emirates.svg.png") "Asia" "Western Asia" - , Country "Honduras" "HN" "https://en.wikipedia.org/wiki/Honduras" 9746117 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Flag_of_Honduras.svg/23px-Flag_of_Honduras.svg.png") "Americas" "Central America" - , Country "Hungary" "HU" "https://en.wikipedia.org/wiki/Hungary" 9684679 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Flag_of_Hungary.svg/23px-Flag_of_Hungary.svg.png") "Europe" "Eastern Europe" - , Country "Belarus" "BY" "https://en.wikipedia.org/wiki/Belarus" 9452411 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Flag_of_Belarus.svg/23px-Flag_of_Belarus.svg.png") "Europe" "Eastern Europe" - , Country "Tajikistan" "TJ" "https://en.wikipedia.org/wiki/Tajikistan" 9321018 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Flag_of_Tajikistan.svg/23px-Flag_of_Tajikistan.svg.png") "Asia" "Central Asia" - , Country "Austria" "AT" "https://en.wikipedia.org/wiki/Austria" 8955102 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Flag_of_Austria.svg/23px-Flag_of_Austria.svg.png") "Europe" "Western Europe" - , Country "Papua New Guinea" "PG" "https://en.wikipedia.org/wiki/Papua_New_Guinea" 8776109 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e3/Flag_of_Papua_New_Guinea.svg/20px-Flag_of_Papua_New_Guinea.svg.png") "Oceania" "Melanesia" - , Country "Serbia" "RS" "https://en.wikipedia.org/wiki/Serbia" 8772235 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Flag_of_Serbia.svg/23px-Flag_of_Serbia.svg.png") "Europe" "Southern Europe" - , Country "Switzerland" "CH" "https://en.wikipedia.org/wiki/Switzerland" 8591365 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Flag_of_Switzerland.svg/16px-Flag_of_Switzerland.svg.png") "Europe" "Western Europe" - , Country "Israel" "IL" "https://en.wikipedia.org/wiki/Israel" 8519377 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Flag_of_Israel.svg/21px-Flag_of_Israel.svg.png") "Asia" "Western Asia" - , Country "Togo" "TG" "https://en.wikipedia.org/wiki/Togo" 8082366 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Flag_of_Togo.svg/23px-Flag_of_Togo.svg.png") "Africa" "Western Africa" - , Country "Sierra Leone" "SL" "https://en.wikipedia.org/wiki/Sierra_Leone" 7813215 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Flag_of_Sierra_Leone.svg/23px-Flag_of_Sierra_Leone.svg.png") "Africa" "Western Africa" - , Country "Hong Kong" "HK" "https://en.wikipedia.org/wiki/Hong_Kong" 7436154 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5b/Flag_of_Hong_Kong.svg/23px-Flag_of_Hong_Kong.svg.png") "Asia" "Eastern Asia" - , Country "Laos" "LA" "https://en.wikipedia.org/wiki/Laos" 7169455 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Flag_of_Laos.svg/23px-Flag_of_Laos.svg.png") "Asia" "South-eastern Asia" - , Country "Paraguay" "PY" "https://en.wikipedia.org/wiki/Paraguay" 7044636 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/Flag_of_Paraguay.svg/23px-Flag_of_Paraguay.svg.png") "Americas" "South America" - , Country "Bulgaria" "BG" "https://en.wikipedia.org/wiki/Bulgaria" 7000119 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Flag_of_Bulgaria.svg/23px-Flag_of_Bulgaria.svg.png") "Europe" "Eastern Europe" - , Country "Lebanon" "LB" "https://en.wikipedia.org/wiki/Lebanon" 6855713 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/Flag_of_Lebanon.svg/23px-Flag_of_Lebanon.svg.png") "Asia" "Western Asia" - , Country "Libya" "LY" "https://en.wikipedia.org/wiki/Libya" 6777452 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Flag_of_Libya.svg/23px-Flag_of_Libya.svg.png") "Africa" "Northern Africa" - , Country "Nicaragua" "NI" "https://en.wikipedia.org/wiki/Nicaragua" 6545502 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Flag_of_Nicaragua.svg/23px-Flag_of_Nicaragua.svg.png") "Americas" "Central America" - , Country "El Salvador" "SV" "https://en.wikipedia.org/wiki/El_Salvador" 6453553 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Flag_of_El_Salvador.svg/23px-Flag_of_El_Salvador.svg.png") "Americas" "Central America" - , Country "Kyrgyzstan" "KG" "https://en.wikipedia.org/wiki/Kyrgyzstan" 6415850 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Flag_of_Kyrgyzstan.svg/23px-Flag_of_Kyrgyzstan.svg.png") "Asia" "Central Asia" - , Country "Turkmenistan" "TM" "https://en.wikipedia.org/wiki/Turkmenistan" 5942089 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Flag_of_Turkmenistan.svg/23px-Flag_of_Turkmenistan.svg.png") "Asia" "Central Asia" - , Country "Singapore" "SG" "https://en.wikipedia.org/wiki/Singapore" 5804337 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Flag_of_Singapore.svg/23px-Flag_of_Singapore.svg.png") "Asia" "South-eastern Asia" - , Country "Denmark" "DK" "https://en.wikipedia.org/wiki/Denmark" 5771876 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Flag_of_Denmark.svg/20px-Flag_of_Denmark.svg.png") "Europe" "Northern Europe" - , Country "Finland" "FI" "https://en.wikipedia.org/wiki/Finland" 5532156 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Flag_of_Finland.svg/23px-Flag_of_Finland.svg.png") "Europe" "Northern Europe" - , Country "Slovakia" "SK" "https://en.wikipedia.org/wiki/Slovakia" 5457013 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Flag_of_Slovakia.svg/23px-Flag_of_Slovakia.svg.png") "Europe" "Eastern Europe" - , Country "Congo" "CG" "https://en.wikipedia.org/wiki/Republic_of_the_Congo" 5380508 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Flag_of_the_Republic_of_the_Congo.svg/23px-Flag_of_the_Republic_of_the_Congo.svg.png") "Africa" "Middle Africa" - , Country "Norway" "NO" "https://en.wikipedia.org/wiki/Norway" 5378857 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Flag_of_Norway.svg/21px-Flag_of_Norway.svg.png") "Europe" "Northern Europe" - , Country "Costa Rica" "CR" "https://en.wikipedia.org/wiki/Costa_Rica" 5047561 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f2/Flag_of_Costa_Rica.svg/23px-Flag_of_Costa_Rica.svg.png") "Americas" "Central America" - , Country "Palestine" "PS" "https://en.wikipedia.org/wiki/State_of_Palestine" 4981420 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Flag_of_Palestine.svg/23px-Flag_of_Palestine.svg.png") "Asia" "Western Asia" - , Country "Oman" "OM" "https://en.wikipedia.org/wiki/Oman" 4974986 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Flag_of_Oman.svg/23px-Flag_of_Oman.svg.png") "Asia" "Western Asia" - , Country "Liberia" "LR" "https://en.wikipedia.org/wiki/Liberia" 4937374 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Flag_of_Liberia.svg/23px-Flag_of_Liberia.svg.png") "Africa" "Western Africa" - , Country "Ireland" "IE" "https://en.wikipedia.org/wiki/Republic_of_Ireland" 4882495 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Flag_of_Ireland.svg/23px-Flag_of_Ireland.svg.png") "Europe" "Northern Europe" - , Country "New Zealand" "NZ" "https://en.wikipedia.org/wiki/New_Zealand" 4783063 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Flag_of_New_Zealand.svg/23px-Flag_of_New_Zealand.svg.png") "Oceania" "Australia and New Zealand" - , Country "Central African Republic" "CF" "https://en.wikipedia.org/wiki/Central_African_Republic" 4745185 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Flag_of_the_Central_African_Republic.svg/23px-Flag_of_the_Central_African_Republic.svg.png") "Africa" "Middle Africa" - , Country "Mauritania" "MR" "https://en.wikipedia.org/wiki/Mauritania" 4525696 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Flag_of_Mauritania.svg/23px-Flag_of_Mauritania.svg.png") "Africa" "Western Africa" - , Country "Panama" "PA" "https://en.wikipedia.org/wiki/Panama" 4246439 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Flag_of_Panama.svg/23px-Flag_of_Panama.svg.png") "Americas" "Central America" - , Country "Kuwait" "KW" "https://en.wikipedia.org/wiki/Kuwait" 4207083 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Flag_of_Kuwait.svg/23px-Flag_of_Kuwait.svg.png") "Asia" "Western Asia" - , Country "Croatia" "HR" "https://en.wikipedia.org/wiki/Croatia" 4130304 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Flag_of_Croatia.svg/23px-Flag_of_Croatia.svg.png") "Europe" "Southern Europe" - , Country "Moldova" "MD" "https://en.wikipedia.org/wiki/Moldova" 4043263 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/Flag_of_Moldova.svg/23px-Flag_of_Moldova.svg.png") "Europe" "Eastern Europe" - , Country "Georgia" "GE" "https://en.wikipedia.org/wiki/Georgia_(country)" 3996765 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Flag_of_Georgia.svg/23px-Flag_of_Georgia.svg.png") "Asia" "Western Asia" - , Country "Eritrea" "ER" "https://en.wikipedia.org/wiki/Eritrea" 3497117 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Flag_of_Eritrea.svg/23px-Flag_of_Eritrea.svg.png") "Africa" "Eastern Africa" - , Country "Uruguay" "UY" "https://en.wikipedia.org/wiki/Uruguay" 3461734 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Flag_of_Uruguay.svg/23px-Flag_of_Uruguay.svg.png") "Americas" "South America" - , Country "Bosnia and Herzegovina" "BA" "https://en.wikipedia.org/wiki/Bosnia_and_Herzegovina" 3301000 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Flag_of_Bosnia_and_Herzegovina.svg/23px-Flag_of_Bosnia_and_Herzegovina.svg.png") "Europe" "Southern Europe" - , Country "Mongolia" "MN" "https://en.wikipedia.org/wiki/Mongolia" 3225167 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Flag_of_Mongolia.svg/23px-Flag_of_Mongolia.svg.png") "Asia" "Eastern Asia" - , Country "Armenia" "AM" "https://en.wikipedia.org/wiki/Armenia" 2957731 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Flag_of_Armenia.svg/23px-Flag_of_Armenia.svg.png") "Asia" "Western Asia" - , Country "Jamaica" "JM" "https://en.wikipedia.org/wiki/Jamaica" 2948279 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/Flag_of_Jamaica.svg/23px-Flag_of_Jamaica.svg.png") "Americas" "Caribbean" - , Country "Puerto Rico" "PR" "https://en.wikipedia.org/wiki/Puerto_Rico" 2933408 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/Flag_of_Puerto_Rico.svg/23px-Flag_of_Puerto_Rico.svg.png") "Americas" "Caribbean" - , Country "Albania" "AL" "https://en.wikipedia.org/wiki/Albania" 2880917 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Flag_of_Albania.svg/21px-Flag_of_Albania.svg.png") "Europe" "Southern Europe" - , Country "Qatar" "QA" "https://en.wikipedia.org/wiki/Qatar" 2832067 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/65/Flag_of_Qatar.svg/23px-Flag_of_Qatar.svg.png") "Asia" "Western Asia" - , Country "Lithuania" "LT" "https://en.wikipedia.org/wiki/Lithuania" 2759627 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Flag_of_Lithuania.svg/23px-Flag_of_Lithuania.svg.png") "Europe" "Northern Europe" - , Country "Namibia" "NA" "https://en.wikipedia.org/wiki/Namibia" 2494530 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Flag_of_Namibia.svg/23px-Flag_of_Namibia.svg.png") "Africa" "Southern Africa" - , Country "Gambia" "GM" "https://en.wikipedia.org/wiki/The_Gambia" 2347706 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Flag_of_The_Gambia.svg/23px-Flag_of_The_Gambia.svg.png") "Africa" "Western Africa" - , Country "Botswana" "BW" "https://en.wikipedia.org/wiki/Botswana" 2303697 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Flag_of_Botswana.svg/23px-Flag_of_Botswana.svg.png") "Africa" "Southern Africa" - , Country "Gabon" "GA" "https://en.wikipedia.org/wiki/Gabon" 2172579 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Flag_of_Gabon.svg/20px-Flag_of_Gabon.svg.png") "Africa" "Middle Africa" - , Country "Lesotho" "LS" "https://en.wikipedia.org/wiki/Lesotho" 2125268 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Flag_of_Lesotho.svg/23px-Flag_of_Lesotho.svg.png") "Africa" "Southern Africa" - , Country "North Macedonia" "MK" "https://en.wikipedia.org/wiki/North_Macedonia" 2083459 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/79/Flag_of_North_Macedonia.svg/23px-Flag_of_North_Macedonia.svg.png") "Europe" "Southern Europe" - , Country "Slovenia" "SI" "https://en.wikipedia.org/wiki/Slovenia" 2078654 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/Flag_of_Slovenia.svg/23px-Flag_of_Slovenia.svg.png") "Europe" "Southern Europe" - , Country "Guinea-Bissau" "GW" "https://en.wikipedia.org/wiki/Guinea-Bissau" 1920922 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Guinea-Bissau.svg/23px-Flag_of_Guinea-Bissau.svg.png") "Africa" "Western Africa" - , Country "Latvia" "LV" "https://en.wikipedia.org/wiki/Latvia" 1906743 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Flag_of_Latvia.svg/23px-Flag_of_Latvia.svg.png") "Europe" "Northern Europe" - , Country "Bahrain" "BH" "https://en.wikipedia.org/wiki/Bahrain" 1641172 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Flag_of_Bahrain.svg/23px-Flag_of_Bahrain.svg.png") "Asia" "Western Asia" - , Country "Trinidad and Tobago" "TT" "https://en.wikipedia.org/wiki/Trinidad_and_Tobago" 1394973 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Flag_of_Trinidad_and_Tobago.svg/23px-Flag_of_Trinidad_and_Tobago.svg.png") "Americas" "Caribbean" - , Country "Equatorial Guinea" "GQ" "https://en.wikipedia.org/wiki/Equatorial_Guinea" 1355986 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Flag_of_Equatorial_Guinea.svg/23px-Flag_of_Equatorial_Guinea.svg.png") "Africa" "Middle Africa" - , Country "Estonia" "EE" "https://en.wikipedia.org/wiki/Estonia" 1325648 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/Flag_of_Estonia.svg/23px-Flag_of_Estonia.svg.png") "Europe" "Northern Europe" - , Country "East Timor" "TL" "https://en.wikipedia.org/wiki/East_Timor" 1293119 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Flag_of_East_Timor.svg/23px-Flag_of_East_Timor.svg.png") "Asia" "South-eastern Asia" - , Country "Mauritius" "MU" "https://en.wikipedia.org/wiki/Mauritius" 1198575 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Flag_of_Mauritius.svg/23px-Flag_of_Mauritius.svg.png") "Africa" "Eastern Africa" - , Country "Cyprus" "CY" "https://en.wikipedia.org/wiki/Cyprus" 1179551 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Flag_of_Cyprus.svg/23px-Flag_of_Cyprus.svg.png") "Asia" "Western Asia" - , Country "Eswatini" "SZ" "https://en.wikipedia.org/wiki/Eswatini" 1148130 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Flag_of_Eswatini.svg/23px-Flag_of_Eswatini.svg.png") "Africa" "Southern Africa" - , Country "Djibouti" "DJ" "https://en.wikipedia.org/wiki/Djibouti" 973560 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Flag_of_Djibouti.svg/23px-Flag_of_Djibouti.svg.png") "Africa" "Eastern Africa" - , Country "Fiji" "FJ" "https://en.wikipedia.org/wiki/Fiji" 889953 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Flag_of_Fiji.svg/23px-Flag_of_Fiji.svg.png") "Oceania" "Melanesia" - , Country "Réunion" "RE" "https://en.wikipedia.org/wiki/R%C3%A9union" 888927 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Proposed_flag_of_R%C3%A9union_%28VAR%29.svg/23px-Proposed_flag_of_R%C3%A9union_%28VAR%29.svg.png") "Africa" "Eastern Africa" - , Country "Comoros" "KM" "https://en.wikipedia.org/wiki/Comoros" 850886 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/94/Flag_of_the_Comoros.svg/23px-Flag_of_the_Comoros.svg.png") "Africa" "Eastern Africa" - , Country "Guyana" "GY" "https://en.wikipedia.org/wiki/Guyana" 782766 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/Flag_of_Guyana.svg/23px-Flag_of_Guyana.svg.png") "Americas" "South America" - , Country "Bhutan" "BT" "https://en.wikipedia.org/wiki/Bhutan" 763092 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Flag_of_Bhutan.svg/23px-Flag_of_Bhutan.svg.png") "Asia" "Southern Asia" - , Country "Solomon Islands" "SB" "https://en.wikipedia.org/wiki/Solomon_Islands" 669823 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Flag_of_the_Solomon_Islands.svg/23px-Flag_of_the_Solomon_Islands.svg.png") "Oceania" "Melanesia" - , Country "Macau" "MO" "https://en.wikipedia.org/wiki/Macau" 640445 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Flag_of_Macau.svg/23px-Flag_of_Macau.svg.png") "Asia" "Eastern Asia" - , Country "Montenegro" "ME" "https://en.wikipedia.org/wiki/Montenegro" 627987 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Flag_of_Montenegro.svg/23px-Flag_of_Montenegro.svg.png") "Europe" "Southern Europe" - , Country "Luxembourg" "LU" "https://en.wikipedia.org/wiki/Luxembourg" 615729 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Flag_of_Luxembourg.svg/23px-Flag_of_Luxembourg.svg.png") "Europe" "Western Europe" - , Country "Western Sahara" "EH" "https://en.wikipedia.org/wiki/Western_Sahara" 582463 Nothing "Africa" "Northern Africa" - , Country "Suriname" "SR" "https://en.wikipedia.org/wiki/Suriname" 581372 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Flag_of_Suriname.svg/23px-Flag_of_Suriname.svg.png") "Americas" "South America" - , Country "Cape Verde" "CV" "https://en.wikipedia.org/wiki/Cape_Verde" 549935 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Flag_of_Cape_Verde.svg/23px-Flag_of_Cape_Verde.svg.png") "Africa" "Western Africa" - , Country "Maldives" "MV" "https://en.wikipedia.org/wiki/Maldives" 530953 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Flag_of_Maldives.svg/23px-Flag_of_Maldives.svg.png") "Asia" "Southern Asia" - , Country "Guadeloupe" "GP" "https://en.wikipedia.org/wiki/Guadeloupe" 447905 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Unofficial_flag_of_Guadeloupe_%28local%29.svg/23px-Unofficial_flag_of_Guadeloupe_%28local%29.svg.png") "Americas" "Caribbean" - , Country "Malta" "MT" "https://en.wikipedia.org/wiki/Malta" 440372 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Flag_of_Malta.svg/23px-Flag_of_Malta.svg.png") "Europe" "Southern Europe" - , Country "Brunei" "BN" "https://en.wikipedia.org/wiki/Brunei" 433285 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Flag_of_Brunei.svg/23px-Flag_of_Brunei.svg.png") "Asia" "South-eastern Asia" - , Country "Belize" "BZ" "https://en.wikipedia.org/wiki/Belize" 390353 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Flag_of_Belize.svg/23px-Flag_of_Belize.svg.png") "Americas" "Central America" - , Country "Bahamas" "BS" "https://en.wikipedia.org/wiki/The_Bahamas" 389482 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Flag_of_the_Bahamas.svg/23px-Flag_of_the_Bahamas.svg.png") "Americas" "Caribbean" - , Country "Martinique" "MQ" "https://en.wikipedia.org/wiki/Martinique" 375554 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Snake_Flag_of_Martinique.svg/23px-Snake_Flag_of_Martinique.svg.png") "Americas" "Caribbean" - , Country "Iceland" "IS" "https://en.wikipedia.org/wiki/Iceland" 339031 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/ce/Flag_of_Iceland.svg/21px-Flag_of_Iceland.svg.png") "Europe" "Northern Europe" - , Country "Vanuatu" "VU" "https://en.wikipedia.org/wiki/Vanuatu" 299882 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Flag_of_Vanuatu.svg/23px-Flag_of_Vanuatu.svg.png") "Oceania" "Melanesia" - , Country "Barbados" "BB" "https://en.wikipedia.org/wiki/Barbados" 287025 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Flag_of_Barbados.svg/23px-Flag_of_Barbados.svg.png") "Americas" "Caribbean" - , Country "New Caledonia" "NC" "https://en.wikipedia.org/wiki/New_Caledonia" 282750 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Flag_of_FLNKS.svg/23px-Flag_of_FLNKS.svg.png") "Oceania" "Melanesia" - , Country "French Guiana" "GF" "https://en.wikipedia.org/wiki/French_Guiana" 282731 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Flag_of_French_Guiana.svg/23px-Flag_of_French_Guiana.svg.png") "Americas" "South America" - , Country "French Polynesia" "PF" "https://en.wikipedia.org/wiki/French_Polynesia" 279287 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/db/Flag_of_French_Polynesia.svg/23px-Flag_of_French_Polynesia.svg.png") "Oceania" "Polynesia" - , Country "Mayotte" "YT" "https://en.wikipedia.org/wiki/Mayotte" 266150 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/Flag_of_Mayotte_%28Local%29.svg/23px-Flag_of_Mayotte_%28Local%29.svg.png") "Africa" "Eastern Africa" - , Country "São Tomé and Príncipe" "ST" "https://en.wikipedia.org/wiki/S%C3%A3o_Tom%C3%A9_and_Pr%C3%ADncipe" 215056 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/Flag_of_Sao_Tome_and_Principe.svg/23px-Flag_of_Sao_Tome_and_Principe.svg.png") "Africa" "Middle Africa" - , Country "Samoa" "WS" "https://en.wikipedia.org/wiki/Samoa" 197097 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Flag_of_Samoa.svg/23px-Flag_of_Samoa.svg.png") "Oceania" "Polynesia" - , Country "Saint Lucia" "LC" "https://en.wikipedia.org/wiki/Saint_Lucia" 182790 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/Flag_of_Saint_Lucia.svg/23px-Flag_of_Saint_Lucia.svg.png") "Americas" "Caribbean" - , Country "Channel Islands" "GB" "https://en.wikipedia.org/wiki/Channel_Islands" 172259 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/a/ae/Flag_of_the_United_Kingdom.svg/23px-Flag_of_the_United_Kingdom.svg.png") "Europe" "Northern Europe" - , Country "Guam" "GU" "https://en.wikipedia.org/wiki/Guam" 167294 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/07/Flag_of_Guam.svg/23px-Flag_of_Guam.svg.png") "Oceania" "Micronesia" - , Country "Curaçao" "CW" "https://en.wikipedia.org/wiki/Cura%C3%A7ao" 163424 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Flag_of_Cura%C3%A7ao.svg/23px-Flag_of_Cura%C3%A7ao.svg.png") "Americas" "Caribbean" - , Country "Kiribati" "KI" "https://en.wikipedia.org/wiki/Kiribati" 117606 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Flag_of_Kiribati.svg/23px-Flag_of_Kiribati.svg.png") "Oceania" "Micronesia" - , Country "Micronesia" "FM" "https://en.wikipedia.org/wiki/Federated_States_of_Micronesia" 113815 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Flag_of_the_Federated_States_of_Micronesia.svg/23px-Flag_of_the_Federated_States_of_Micronesia.svg.png") "Oceania" "Micronesia" - , Country "Grenada" "GD" "https://en.wikipedia.org/wiki/Grenada" 112003 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Flag_of_Grenada.svg/23px-Flag_of_Grenada.svg.png") "Americas" "Caribbean" - , Country "Tonga" "TO" "https://en.wikipedia.org/wiki/Tonga" 110940 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Flag_of_Tonga.svg/23px-Flag_of_Tonga.svg.png") "Oceania" "Polynesia" - , Country "Saint Vincent and the Grenadines" "VC" "https://en.wikipedia.org/wiki/Saint_Vincent_and_the_Grenadines" 110589 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Flag_of_Saint_Vincent_and_the_Grenadines.svg/23px-Flag_of_Saint_Vincent_and_the_Grenadines.svg.png") "Americas" "Caribbean" - , Country "Aruba" "AW" "https://en.wikipedia.org/wiki/Aruba" 106314 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Flag_of_Aruba.svg/23px-Flag_of_Aruba.svg.png") "Americas" "Caribbean" - , Country "U.S. Virgin Islands" "VI" "https://en.wikipedia.org/wiki/United_States_Virgin_Islands" 104578 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Flag_of_the_United_States_Virgin_Islands.svg/23px-Flag_of_the_United_States_Virgin_Islands.svg.png") "Americas" "Caribbean" - , Country "Seychelles" "SC" "https://en.wikipedia.org/wiki/Seychelles" 97739 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Flag_of_Seychelles.svg/23px-Flag_of_Seychelles.svg.png") "Africa" "Eastern Africa" - , Country "Antigua and Barbuda" "AG" "https://en.wikipedia.org/wiki/Antigua_and_Barbuda" 97118 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Flag_of_Antigua_and_Barbuda.svg/23px-Flag_of_Antigua_and_Barbuda.svg.png") "Americas" "Caribbean" - , Country "Isle of Man" "IM" "https://en.wikipedia.org/wiki/Isle_of_Man" 84584 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Flag_of_the_Isle_of_Man.svg/23px-Flag_of_the_Isle_of_Man.svg.png") "Europe" "Northern Europe" - , Country "Andorra" "AD" "https://en.wikipedia.org/wiki/Andorra" 77142 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Flag_of_Andorra.svg/22px-Flag_of_Andorra.svg.png") "Europe" "Southern Europe" - , Country "Dominica" "DM" "https://en.wikipedia.org/wiki/Dominica" 71808 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c4/Flag_of_Dominica.svg/23px-Flag_of_Dominica.svg.png") "Americas" "Caribbean" - , Country "Cayman Islands" "KY" "https://en.wikipedia.org/wiki/Cayman_Islands" 64948 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Flag_of_the_Cayman_Islands.svg/23px-Flag_of_the_Cayman_Islands.svg.png") "Americas" "Caribbean" - , Country "Bermuda" "BM" "https://en.wikipedia.org/wiki/Bermuda" 62506 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Flag_of_Bermuda.svg/23px-Flag_of_Bermuda.svg.png") "Americas" "Northern America" - , Country "Marshall Islands" "MH" "https://en.wikipedia.org/wiki/Marshall_Islands" 58791 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Flag_of_the_Marshall_Islands.svg/23px-Flag_of_the_Marshall_Islands.svg.png") "Oceania" "Micronesia" - , Country "Greenland" "GL" "https://en.wikipedia.org/wiki/Greenland" 56672 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/Flag_of_Greenland.svg/23px-Flag_of_Greenland.svg.png") "Americas" "Northern America" - , Country "Northern Mariana Islands" "MP" "https://en.wikipedia.org/wiki/Northern_Mariana_Islands" 56188 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Flag_of_the_Northern_Mariana_Islands.svg/23px-Flag_of_the_Northern_Mariana_Islands.svg.png") "Oceania" "Micronesia" - , Country "American Samoa" "AS" "https://en.wikipedia.org/wiki/American_Samoa" 55312 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Flag_of_American_Samoa.svg/23px-Flag_of_American_Samoa.svg.png") "Oceania" "Polynesia" - , Country "Saint Kitts and Nevis" "KN" "https://en.wikipedia.org/wiki/Saint_Kitts_and_Nevis" 52823 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Flag_of_Saint_Kitts_and_Nevis.svg/23px-Flag_of_Saint_Kitts_and_Nevis.svg.png") "Americas" "Caribbean" - , Country "Faroe Islands" "FO" "https://en.wikipedia.org/wiki/Faroe_Islands" 48678 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Flag_of_the_Faroe_Islands.svg/21px-Flag_of_the_Faroe_Islands.svg.png") "Europe" "Northern Europe" - , Country "Sint Maarten" "SX" "https://en.wikipedia.org/wiki/Sint_Maarten" 42388 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Flag_of_Sint_Maarten.svg/23px-Flag_of_Sint_Maarten.svg.png") "Americas" "Caribbean" - , Country "Monaco" "MC" "https://en.wikipedia.org/wiki/Monaco" 38964 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Flag_of_Monaco.svg/19px-Flag_of_Monaco.svg.png") "Europe" "Western Europe" - , Country "Turks and Caicos Islands" "TC" "https://en.wikipedia.org/wiki/Turks_and_Caicos_Islands" 38191 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Flag_of_the_Turks_and_Caicos_Islands.svg/23px-Flag_of_the_Turks_and_Caicos_Islands.svg.png") "Americas" "Caribbean" - , Country "Liechtenstein" "LI" "https://en.wikipedia.org/wiki/Liechtenstein" 38019 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Flag_of_Liechtenstein.svg/23px-Flag_of_Liechtenstein.svg.png") "Europe" "Western Europe" - , Country "San Marino" "SM" "https://en.wikipedia.org/wiki/San_Marino" 33860 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Flag_of_San_Marino.svg/20px-Flag_of_San_Marino.svg.png") "Europe" "Southern Europe" - , Country "Gibraltar" "GI" "https://en.wikipedia.org/wiki/Gibraltar" 33701 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/Flag_of_Gibraltar.svg/23px-Flag_of_Gibraltar.svg.png") "Europe" "Southern Europe" - , Country "British Virgin Islands" "VG" "https://en.wikipedia.org/wiki/British_Virgin_Islands" 30030 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/Flag_of_the_British_Virgin_Islands.svg/23px-Flag_of_the_British_Virgin_Islands.svg.png") "Americas" "Caribbean" - , Country "Caribbean Netherlands" "BQ" "https://en.wikipedia.org/wiki/Caribbean_Netherlands" 25979 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Flag_of_the_Netherlands.svg/23px-Flag_of_the_Netherlands.svg.png") "Americas" "Caribbean" - , Country "Palau" "PW" "https://en.wikipedia.org/wiki/Palau" 18008 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Flag_of_Palau.svg/23px-Flag_of_Palau.svg.png") "Oceania" "Micronesia" - , Country "Cook Islands" "CK" "https://en.wikipedia.org/wiki/Cook_Islands" 17548 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Flag_of_the_Cook_Islands.svg/23px-Flag_of_the_Cook_Islands.svg.png") "Oceania" "Polynesia" - , Country "Anguilla" "AI" "https://en.wikipedia.org/wiki/Anguilla" 14869 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/Flag_of_Anguilla.svg/23px-Flag_of_Anguilla.svg.png") "Americas" "Caribbean" - , Country "Tuvalu" "TV" "https://en.wikipedia.org/wiki/Tuvalu" 11646 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Flag_of_Tuvalu.svg/23px-Flag_of_Tuvalu.svg.png") "Oceania" "Polynesia" - , Country "Wallis and Futuna" "WF" "https://en.wikipedia.org/wiki/Wallis_and_Futuna" 11432 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Flag_of_Wallis_and_Futuna.svg/23px-Flag_of_Wallis_and_Futuna.svg.png") "Oceania" "Polynesia" - , Country "Nauru" "NR" "https://en.wikipedia.org/wiki/Nauru" 10756 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Flag_of_Nauru.svg/23px-Flag_of_Nauru.svg.png") "Oceania" "Micronesia" - , Country "Saint Helena" "SH" "https://en.wikipedia.org/wiki/Saint_Helena,_Ascension_and_Tristan_da_Cunha" 6059 (Just "https://upload.wikimedia.org/wikipedia/en/thumb/a/ae/Flag_of_the_United_Kingdom.svg/23px-Flag_of_the_United_Kingdom.svg.png") "Africa" "Western Africa" - , Country "Saint Pierre and Miquelon" "PM" "https://en.wikipedia.org/wiki/Saint_Pierre_and_Miquelon" 5822 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Flag_of_Saint-Pierre_and_Miquelon.svg/23px-Flag_of_Saint-Pierre_and_Miquelon.svg.png") "Americas" "Northern America" - , Country "Montserrat" "MS" "https://en.wikipedia.org/wiki/Montserrat" 4989 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Flag_of_Montserrat.svg/23px-Flag_of_Montserrat.svg.png") "Americas" "Caribbean" - , Country "Falkland Islands" "FK" "https://en.wikipedia.org/wiki/Falkland_Islands" 3377 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Flag_of_the_Falkland_Islands.svg/23px-Flag_of_the_Falkland_Islands.svg.png") "Americas" "South America" - , Country "Niue" "NU" "https://en.wikipedia.org/wiki/Niue" 1615 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Flag_of_Niue.svg/23px-Flag_of_Niue.svg.png") "Oceania" "Polynesia" - , Country "Tokelau" "TK" "https://en.wikipedia.org/wiki/Tokelau" 1340 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Flag_of_Tokelau.svg/23px-Flag_of_Tokelau.svg.png") "Oceania" "Polynesia" - , Country "Vatican City" "VA" "https://en.wikipedia.org/wiki/Vatican_City" 799 (Just "https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Flag_of_the_Vatican_City.svg/16px-Flag_of_the_Vatican_City.svg.png") "Europe" "Southern Europe" - ] - -awsmCss :: Text -awsmCss = "\ - \@charset \"UTF-8\";\ - \/*!\ - \ * awsm.css v3.0.7 (https://igoradamenko.github.io/awsm.css/)\ - \ * Copyright 2015 Igor Adamenko (https://igoradamenko.com)\ - \ * Licensed under MIT (https://github.com/igoradamenko/awsm.css/blob/master/LICENSE.md)\ - \ */\ - \html{\ - \ font-family:system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, \"PT Sans\", \"Open Sans\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\ - \ font-size:100%;\ - \ line-height:1.4;\ - \ background:white;\ - \ color:black;\ - \ -webkit-overflow-scrolling:touch;\ - \}\ - \\ - \body{\ - \ margin:1.2em;\ - \ font-size:1rem;\ - \}\ - \@media (min-width: 20rem){\ - \ body{\ - \ font-size:calc(1rem + 0.00625 * (100vw - 20rem));\ - \ }\ - \}\ - \@media (min-width: 40rem){\ - \ body{\ - \ font-size:1.125rem;\ - \ }\ - \}\ - \body header,\ - \body main,\ - \body footer,\ - \body article{\ - \ position:relative;\ - \ max-width:40rem;\ - \ margin:0 auto;\ - \}\ - \body > header{\ - \ margin-bottom:3.5em;\ - \}\ - \body > header h1{\ - \ margin:0;\ - \ font-size:1.5em;\ - \}\ - \body > header p{\ - \ margin:0;\ - \ font-size:0.85em;\ - \}\ - \body > footer{\ - \ margin-top:6em;\ - \ padding-bottom:1.5em;\ - \ text-align:center;\ - \ font-size:0.8rem;\ - \ color:#aaaaaa;\ - \}\ - \\ - \nav{\ - \ margin:1em 0;\ - \}\ - \nav ul{\ - \ list-style:none;\ - \ margin:0;\ - \ padding:0;\ - \}\ - \nav li{\ - \ display:inline-block;\ - \ margin-right:1em;\ - \ margin-bottom:0.25em;\ - \}\ - \nav li:last-child{\ - \ margin-right:0;\ - \}\ - \nav a:visited{\ - \ color:#0064c1;\ - \}\ - \nav a:hover{\ - \ color:#f00000;\ - \}\ - \\ - \ul, ol{\ - \ margin-top:0;\ - \ padding-top:0;\ - \ padding-left:2.5em;\ - \}\ - \ul li + li, ol li + li{\ - \ margin-top:0.25em;\ - \}\ - \ul li > details, ol li > details{\ - \ margin:0;\ - \}\ - \\ - \p{\ - \ margin:1em 0;\ - \ -webkit-hyphens:auto;\ - \ -ms-hyphens:auto;\ - \ hyphens:auto;\ - \}\ - \p:first-child{\ - \ margin-top:0;\ - \}\ - \p:last-child{\ - \ margin-bottom:0;\ - \}\ - \p + ul, p + ol{\ - \ margin-top:-0.75em;\ - \}\ - \p img, p picture{\ - \ float:right;\ - \ margin-bottom:0.5em;\ - \ margin-left:0.5em;\ - \}\ - \p picture img{\ - \ float:none;\ - \ margin:0;\ - \}\ - \\ - \dd{\ - \ margin-bottom:1em;\ - \ margin-left:0;\ - \ padding-left:2.5em;\ - \}\ - \\ - \dt{\ - \ font-weight:700;\ - \}\ - \\ - \blockquote{\ - \ margin:0;\ - \ padding-left:2.5em;\ - \}\ - \\ - \aside{\ - \ margin:0.5em 0;\ - \ font-style:italic;\ - \ color:#aaaaaa;\ - \}\ - \@media (min-width: 65rem){\ - \ aside{\ - \ position:absolute;\ - \ right:-12.5rem;\ - \ width:9.375rem;\ - \ max-width:9.375rem;\ - \ margin:0;\ - \ padding-left:0.5em;\ - \ font-size:0.8em;\ - \ border-left:1px solid #f2f2f2;\ - \ }\ - \}\ - \aside:first-child{\ - \ margin-top:0;\ - \}\ - \aside:last-child{\ - \ margin-bottom:0;\ - \}\ - \\ - \section + section{\ - \ margin-top:2em;\ - \}\ - \\ - \h1, h2, h3, h4, h5, h6{\ - \ margin:1.25em 0 0;\ - \ line-height:1.2;\ - \}\ - \h1:hover > a[href^=\"#\"][id]:empty, h1:focus > a[href^=\"#\"][id]:empty, h2:hover > a[href^=\"#\"][id]:empty, h2:focus > a[href^=\"#\"][id]:empty, h3:hover > a[href^=\"#\"][id]:empty, h3:focus > a[href^=\"#\"][id]:empty, h4:hover > a[href^=\"#\"][id]:empty, h4:focus > a[href^=\"#\"][id]:empty, h5:hover > a[href^=\"#\"][id]:empty, h5:focus > a[href^=\"#\"][id]:empty, h6:hover > a[href^=\"#\"][id]:empty, h6:focus > a[href^=\"#\"][id]:empty{\ - \ opacity:1;\ - \}\ - \h1 + p, h1 + details, h2 + p, h2 + details, h3 + p, h3 + details, h4 + p, h4 + details, h5 + p, h5 + details, h6 + p, h6 + details{\ - \ margin-top:0.5em;\ - \}\ - \h1 > a[href^=\"#\"][id]:empty, h2 > a[href^=\"#\"][id]:empty, h3 > a[href^=\"#\"][id]:empty, h4 > a[href^=\"#\"][id]:empty, h5 > a[href^=\"#\"][id]:empty, h6 > a[href^=\"#\"][id]:empty{\ - \ position:absolute;\ - \ left:-0.65em;\ - \ opacity:0;\ - \ text-decoration:none;\ - \ font-weight:400;\ - \ line-height:1;\ - \ color:#aaaaaa;\ - \}\ - \@media (min-width: 40rem){\ - \ h1 > a[href^=\"#\"][id]:empty, h2 > a[href^=\"#\"][id]:empty, h3 > a[href^=\"#\"][id]:empty, h4 > a[href^=\"#\"][id]:empty, h5 > a[href^=\"#\"][id]:empty, h6 > a[href^=\"#\"][id]:empty{\ - \ left:-0.8em;\ - \ }\ - \}\ - \h1 > a[href^=\"#\"][id]:empty:target, h1 > a[href^=\"#\"][id]:empty:hover, h1 > a[href^=\"#\"][id]:empty:focus, h2 > a[href^=\"#\"][id]:empty:target, h2 > a[href^=\"#\"][id]:empty:hover, h2 > a[href^=\"#\"][id]:empty:focus, h3 > a[href^=\"#\"][id]:empty:target, h3 > a[href^=\"#\"][id]:empty:hover, h3 > a[href^=\"#\"][id]:empty:focus, h4 > a[href^=\"#\"][id]:empty:target, h4 > a[href^=\"#\"][id]:empty:hover, h4 > a[href^=\"#\"][id]:empty:focus, h5 > a[href^=\"#\"][id]:empty:target, h5 > a[href^=\"#\"][id]:empty:hover, h5 > a[href^=\"#\"][id]:empty:focus, h6 > a[href^=\"#\"][id]:empty:target, h6 > a[href^=\"#\"][id]:empty:hover, h6 > a[href^=\"#\"][id]:empty:focus{\ - \ opacity:1;\ - \ box-shadow:none;\ - \ color:black;\ - \}\ - \h1 > a[href^=\"#\"][id]:empty:target:focus, h2 > a[href^=\"#\"][id]:empty:target:focus, h3 > a[href^=\"#\"][id]:empty:target:focus, h4 > a[href^=\"#\"][id]:empty:target:focus, h5 > a[href^=\"#\"][id]:empty:target:focus, h6 > a[href^=\"#\"][id]:empty:target:focus{\ - \ outline:none;\ - \}\ - \h1 > a[href^=\"#\"][id]:empty::before, h2 > a[href^=\"#\"][id]:empty::before, h3 > a[href^=\"#\"][id]:empty::before, h4 > a[href^=\"#\"][id]:empty::before, h5 > a[href^=\"#\"][id]:empty::before, h6 > a[href^=\"#\"][id]:empty::before{\ - \ content:\"§ \";\ - \}\ - \\ - \h1{\ - \ font-size:2.5em;\ - \}\ - \\ - \h2{\ - \ font-size:1.75em;\ - \}\ - \\ - \h3{\ - \ font-size:1.25em;\ - \}\ - \\ - \h4{\ - \ font-size:1.15em;\ - \}\ - \\ - \h5{\ - \ font-size:1em;\ - \}\ - \\ - \h6{\ - \ margin-top:1em;\ - \ font-size:1em;\ - \ color:#aaaaaa;\ - \}\ - \\ - \article + article{\ - \ margin-top:4em;\ - \}\ - \article header p{\ - \ font-size:0.6em;\ - \ color:#aaaaaa;\ - \}\ - \article header p + h1, article header p + h2{\ - \ margin-top:-0.25em;\ - \}\ - \article header h1 + p, article header h2 + p{\ - \ margin-top:0.25em;\ - \}\ - \article header h1 a, article header h2 a{\ - \ color:black;\ - \}\ - \article header h1 a:visited, article header h2 a:visited{\ - \ color:#aaaaaa;\ - \}\ - \article header h1 a:visited:hover, article header h2 a:visited:hover{\ - \ color:#f00000;\ - \}\ - \article > footer{\ - \ margin-top:1.5em;\ - \ font-size:0.85em;\ - \}\ - \\ - \a{\ - \ color:#0064c1;\ - \}\ - \a:visited{\ - \ color:#8d39d0;\ - \}\ - \a:hover, a:active{\ - \ outline-width:0;\ - \}\ - \a:hover{\ - \ color:#f00000;\ - \}\ - \a abbr{\ - \ font-size:1em;\ - \}\ - \\ - \abbr{\ - \ margin-right:-0.075em;\ - \ text-decoration:none;\ - \ -webkit-hyphens:none;\ - \ -ms-hyphens:none;\ - \ hyphens:none;\ - \ letter-spacing:0.075em;\ - \ font-size:0.9em;\ - \}\ - \\ - \img, picture{\ - \ display:block;\ - \ max-width:100%;\ - \ margin:0 auto;\ - \}\ - \\ - \audio, video{\ - \ width:100%;\ - \ max-width:100%;\ - \}\ - \\ - \figure{\ - \ margin:1em 0 0.5em;\ - \ padding:0;\ - \}\ - \figure + p{\ - \ margin-top:0.5em;\ - \}\ - \figure figcaption{\ - \ opacity:0.65;\ - \ font-size:0.85em;\ - \}\ - \\ - \table{\ - \ display:inline-block;\ - \ border-spacing:0;\ - \ border-collapse:collapse;\ - \ overflow-x:auto;\ - \ max-width:100%;\ - \ text-align:left;\ - \ vertical-align:top;\ - \ background:linear-gradient(rgba(0, 0, 0, 0.15) 0%, rgba(0, 0, 0, 0.15) 100%) 0 0, linear-gradient(rgba(0, 0, 0, 0.15) 0%, rgba(0, 0, 0, 0.15) 100%) 100% 0;\ - \ background-attachment:scroll, scroll;\ - \ background-size:1px 100%, 1px 100%;\ - \ background-repeat:no-repeat, no-repeat;\ - \}\ - \table caption{\ - \ font-size:0.9em;\ - \ background:white;\ - \}\ - \table td, table th{\ - \ padding:0.35em 0.75em;\ - \ vertical-align:top;\ - \ font-size:0.9em;\ - \ border:1px solid #f2f2f2;\ - \ border-top:0;\ - \ border-left:0;\ - \}\ - \table td:first-child, table th:first-child{\ - \ padding-left:0;\ - \ background-image:linear-gradient(to right, white 50%, rgba(255, 255, 255, 0) 100%);\ - \ background-size:2px 100%;\ - \ background-repeat:no-repeat;\ - \}\ - \table td:last-child, table th:last-child{\ - \ padding-right:0;\ - \ border-right:0;\ - \ background-image:linear-gradient(to left, white 50%, rgba(255, 255, 255, 0) 100%);\ - \ background-position:100% 0;\ - \ background-size:2px 100%;\ - \ background-repeat:no-repeat;\ - \}\ - \table td:only-child, table th:only-child{\ - \ background-image:linear-gradient(to right, white 50%, rgba(255, 255, 255, 0) 100%), linear-gradient(to left, white 50%, rgba(255, 255, 255, 0) 100%);\ - \ background-position:0 0, 100% 0;\ - \ background-size:2px 100%, 2px 100%;\ - \ background-repeat:no-repeat, no-repeat;\ - \}\ - \table th{\ - \ line-height:1.2;\ - \}\ - \\ - \form{\ - \ margin-right:auto;\ - \ margin-left:auto;\ - \}\ - \@media (min-width: 40rem){\ - \ form{\ - \ max-width:80%;\ - \ }\ - \}\ - \form select, form label{\ - \ display:block;\ - \}\ - \form label:not(:first-child){\ - \ margin-top:1em;\ - \}\ - \form p label{\ - \ display:inline;\ - \}\ - \form p label + label{\ - \ margin-left:1em;\ - \}\ - \form legend:first-child + label{\ - \ margin-top:0;\ - \}\ - \form select, form input[type], form textarea{\ - \ margin-bottom:1em;\ - \}\ - \form input[type=checkbox], form input[type=radio]{\ - \ margin-bottom:0;\ - \}\ - \\ - \fieldset{\ - \ margin:0;\ - \ padding:0.5em 1em;\ - \ border:1px solid #aaaaaa;\ - \}\ - \\ - \legend{\ - \ color:#aaaaaa;\ - \}\ - \\ - \button{\ - \ outline:none;\ - \ box-sizing:border-box;\ - \ height:2em;\ - \ margin:0;\ - \ padding:calc(.25em - 1px) 0.5em;\ - \ font-family:inherit;\ - \ font-size:1em;\ - \ border:1px solid #aaaaaa;\ - \ border-radius:2px;\ - \ background:white;\ - \ color:black;\ - \ display:inline-block;\ - \ width:auto;\ - \ background:#f2f2f2;\ - \ color:black;\ - \ cursor:pointer;\ - \}\ - \button:focus{\ - \ border:1px solid black;\ - \}\ - \button:not([disabled]):hover{\ - \ border:1px solid black;\ - \}\ - \button:active{\ - \ background-color:#aaaaaa;\ - \}\ - \button[disabled]{\ - \ color:#aaaaaa;\ - \ cursor:not-allowed;\ - \}\ - \\ - \select{\ - \ outline:none;\ - \ box-sizing:border-box;\ - \ height:2em;\ - \ margin:0;\ - \ padding:calc(.25em - 1px) 0.5em;\ - \ font-family:inherit;\ - \ font-size:1em;\ - \ border:1px solid #aaaaaa;\ - \ border-radius:2px;\ - \ background:white;\ - \ color:black;\ - \ display:inline-block;\ - \ width:auto;\ - \ background:#f2f2f2;\ - \ color:black;\ - \ cursor:pointer;\ - \ padding-right:1.2em;\ - \ background-position:top 55% right 0.35em;\ - \ background-size:0.5em;\ - \ background-repeat:no-repeat;\ - \ -webkit-appearance:none;\ - \ -moz-appearance:none;\ - \ appearance:none;\ - \ background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3Cpath fill='rgb(170, 170, 170)' fill-rule='nonzero' d='M1.5 2L3 0H0z'/%3E%3C/svg%3E\");\ - \}\ - \select:focus{\ - \ border:1px solid black;\ - \}\ - \select:not([disabled]):hover{\ - \ border:1px solid black;\ - \}\ - \select:active{\ - \ background-color:#aaaaaa;\ - \}\ - \select[disabled]{\ - \ color:#aaaaaa;\ - \ cursor:not-allowed;\ - \}\ - \select:not([disabled]):focus, select:not([disabled]):hover{\ - \ background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3Cpath fill='rgb(0, 0, 0)' fill-rule='nonzero' d='M1.5 2L3 0H0z'/%3E%3C/svg%3E\");\ - \}\ - \\ - \input[type=text], input[type=password], input[type^=date], input[type=email], input[type=number], input[type=search], input[type=tel], input[type=time], input[type=month], input[type=week], input[type=url]{\ - \ outline:none;\ - \ box-sizing:border-box;\ - \ height:2em;\ - \ margin:0;\ - \ padding:calc(.25em - 1px) 0.5em;\ - \ font-family:inherit;\ - \ font-size:1em;\ - \ border:1px solid #aaaaaa;\ - \ border-radius:2px;\ - \ background:white;\ - \ color:black;\ - \ display:block;\ - \ width:100%;\ - \ line-height:calc(2em - 1px * 2 - (.25em - 1px) * 2);\ - \ -webkit-appearance:none;\ - \ -moz-appearance:none;\ - \ appearance:none;\ - \}\ - \input[type=text]:focus, input[type=password]:focus, input[type^=date]:focus, input[type=email]:focus, input[type=number]:focus, input[type=search]:focus, input[type=tel]:focus, input[type=time]:focus, input[type=month]:focus, input[type=week]:focus, input[type=url]:focus{\ - \ border:1px solid black;\ - \}\ - \input[type=text]::-moz-placeholder, input[type=password]::-moz-placeholder, input[type^=date]::-moz-placeholder, input[type=email]::-moz-placeholder, input[type=number]::-moz-placeholder, input[type=search]::-moz-placeholder, input[type=tel]::-moz-placeholder, input[type=time]::-moz-placeholder, input[type=month]::-moz-placeholder, input[type=week]::-moz-placeholder, input[type=url]::-moz-placeholder{\ - \ color:#aaaaaa;\ - \}\ - \input[type=text]::-webkit-input-placeholder, input[type=password]::-webkit-input-placeholder, input[type^=date]::-webkit-input-placeholder, input[type=email]::-webkit-input-placeholder, input[type=number]::-webkit-input-placeholder, input[type=search]::-webkit-input-placeholder, input[type=tel]::-webkit-input-placeholder, input[type=time]::-webkit-input-placeholder, input[type=month]::-webkit-input-placeholder, input[type=week]::-webkit-input-placeholder, input[type=url]::-webkit-input-placeholder{\ - \ color:#aaaaaa;\ - \}\ - \input[type=text]:-ms-input-placeholder, input[type=password]:-ms-input-placeholder, input[type^=date]:-ms-input-placeholder, input[type=email]:-ms-input-placeholder, input[type=number]:-ms-input-placeholder, input[type=search]:-ms-input-placeholder, input[type=tel]:-ms-input-placeholder, input[type=time]:-ms-input-placeholder, input[type=month]:-ms-input-placeholder, input[type=week]:-ms-input-placeholder, input[type=url]:-ms-input-placeholder{\ - \ color:#aaaaaa;\ - \}\ - \input[type=submit], input[type=button], input[type=reset]{\ - \ outline:none;\ - \ box-sizing:border-box;\ - \ height:2em;\ - \ margin:0;\ - \ padding:calc(.25em - 1px) 0.5em;\ - \ font-family:inherit;\ - \ font-size:1em;\ - \ border:1px solid #aaaaaa;\ - \ border-radius:2px;\ - \ background:white;\ - \ color:black;\ - \ display:inline-block;\ - \ width:auto;\ - \ background:#f2f2f2;\ - \ color:black;\ - \ cursor:pointer;\ - \ -webkit-appearance:none;\ - \ -moz-appearance:none;\ - \ appearance:none;\ - \}\ - \input[type=submit]:focus, input[type=button]:focus, input[type=reset]:focus{\ - \ border:1px solid black;\ - \}\ - \input[type=submit]:not([disabled]):hover, input[type=button]:not([disabled]):hover, input[type=reset]:not([disabled]):hover{\ - \ border:1px solid black;\ - \}\ - \input[type=submit]:active, input[type=button]:active, input[type=reset]:active{\ - \ background-color:#aaaaaa;\ - \}\ - \input[type=submit][disabled], input[type=button][disabled], input[type=reset][disabled]{\ - \ color:#aaaaaa;\ - \ cursor:not-allowed;\ - \}\ - \input[type=color]{\ - \ outline:none;\ - \ box-sizing:border-box;\ - \ height:2em;\ - \ margin:0;\ - \ padding:calc(.25em - 1px) 0.5em;\ - \ font-family:inherit;\ - \ font-size:1em;\ - \ border:1px solid #aaaaaa;\ - \ border-radius:2px;\ - \ background:white;\ - \ color:black;\ - \ display:block;\ - \ width:100%;\ - \ line-height:calc(2em - 1px * 2 - (.25em - 1px) * 2);\ - \ -webkit-appearance:none;\ - \ -moz-appearance:none;\ - \ appearance:none;\ - \ width:6em;\ - \}\ - \input[type=color]:focus{\ - \ border:1px solid black;\ - \}\ - \input[type=color]::-moz-placeholder{\ - \ color:#aaaaaa;\ - \}\ - \input[type=color]::-webkit-input-placeholder{\ - \ color:#aaaaaa;\ - \}\ - \input[type=color]:-ms-input-placeholder{\ - \ color:#aaaaaa;\ - \}\ - \input[type=color]:hover{\ - \ border:1px solid black;\ - \}\ - \input[type=file]{\ - \ outline:none;\ - \ box-sizing:border-box;\ - \ height:2em;\ - \ margin:0;\ - \ padding:calc(.25em - 1px) 0.5em;\ - \ font-family:inherit;\ - \ font-size:1em;\ - \ border:1px solid #aaaaaa;\ - \ border-radius:2px;\ - \ background:white;\ - \ color:black;\ - \ display:inline-block;\ - \ width:auto;\ - \ background:#f2f2f2;\ - \ color:black;\ - \ cursor:pointer;\ - \ display:block;\ - \ width:100%;\ - \ height:auto;\ - \ padding:0.75em 0.5em;\ - \ font-size:12px;\ - \ line-height:1;\ - \}\ - \input[type=file]:focus{\ - \ border:1px solid black;\ - \}\ - \input[type=file]:not([disabled]):hover{\ - \ border:1px solid black;\ - \}\ - \input[type=file]:active{\ - \ background-color:#aaaaaa;\ - \}\ - \input[type=file][disabled]{\ - \ color:#aaaaaa;\ - \ cursor:not-allowed;\ - \}\ - \input[type=checkbox], input[type=radio]{\ - \ margin:-0.2em 0.75em 0 0;\ - \ vertical-align:middle;\ - \}\ - \\ - \textarea{\ - \ outline:none;\ - \ box-sizing:border-box;\ - \ height:2em;\ - \ margin:0;\ - \ padding:calc(.25em - 1px) 0.5em;\ - \ font-family:inherit;\ - \ font-size:1em;\ - \ border:1px solid #aaaaaa;\ - \ border-radius:2px;\ - \ background:white;\ - \ color:black;\ - \ display:block;\ - \ width:100%;\ - \ line-height:calc(2em - 1px * 2 - (.25em - 1px) * 2);\ - \ -webkit-appearance:none;\ - \ -moz-appearance:none;\ - \ appearance:none;\ - \ height:4.5em;\ - \ resize:vertical;\ - \ padding-top:0.5em;\ - \ padding-bottom:0.5em;\ - \}\ - \textarea:focus{\ - \ border:1px solid black;\ - \}\ - \textarea::-moz-placeholder{\ - \ color:#aaaaaa;\ - \}\ - \textarea::-webkit-input-placeholder{\ - \ color:#aaaaaa;\ - \}\ - \textarea:-ms-input-placeholder{\ - \ color:#aaaaaa;\ - \}\ - \\ - \output{\ - \ display:block;\ - \}\ - \\ - \code, kbd, var, samp{\ - \ font-family:Consolas, \"Lucida Console\", Monaco, monospace;\ - \ font-style:normal;\ - \}\ - \\ - \pre{\ - \ overflow-x:auto;\ - \ font-size:0.8em;\ - \ background:linear-gradient(rgba(0, 0, 0, 0.15) 0%, rgba(0, 0, 0, 0.15) 100%) 0 0, linear-gradient(rgba(0, 0, 0, 0.15) 0%, rgba(0, 0, 0, 0.15) 100%) 100% 0;\ - \ background-attachment:scroll, scroll;\ - \ background-size:1px 100%, 1px 100%;\ - \ background-repeat:no-repeat, no-repeat;\ - \}\ - \pre > code{\ - \ display:inline-block;\ - \ overflow-x:visible;\ - \ box-sizing:border-box;\ - \ min-width:100%;\ - \ border-right:3px solid white;\ - \ border-left:1px solid white;\ - \}\ - \\ - \hr{\ - \ height:1px;\ - \ margin:2em 0;\ - \ border:0;\ - \ background:#f2f2f2;\ - \}\ - \\ - \details{\ - \ margin:1em 0;\ - \}\ - \details[open]{\ - \ padding-bottom:0.5em;\ - \ border-bottom:1px solid #f2f2f2;\ - \}\ - \\ - \summary{\ - \ display:inline-block;\ - \ font-weight:700;\ - \ border-bottom:1px dashed;\ - \ cursor:pointer;\ - \}\ - \summary::-webkit-details-marker{\ - \ display:none;\ - \}\ - \\ - \noscript{\ - \ color:#d00000;\ - \}\ - \\ - \::selection{\ - \ background:rgba(0, 100, 193, 0.25);\ - \}" - -countriesMap :: Text -countriesMap = "\ - \\ - \\ - \ World Map\ - \ \ - \\ - \ \ - \ Sudan\ - \ \ - \ \ - \ South Sudan\ - \ \ - \ \ - \ Georgia\ - \ \ - \ \ - \ Abkhazia\ - \ \ - \ \ - \ \ - \ \ - \ South Ossetia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Peru\ - \ \ - \ \ - \ Burkina Faso\ - \ \ - \ \ - \ Libya\ - \ \ - \ \ - \ Belarus\ - \ \ - \ \ - \ Pakistan\ - \ \ - \ \ - \ Azad Jammu and Kashmir\ - \ \ - \ \ - \ \ - \ Indonesia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Yemen\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Madagascar\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Bolivia, Plurinational State of\ - \ \ - \ \ - \ \ - \ \ - \ Serbia\ - \ \ - \ \ - \ Kosovo\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Cote d'Ivoire\ - \ \ - \ \ - \ Algeria\ - \ \ - \ \ - \ Switzerland\ - \ \ - \ \ - \ Cameroon\ - \ \ - \ \ - \ North Macedonia, Republic of\ - \ \ - \ \ - \ Botswana\ - \ \ - \ \ - \ Kenya\ - \ \ - \ \ - \ Jordan\ - \ \ - \ \ - \ Mexico\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ United Arab Emirates\ - \ \ - \ \ - \ \ - \ \ - \ Belize\ - \ \ - \ \ - \ \ - \ \ - \ Brazil\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Sierra Leone\ - \ \ - \ \ - \ \ - \ \ - \ Mali\ - \ \ - \ \ - \ Congo, Democratic Republic of the\ - \ \ - \ \ - \ Italy\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Somalia\ - \ \ - \ \ - \ Somaliland\ - \ \ - \ \ - \ \ - \ Afghanistan\ - \ \ - \ \ - \ Bangladesh\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Dominican Republic\ - \ \ - \ \ - \ \ - \ \ - \ Guinea-Bissau\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Ghana\ - \ \ - \ \ - \ Austria\ - \ \ - \ \ - \ Sweden\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Turkey\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Uganda\ - \ \ - \ \ - \ Mozambique\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Japan\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ New Zealand\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Cuba\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Venezuela, Bolivarian Republic of\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Portugal\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Colombia\ - \ \ - \ \ - \ Mauritania\ - \ \ - \ \ - \ \ - \ \ - \ Angola\ - \ \ - \ \ - \ \ - \ \ - \ Germany\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Thailand\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Papua New Guinea\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Iraq\ - \ \ - \ \ - \ Croatia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Greenland\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Niger\ - \ \ - \ \ - \ Denmark\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Latvia\ - \ \ - \ \ - \ Romania\ - \ \ - \ \ - \ Zambia\ - \ \ - \ \ - \ Myanmar\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Ethiopia\ - \ \ - \ \ - \ Guatemala\ - \ \ - \ \ - \ Suriname\ - \ \ - \ \ - \ Czech Republic\ - \ \ - \ \ - \ Chad\ - \ \ - \ \ - \ Albania\ - \ \ - \ \ - \ Finland\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Syrian Arab Republic\ - \ \ - \ \ - \ Kyrgyzstan\ - \ \ - \ \ - \ Solomon Islands\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Oman\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Panama\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Argentina\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ United Kingdom\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Costa Rica\ - \ \ - \ \ - \ \ - \ \ - \ Paraguay\ - \ \ - \ \ - \ Guinea\ - \ \ - \ \ - \ \ - \ \ - \ Ireland\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Nigeria\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Tunisia\ - \ \ - \ \ - \ \ - \ \ - \ Poland\ - \ \ - \ \ - \ Namibia\ - \ \ - \ \ - \ South Africa\ - \ \ - \ \ - \ Egypt\ - \ \ - \ \ - \ Tanzania, United Republic of\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Saudi Arabia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Vietnam, Socialist Republic of\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Russian Federation\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Southern Kuril Islands\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Crimea\ - \ \ - \ \ - \ \ - \ Haiti\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Bosnia and Herzegovina\ - \ \ - \ \ - \ India\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Canada\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ El Salvador\ - \ \ - \ \ - \ Guyana\ - \ \ - \ \ - \ Belgium\ - \ \ - \ \ - \ Equatorial Guinea\ - \ \ - \ \ - \ \ - \ \ - \ Lesotho\ - \ \ - \ \ - \ Bulgaria\ - \ \ - \ \ - \ Burundi\ - \ \ - \ \ - \ Djibouti\ - \ \ - \ \ - \ Azerbaijan\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Artsakh, Republic of\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Iran, Islamic Republic of\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Malaysia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Philippines\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Uruguay\ - \ \ - \ \ - \ Congo, Republic of the\ - \ \ - \ \ - \ Estonia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Rwanda\ - \ \ - \ \ - \ Armenia\ - \ \ - \ \ - \ Senegal\ - \ \ - \ \ - \ Togo\ - \ \ - \ \ - \ Spain\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Gabon\ - \ \ - \ \ - \ \ - \ \ - \ Hungary\ - \ \ - \ \ - \ Malawi\ - \ \ - \ \ - \ Tajikistan\ - \ \ - \ \ - \ Cambodia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Korea, Republic of\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Honduras\ - \ \ - \ \ - \ \ - \ \ - \ Iceland\ - \ \ - \ \ - \ Nicaragua\ - \ \ - \ \ - \ Chile\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Morocco\ - \ \ - \ \ - \ \ - \ Western Sahara\ - \ \ - \ \ - \ Sahrawi Arab Democratic Republic\ - \ \ - \ \ - \ \ - \ \ - \ Liberia\ - \ \ - \ \ - \ Central African Republic\ - \ \ - \ \ - \ Slovakia\ - \ \ - \ \ - \ Lithuania\ - \ \ - \ \ - \ Zimbabwe\ - \ \ - \ \ - \ Sri Lanka\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Israel\ - \ \ - \ \ - \ \ - \ State of Palestine\ - \ \ - \ \ - \ Gaza Strip\ - \ \ - \ \ - \ West Bank\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Lao People's Democratic Republic\ - \ \ - \ \ - \ Korea, Democratic People's Republic of\ - \ \ - \ \ - \ Greece\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Turkmenistan\ - \ \ - \ \ - \ Ecuador\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Benin\ - \ \ - \ \ - \ Slovenia\ - \ \ - \ \ - \ Norway\ - \ \ - \ Svalbard\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Moldova, Republic of\ - \ \ - \ \ - \ Transnistria\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Ukraine\ - \ \ - \ \ - \ Donetsk People's Republic\ - \ \ - \ \ - \ \ - \ \ - \ Luhansk People's Republic\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Nepal\ - \ \ - \ \ - \ Eritrea\ - \ \ - \ \ - \ \ - \ \ - \ United States of America\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Kazakhstan\ - \ \ - \ \ - \ \ - \ \ - \ French Southern Territories\ - \ \ - \ \ - \ \ - \ \ - \ Uzbekistan\ - \ \ - \ \ - \ Mongolia\ - \ \ - \ \ - \ Bhutan\ - \ \ - \ \ - \ Antarctica\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \\ - \\ - \\ - \\ - \ \ - \ Australia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Christmas Island\ - \ \ - \ \ - \ \ - \ \ - \ Cocos (Keeling) Islands\ - \ \ - \ \ - \ \ - \ \ - \ Heard Island and McDonald Islands\ - \ \ - \ \ - \ \ - \ \ - \ Norfolk Island\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ China\ - \ \ - \ China, People's Republic of\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Hong Kong\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Macao\ - \ \ - \ \ - \ \ - \ \ - \ Taiwan\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ France\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ French Guiana\ - \ \ - \ \ - \ Guadeloupe\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Martinique\ - \ \ - \ \ - \ \ - \ \ - \ Reunion\ - \ \ - \ \ - \ \ - \ \ - \ Mayotte\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Netherlands\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Bonaire, Sint Eustatius and Saba\ - \ \ - \ \ - \ \ - \ \ - \\ - \\ - \\ - \\ - \ \ - \ Lebanon\ - \ \ - \ \ - \ \ - \ \ - \ Montenegro\ - \ \ - \ \ - \ \ - \ \ - \ Eswatini\ - \ \ - \ \ - \ \ - \ \ - \ New Caledonia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Fiji\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Kuwait\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Timor-Leste\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Bahamas\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Vanuatu\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Falkland Islands (Islas Malvinas)\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ South Georgia and the South Sandwich Islands\ - \ \ - \ \ - \ \ - \ \ - \ Gambia\ - \ \ - \ \ - \ \ - \ \ - \ Qatar\ - \ \ - \ \ - \ \ - \ \ - \ Jamaica\ - \ \ - \ \ - \ \ - \ \ - \ Cyprus\ - \ \ - \ \ - \ Northern Cyprus\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Puerto Rico\ - \ \ - \ \ - \ \ - \ \ - \ Brunei\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Trinidad and Tobago\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Cape Verde\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ French Polynesia\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Samoa\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Luxembourg\ - \ \ - \ \ - \ \ - \ \ - \ Comoros\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Mauritius\ - \ \ - \ \ - \ \ - \ \ - \ Faroe Islands\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Sao Tome and Principe\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Virgin Islands, U.S.\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Curaçao\ - \ \ - \ \ - \ \ - \ \ - \ Sint Maarten (Dutch Part)\ - \ \ - \ \ - \ \ - \ \ - \ Dominica\ - \ \ - \ \ - \ \ - \ \ - \ Tonga\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Kiribati\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Micronesia, Federated States of\ - \ \ - \ \ - \ \ - \ \ - \ Bahrain\ - \ \ - \ \ - \ \ - \ \ - \ Andorra\ - \ \ - \ \ - \ \ - \ \ - \ Northern Mariana Islands\ - \ \ - \ \ - \ \ - \ \ - \ Palau\ - \ \ - \ \ - \ \ - \ \ - \ Seychelles, Republic of\ - \ \ - \ \ - \ \ - \ \ - \ British Indian Ocean Territory\ - \ \ - \ \ - \ \ - \ \ - \ Antigua and Barbuda\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Barbados\ - \ \ - \ \ - \ \ - \ \ - \ Turks and Caicos Islands\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Saint Vincent and the Grenadines\ - \ \ - \ \ - \ \ - \ \ - \ Saint Lucia\ - \ \ - \ \ - \ \ - \ \ - \ Grenada\ - \ \ - \ \ - \ \ - \ \ - \ Malta\ - \ \ - \ \ - \ \ - \ \ - \ Maldives, Republic of\ - \ \ - \ \ - \ \ - \ \ - \ Cayman Islands\ - \ \ - \ \ - \ \ - \ \ - \ Saint Kitts and Nevis\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Montserrat\ - \ \ - \ \ - \ \ - \ \ - \ Saint Barthélemy\ - \ \ - \ \ - \ \ - \ \ - \ Niue\ - \ \ - \ \ - \ \ - \ \ - \ Saint Pierre and Miquelon\ - \ \ - \ \ - \ \ - \ \ - \ Cook Islands\ - \ \ - \ \ - \ \ - \ \ - \ Wallis and Futuna\ - \ \ - \ \ - \ \ - \ \ - \ American Samoa\ - \ \ - \ \ - \ \ - \ \ - \ Marshall Islands, Republic of the\ - \ \ - \ \ - \ \ - \ \ - \ Aruba\ - \ \ - \ \ - \ \ - \ \ - \ Liechtenstein\ - \ \ - \ \ - \ \ - \ \ - \ Virgin Islands, British\ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ \ - \ Saint Helena, Ascension and Tristan da Cunha\ - \ \ - \ \ - \ \ - \ \ - \ Jersey\ - \ \ - \ \ - \ \ - \ \ - \ Anguilla\ - \ \ - \ \ - \ \ - \ \ - \ Saint Martin (French Part)\ - \ \ - \ \ - \ \ - \ \ - \ Guernsey\ - \ \ - \ \ - \ \ - \ \ - \ San Marino\ - \ \ - \ \ - \ \ - \ \ - \ Bermuda\ - \ \ - \ \ - \ \ - \ \ - \ Tuvalu\ - \ \ - \ \ - \ \ - \ \ - \ Nauru\ - \ \ - \ \ - \ \ - \ \ - \ Gibraltar\ - \ \ - \ \ - \ \ - \ \ - \ Pitcairn Islands\ - \ \ - \ \ - \ \ - \ \ - \ Monaco\ - \ \ - \ \ - \ \ - \ \ - \ Vatican City\ - \ \ - \ \ - \ \ - \ \ - \ Isle of Man\ - \ \ - \ \ - \ \ - \ \ - \ Guam\ - \ \ - \ \ - \ \ - \ \ - \ Singapore\ - \ \ - \ \ - \ \ - \ \ - \ Tokelau\ - \ \ - \ \ - \ \ - \\ - \\ - \\ - \\ - \" - -prismJs :: Text -prismJs = "\ - \var _self=\"undefined\"!=typeof window?window:\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\\blang(?:uage)?-([\\w-]+)\\b/i,n=0,e={},M={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof W?new W(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,\"&\").replace(/=l.reach);y+=m.value.length,m=m.next){var b=m.value;if(t.length>n.length)return;if(!(b instanceof W)){var k,x=1;if(h){if(!(k=z(v,y,n,f))||k.index>=n.length)break;var w=k.index,A=k.index+k[0].length,P=y;for(P+=m.value.length;P<=w;)m=m.next,P+=m.value.length;if(P-=m.value.length,y=P,m.value instanceof W)continue;for(var E=m;E!==t.tail&&(Pl.reach&&(l.reach=N);var j=m.prev;O&&(j=I(t,j,O),y+=O.length),q(t,j,x);var C=new W(o,g?M.tokenize(S,g):S,d,S);if(m=I(t,j,C),L&&I(t,m,L),1l.reach&&(l.reach=_.reach)}}}}}}(e,a,n,a.head,0),function(e){var n=[],t=e.head.next;for(;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=M.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=M.hooks.all[e];if(t&&t.length)for(var r,a=0;r=t[a++];)r(n)}},Token:W};function W(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||\"\").length}function z(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function i(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function I(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function q(e,n,t){for(var r=n.next,a=0;a\"+a.content+\"\"},!u.document)return u.addEventListener&&(M.disableWorkerMessageHandler||u.addEventListener(\"message\",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(M.highlight(r,M.languages[t],t)),a&&u.close()},!1)),M;var t=M.util.currentScript();function r(){M.manual||M.highlightAll()}if(t&&(M.filename=t.src,t.hasAttribute(\"data-manual\")&&(M.manual=!0)),!M.manual){var a=document.readyState;\"loading\"===a||\"interactive\"===a&&t&&t.defer?document.addEventListener(\"DOMContentLoaded\",r):window.requestAnimationFrame?window.requestAnimationFrame(r):window.setTimeout(r,16)}return M}(_self);\"undefined\"!=typeof module&&module.exports&&(module.exports=Prism),\"undefined\"!=typeof global&&(global.Prism=Prism);\ - \Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\\?[\\s\\S]+?\\?>/,greedy:!0},doctype:{pattern:/\"'[\\]]|\"[^\"]*\"|'[^']*')+(?:\\[(?:[^<\"'\\]]|\"[^\"]*\"|'[^']*'|<(?!!--)|)*\\]\\s*)?>/i,greedy:!0,inside:{\"internal-subset\":{pattern:/(^[^\\[]*\\[)[\\s\\S]+(?=\\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/\"[^\"]*\"|'[^']*'/,greedy:!0},punctuation:/^$|[[\\]]/,\"doctype-tag\":/^DOCTYPE/i,name:/[^\\s<>'\"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\\/?(?!\\d)[^\\s>\\/=$<%]+(?:\\s(?:\\s*[^\\s>\\/=]+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))|(?=[\\s/>])))+)?\\s*\\/?>/,greedy:!0,inside:{tag:{pattern:/^<\\/?[^\\s>\\/]+/,inside:{punctuation:/^<\\/?/,namespace:/^[^\\s>\\/:]+:/}},\"special-attr\":[],\"attr-value\":{pattern:/=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:\"attr-equals\"},/\"|'/]}},punctuation:/\\/?>/,\"attr-name\":{pattern:/[^\\s>\\/]+/,inside:{namespace:/^[^\\s>\\/:]+:/}}}},entity:[{pattern:/&[\\da-z]{1,8};/i,alias:\"named-entity\"},/&#x?[\\da-f]{1,8};/i]},Prism.languages.markup.tag.inside[\"attr-value\"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside[\"internal-subset\"].inside=Prism.languages.markup,Prism.hooks.add(\"wrap\",function(a){\"entity\"===a.type&&(a.attributes.title=a.content.replace(/&/,\"&\"))}),Object.defineProperty(Prism.languages.markup.tag,\"addInlined\",{value:function(a,e){var s={};s[\"language-\"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={\"included-cdata\":{pattern://i,inside:s}};t[\"language-\"+e]={pattern:/[\\s\\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp(\"(<__[^>]*>)(?:))*\\\\]\\\\]>|(?!)\".replace(/__/g,function(){return a}),\"i\"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore(\"markup\",\"cdata\",n)}}),Object.defineProperty(Prism.languages.markup.tag,\"addAttribute\",{value:function(a,e){Prism.languages.markup.tag.inside[\"special-attr\"].push({pattern:RegExp(\"(^|[\\\"'\\\\s])(?:\"+a+\")\\\\s*=\\\\s*(?:\\\"[^\\\"]*\\\"|'[^']*'|[^\\\\s'\\\">=]+(?=[\\\\s>]))\",\"i\"),lookbehind:!0,inside:{\"attr-name\":/^[^\\s=]+/,\"attr-value\":{pattern:/=[\\s\\S]+/,inside:{value:{pattern:/(^=\\s*([\"']|(?![\"'])))\\S[\\s\\S]*(?=\\2$)/,lookbehind:!0,alias:[e,\"language-\"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:\"attr-equals\"},/\"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend(\"markup\",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml;\ - \!function(s){var e=/(?:\"(?:\\\\(?:\\r\\n|[\\s\\S])|[^\"\\\\\\r\\n])*\"|'(?:\\\\(?:\\r\\n|[\\s\\S])|[^'\\\\\\r\\n])*')/;s.languages.css={comment:/\\/\\*[\\s\\S]*?\\*\\//,atrule:{pattern:/@[\\w-](?:[^;{\\s]|\\s+(?![\\s{]))*(?:;|(?=\\s*\\{))/,inside:{rule:/^@[\\w-]+/,\"selector-function-argument\":{pattern:/(\\bselector\\s*\\(\\s*(?![\\s)]))(?:[^()\\s]|\\s+(?![\\s)])|\\((?:[^()]|\\([^()]*\\))*\\))+(?=\\s*\\))/,lookbehind:!0,alias:\"selector\"},keyword:{pattern:/(^|[^\\w-])(?:and|not|only|or)(?![\\w-])/,lookbehind:!0}}},url:{pattern:RegExp(\"\\\\burl\\\\((?:\"+e.source+\"|(?:[^\\\\\\\\\\r\\n()\\\"']|\\\\\\\\[^])*)\\\\)\",\"i\"),greedy:!0,inside:{function:/^url/i,punctuation:/^\\(|\\)$/,string:{pattern:RegExp(\"^\"+e.source+\"$\"),alias:\"url\"}}},selector:{pattern:RegExp(\"(^|[{}\\\\s])[^{}\\\\s](?:[^{};\\\"'\\\\s]|\\\\s+(?![\\\\s{])|\"+e.source+\")*(?=\\\\s*\\\\{)\"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\\w\\xA0-\\uFFFF])(?!\\s)[-_a-z\\xA0-\\uFFFF](?:(?!\\s)[-\\w\\xA0-\\uFFFF])*(?=\\s*:)/i,lookbehind:!0},important:/!important\\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined(\"style\",\"css\"),t.tag.addAttribute(\"style\",\"css\"))}(Prism);\ - \Prism.languages.haskell={comment:{pattern:/(^|[^-!#$%*+=?&@|~.:<>^\\\\\\/])(?:--(?:(?=.)[^-!#$%*+=?&@|~.:<>^\\\\\\/].*|$)|\\{-[\\s\\S]*?-\\})/m,lookbehind:!0},char:{pattern:/'(?:[^\\\\']|\\\\(?:[abfnrtv\\\\\"'&]|\\^[A-Z@[\\]^_]|ACK|BEL|BS|CAN|CR|DC1|DC2|DC3|DC4|DEL|DLE|EM|ENQ|EOT|ESC|ETB|ETX|FF|FS|GS|HT|LF|NAK|NUL|RS|SI|SO|SOH|SP|STX|SUB|SYN|US|VT|\\d+|o[0-7]+|x[0-9a-fA-F]+))'/,alias:\"string\"},string:{pattern:/\"(?:[^\\\\\"]|\\\\(?:\\S|\\s+\\\\))*\"/,greedy:!0},keyword:/\\b(?:case|class|data|deriving|do|else|if|in|infixl|infixr|instance|let|module|newtype|of|primitive|then|type|where)\\b/,\"import-statement\":{pattern:/(^[\\t ]*)import\\s+(?:qualified\\s+)?(?:[A-Z][\\w']*)(?:\\.[A-Z][\\w']*)*(?:\\s+as\\s+(?:[A-Z][\\w']*)(?:\\.[A-Z][\\w']*)*)?(?:\\s+hiding\\b)?/m,lookbehind:!0,inside:{keyword:/\\b(?:as|hiding|import|qualified)\\b/,punctuation:/\\./}},builtin:/\\b(?:abs|acos|acosh|all|and|any|appendFile|approxRational|asTypeOf|asin|asinh|atan|atan2|atanh|basicIORun|break|catch|ceiling|chr|compare|concat|concatMap|const|cos|cosh|curry|cycle|decodeFloat|denominator|digitToInt|div|divMod|drop|dropWhile|either|elem|encodeFloat|enumFrom|enumFromThen|enumFromThenTo|enumFromTo|error|even|exp|exponent|fail|filter|flip|floatDigits|floatRadix|floatRange|floor|fmap|foldl|foldl1|foldr|foldr1|fromDouble|fromEnum|fromInt|fromInteger|fromIntegral|fromRational|fst|gcd|getChar|getContents|getLine|group|head|id|inRange|index|init|intToDigit|interact|ioError|isAlpha|isAlphaNum|isAscii|isControl|isDenormalized|isDigit|isHexDigit|isIEEE|isInfinite|isLower|isNaN|isNegativeZero|isOctDigit|isPrint|isSpace|isUpper|iterate|last|lcm|length|lex|lexDigits|lexLitChar|lines|log|logBase|lookup|map|mapM|mapM_|max|maxBound|maximum|maybe|min|minBound|minimum|mod|negate|not|notElem|null|numerator|odd|or|ord|otherwise|pack|pi|pred|primExitWith|print|product|properFraction|putChar|putStr|putStrLn|quot|quotRem|range|rangeSize|read|readDec|readFile|readFloat|readHex|readIO|readInt|readList|readLitChar|readLn|readOct|readParen|readSigned|reads|readsPrec|realToFrac|recip|rem|repeat|replicate|return|reverse|round|scaleFloat|scanl|scanl1|scanr|scanr1|seq|sequence|sequence_|show|showChar|showInt|showList|showLitChar|showParen|showSigned|showString|shows|showsPrec|significand|signum|sin|sinh|snd|sort|span|splitAt|sqrt|subtract|succ|sum|tail|take|takeWhile|tan|tanh|threadToIOResult|toEnum|toInt|toInteger|toLower|toRational|toUpper|truncate|uncurry|undefined|unlines|until|unwords|unzip|unzip3|userError|words|writeFile|zip|zip3|zipWith|zipWith3)\\b/,number:/\\b(?:\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?|0o[0-7]+|0x[0-9a-f]+)\\b/i,operator:[{pattern:/`(?:[A-Z][\\w']*\\.)*[_a-z][\\w']*`/,greedy:!0},{pattern:/(\\s)\\.(?=\\s)/,lookbehind:!0},/[-!#$%*+=?&@|~:<>^\\\\\\/][-!#$%*+=?&@|~.:<>^\\\\\\/]*|\\.[-!#$%*+=?&@|~.:<>^\\\\\\/]+/],hvariable:{pattern:/\\b(?:[A-Z][\\w']*\\.)*[_a-z][\\w']*/,inside:{punctuation:/\\./}},constant:{pattern:/\\b(?:[A-Z][\\w']*\\.)*[A-Z][\\w']*/,inside:{punctuation:/\\./}},punctuation:/[{}[\\];(),.:]/},Prism.languages.hs=Prism.languages.haskell;\ - \" - -prismCss :: Text -prismCss = "\ - \/* PrismJS 1.25.0\ - \https://prismjs.com/download.html#themes=prism&languages=haskell */\ - \code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}\ - \" diff --git a/examples/simple-routing/Pages.hs b/examples/simple-routing/Pages.hs deleted file mode 100644 index cffdcca..0000000 --- a/examples/simple-routing/Pages.hs +++ /dev/null @@ -1,219 +0,0 @@ -module Pages where - -import Control.Monad.IO.Class -import Control.Monad.Reader -import Data.Foldable -import Data.List qualified as List -import Data.Maybe -import Data.Ord -import Data.Text qualified as Text -import Data.Text (Text) -import Data.Function((&)) -import HtmlT -import Wasm.Compat.Marshal -import Wasm.Compat.Prim - -import "this" Assets -import "this" Router -import "this" Utils - -homePage :: Html () -homePage = unsafeHtml $ "\ - \

How routing works

\ - \

Inside the \ - \Router \ - \module there is a definition of type Route:

\ - \
" <> highlightHaskell "\
-  \data Route\n\
-  \  = HomeR -- matches root route\n\
-  \  | CountriesMapR CountriesMapQ -- example: #map?selected=ru\n\
-  \  | CountriesListR CountriesListQ -- example: #list?page=3"
-  <> "
\ - \

Here Route defines the list of webpages in the site. \ - \Constructor parameters (like CountriesMapQ) indicate \ - \that this page takes some information from the URL string encoded in GET \ - \parameters or URL segments. By convention route contructors have suffix \ - \-R and constructor parameters has suffix -Q

\ - \

Another importants definitions are these two functions:\ - \

" <> highlightHaskell "\
-  \parseRoute :: UrlParts -> Maybe Route\n\
-  \parseRoute = \\case\n\
-  \  Url [] [] -> Just HomeR\n\
-  \  Url [\"map\"] q\n\
-  \    | selected <- List.lookup \"selected\" q\n\
-  \    -> Just $ CountriesMapR CountriesMapQ{selected}\n\
-  \  Url [\"list\"] q\n\
-  \    | search <- List.lookup \"search\" q\n\
-  \    , page <- parsePage $ List.lookup \"page\" q\n\
-  \    , sort_dir <- parseSortDir $ List.lookup \"sort_dir\" q\n\
-  \    , sort_by <- parseSortBy $ List.lookup \"sort_by\" q\n\
-  \    -> Just $ CountriesListR CountriesListQ{search, page, sort_dir, sort_by}"
-  <> "
" <> highlightHaskell "\
-  \printRoute :: Route -> UrlParts\n\
-  \printRoute = \\case\n\
-  \  HomeR -> Url [] []\n\
-  \  CountriesMapR q -> Url [\"map\"] $ catMaybes\n\
-  \    [ (\"selected\",) <$> q.selected ]\n\
-  \  CountriesListR q -> Url [\"list\"] $ catMaybes\n\
-  \    [ (\"search\",) <$> mfilter (/=\"\") q.search\n\
-  \    , (\"page\",) <$> printPage q.page\n\
-  \    , (\"sort_dir\",) <$> printSortDir q.sort_dir\n\
-  \    , (\"sort_by\",) <$> printSortBy q.sort_by\n\
-  \    ]"
-  <>  "
\ - \With help of haskell guarded pattern-match syntax it's easy to convert a \ - \URL in form of UrlParts to a structured datatype like \ - \Route and other way around. The type Route and \ - \these two functions conclude the portable part of the routing mechanism. \ - \They can and should be shared with backend code to construct correct URLs \ - \and implement backend part of HTML5-style routing.

\ - \

Last thing we need to run the site is this auxiliary function \ - \mkUrlHashRef \ - \that creates a DynRef Text — dynamic value containing current \ - \hash-string from the browser. When parsed to Dynamic Route \ - \and then mapped with (<&>) operator to \ - \Dynamic (Html ()) the dyn function can be used to \ - \attach the contents of dynamic pages to the application.\ - \

" <> highlightHaskell "\
-  \dyn $ routeDyn <&> \\case\n\
-  \  HomeR -> homePage\n\
-  \  CountriesMapR q -> countriesMapPage q\n\
-  \  CountriesListR q -> countriesListPage q"
-  <> "

" - -countriesListPage :: CountriesListQ -> Html () -countriesListPage q = div_ [class_ "CountriesList"] do - searchQueryRef <- newRef q - form_ do - on @"submit" do - newRoute <- toUrl . CountriesListR . (\s -> s{page = 1}) <$> readRef searchQueryRef - pushUrl newRoute - div_ [style_ "display:flex;"] do - input_ - [ type_ "text" , placeholder_ "Search countries by title", autofocus_ True - ] do - dynValue $ fromMaybe "" . (.search) <$> fromRef searchQueryRef - on @"input" $ modifyRef searchQueryRef . (\v s -> s{search = v}) . Just - button_ [type_ "submit"] "Search" - table_ do - thead_ $ tr_ do - th_ "" - thSort SortByTitle "Country Name" - thSort SortByRegion "Region" - thSort SortBySubregion "Subregion" - thSort SortByPopulation "Population" - tbody_ do - for_ pageResults \(n, country) -> tr_ do - td_ do text (Text.pack (show @Int n)) - td_ do - a_ [href_ (mkMapLink country.code)] do - for_ country.flag_icon - (img_ . (>> style_ "display:inline; margin-right: 6px"). src_) - text country.title - td_ do text country.region - td_ do text country.subregion - td_ do text (Text.pack (show country.population)) - center_ do - for_ (paginate total q.page itemsPerPage) \case - Nothing -> - button_ [disabled_ True] "..." - Just p -> a_ - [ href_ (toUrl (CountriesListR q {page = p}))] $ - button_ [disabled_ (q.page == p)] $ text $ Text.pack $ show p - dl_ do - dt_ "Country" - dd_ $ unsafeHtml "The word country comes from \ - \Old French contrée, which derives from \ - \Vulgar Latin (terra) contrata (\"(land) lying \ - \opposite\"; \"(land) spread before\"), derived from contra \ - \(\"against, opposite\"). It most likely entered the English language \ - \after the Franco-Norman invasion\ - \ during the 11th century." - where - thSort sortBy title = th_ [style_ "cursor: pointer"] do - text title - case (q.sort_by, q.sort_dir) of - (sortVal, Asc) | sortVal == sortBy -> text "▲" - (sortVal, Desc) | sortVal == sortBy -> text "▼" - otherwise -> text "" - on @"click" do pushUrl $ toUrl . CountriesListR . toggleSortBy sortBy $ q - - toggleSortBy sortBy q - | q.sort_by == sortBy = q {sort_dir = flipDir q.sort_dir} - | otherwise = q {sort_by = sortBy, sort_dir = Asc} - where - flipDir = \case Asc -> Desc; Desc -> Asc - - offset = pred q.page * itemsPerPage - total = Prelude.length countryResults - pageResults = Prelude.zip [offset + 1..] - . Prelude.take itemsPerPage - . Prelude.drop offset - $ countryResults - countryResults = List.sortOn countrySortDir - . Prelude.filter countryFilter - $ countries - countryFilter country = case q.search of - Just needle -> - Text.isInfixOf (Text.toLower needle) (Text.toLower country.title) - Nothing -> True - countrySortBy = case q.sort_by of - SortByTitle -> Left . (.title) - SortByRegion -> Right . Left . (.region) - SortBySubregion -> Right . Right . Left . (.subregion) - SortByPopulation -> Right . Right . Right . (.population) - countrySortDir = case q.sort_dir of - Asc -> Left . countrySortBy - Desc -> Right . Down . countrySortBy - itemsPerPage = 40 - mkMapLink = toUrl . CountriesMapR . CountriesMapQ . Just . Text.toLower - -countriesMapPage :: CountriesMapQ -> Html () -countriesMapPage q = - div_ [class_ "CountriesMap"] $ - figure_ $ center_ do - unsafeHtml countriesMap - figcaption_ "political map of the planet Earth" - centerEl <- asks html_current_element - liftIO do - msel <- mapM toJSVal q.selected - js_selectCountry centerEl $ maybeToNullable msel - on @ClickWithEvent \event -> do - mcode <- liftIO (js_svgClickGetCountryCode event) - & (fmap nullableToMaybe) - & mapM fromJSVal - mapM_ (pushUrl . toUrl . CountriesMapR . CountriesMapQ . Just) mcode - -paginate - :: Int -- ^ Total number of items - -> Int -- ^ Current page - -> Int -- ^ Items per page - -> [Maybe Int] -- ^ List of page links, Nothing stands for ellipsis -paginate totalItems curPage limit - | totalPages <= maxLinks = - fmap Just [1..totalPages] - | curPage <= 7 = - fmap Just [1..8] <> [Nothing, Just totalPages] - | curPage >= totalPages - 6 = - [Just 1, Nothing] <> fmap Just [(totalPages - 8)..totalPages] - | otherwise = - [Just 1, Nothing] <> fmap Just [(curPage - 2)..(curPage + 3)] - <> [Nothing, Just totalPages] - where - (pageQuot, pageRem) = totalItems `divMod` limit - totalPages = if pageRem == 0 then pageQuot else pageQuot + 1 - maxLinks = 10 - - -data ClickWithEvent - -instance IsEventName ClickWithEvent where - type EventListenerCb ClickWithEvent = JSVal -> Step () - addEventListenerArgs = AddEventListenerArgs - { event_name = "dblclick" - , listener_options = defaultEventListenerOptions - , mk_callback = \k j -> k j - } diff --git a/examples/simple-routing/Router.hs b/examples/simple-routing/Router.hs deleted file mode 100644 index 050ceeb..0000000 --- a/examples/simple-routing/Router.hs +++ /dev/null @@ -1,185 +0,0 @@ -module Router where - -import Control.Monad -import Data.Bifunctor -import Data.List qualified as List -import Data.Maybe -import Data.Function -import GHC.Generics -import Text.Read -import Data.Text (Text) -import Data.Text qualified as Text -import Wasm.Compat.Prim -import Wasm.Compat.Marshal -import Data.Char qualified as C - -data UrlParts = Url - { partsPath :: [Text] -- ^ Path segments - , partsQuery :: [(Text, Text)] -- ^ GET parameters - } deriving (Eq, Show, Generic) - -data Route - = HomeR - | CountriesMapR CountriesMapQ - | CountriesListR CountriesListQ - deriving (Eq, Show, Generic) - -data CountriesListQ = CountriesListQ - { search :: Maybe Text - , page :: Int - , sort_by :: CountrySortBy - , sort_dir :: SortDir - } deriving (Eq, Show, Generic) - -data CountriesMapQ = CountriesMapQ - { selected :: Maybe Text - } deriving (Eq, Show, Generic) - -data SortDir = Asc | Desc - deriving (Eq, Show, Generic) - -data CountrySortBy - = SortByTitle - | SortByPopulation - | SortByRegion - | SortBySubregion - deriving (Eq, Show, Generic) - -parseRoute :: UrlParts -> Maybe Route -parseRoute = \case - Url [] [] -> Just HomeR - Url ["map"] q - | selected <- List.lookup "selected" q - -> Just $ CountriesMapR CountriesMapQ{selected} - Url ["list"] q - | search <- List.lookup "search" q - , page <- parsePage $ List.lookup "page" q - , sort_dir <- parseSortDir $ List.lookup "sort_dir" q - , sort_by <- parseSortBy $ List.lookup "sort_by" q - -> Just $ CountriesListR CountriesListQ{search, page, sort_dir, sort_by} - _ -> Nothing - where - parsePage = fromMaybe defaultCountriesListQ.page - . (parseIntQuery =<<) - parseSortDir = \case - Just "asc" -> Asc - Just "desc" -> Desc - _ -> defaultCountriesListQ.sort_dir - parseSortBy = \case - Just "title" -> SortByTitle - Just "population" -> SortByPopulation - Just "region" -> SortByRegion - Just "subregion" -> SortBySubregion - _ -> defaultCountriesListQ.sort_by - parseIntQuery = readMaybe . Text.unpack - -printRoute :: Route -> UrlParts -printRoute = \case - HomeR -> Url [] [] - CountriesMapR q -> Url ["map"] $ catMaybes - [ ("selected",) <$> q.selected ] - CountriesListR q -> Url ["list"] $ catMaybes - [ ("search",) <$> mfilter (/="") q.search - , ("page",) <$> printPage q.page - , ("sort_dir",) <$> printSortDir q.sort_dir - , ("sort_by",) <$> printSortBy q.sort_by - ] - where - printPage = fmap toIntQuery . - mfilter (/=defaultCountriesListQ.page) . Just - printSortDir = fmap (\case - Asc -> "asc" - Desc -> "desc") . - mfilter (/=defaultCountriesListQ.sort_dir) . Just - printSortBy = fmap (\case - SortByTitle -> "title" - SortByPopulation -> "population" - SortByRegion -> "region" - SortBySubregion -> "subregion") . - mfilter (/=defaultCountriesListQ.sort_by) . Just - toIntQuery = Text.pack . show - -defaultCountriesListQ :: CountriesListQ -defaultCountriesListQ = CountriesListQ - { search = Nothing - , page = 1 - , sort_by = SortByPopulation - , sort_dir = Desc - } - -defaultCountriesMapQ :: CountriesMapQ -defaultCountriesMapQ = CountriesMapQ - { selected = Nothing - } - -toUrl :: Route -> Text -toUrl = ("#"<>) . printUrlParts . printRoute - -fromUrl :: Text -> Maybe Route -fromUrl url = url - & Text.stripPrefix "#" - & fromMaybe url - & parseUrlParts - & parseRoute - -printUrlParts :: UrlParts -> Text -printUrlParts (Url s q) = Text.intercalate "?" (segments : query) - where - segments = - Text.intercalate "/" $ fmap encodeURIComponent s - query = q - & fmap (bimap encodeURIComponent encodeURIComponent) - & fmap (\(k, v) -> k <> "=" <> v) - & List.filter (not . Text.null) - & Text.intercalate "&" - & List.filter (not . Text.null) . (:[]) - -parseUrlParts :: Text -> UrlParts -parseUrlParts t = Url segments query - where - (segmentsStr, queryStr) = breakOn1 "?" t - segments = segmentsStr - & Text.splitOn "/" - & List.filter (not . Text.null) - & fmap decodeURIComponent - query = queryStr - & Text.splitOn "&" - & List.filter (not . Text.null) - & fmap (breakOn1 "=" . decodeURIComponent) - breakOn1 s t = - let (a, b) = Text.breakOn s t in (a, Text.drop 1 b) - -encodeURIComponent :: Text -> Text -encodeURIComponent = - Text.pack . concatMap encodeChar . Text.unpack - where - encodeChar c - | C.isAlphaNum c = [c] - | c == ' ' = "+" - | otherwise = '%' : showHex (C.ord c) "" - showHex :: Int -> String -> String - showHex n acc - | n < 16 = intToDigit n : acc - | otherwise = let (q,r) = n `divMod` 16 in showHex q (intToDigit r : acc) - intToDigit :: Int -> Char - intToDigit n - | 0 <= n && n <= 9 = toEnum (fromEnum '0' + n) - | 10 <= n && n <= 15 = toEnum (fromEnum 'a' + n - 10) - | otherwise = error "intToDigit: not a digit" - -decodeURIComponent :: Text -> Text -decodeURIComponent = - Text.pack . decode . Text.unpack - where - decode [] = [] - decode ('%':x1:x2:xs) - | C.isHexDigit x1 && C.isHexDigit x2 = - C.chr (16 * digitToInt x1 + digitToInt x2) : decode xs - decode ('+':xs) = ' ' : decode xs - decode (x:xs) = x : decode xs - digitToInt :: Char -> Int - digitToInt c - | '0' <= c && c <= '9' = fromEnum c - fromEnum '0' - | 'a' <= c && c <= 'f' = fromEnum c - fromEnum 'a' + 10 - | 'A' <= c && c <= 'F' = fromEnum c - fromEnum 'A' + 10 - | otherwise = error "digitToInt: not a digit" diff --git a/examples/simple-routing/Utils.hs b/examples/simple-routing/Utils.hs deleted file mode 100644 index 9b997b7..0000000 --- a/examples/simple-routing/Utils.hs +++ /dev/null @@ -1,82 +0,0 @@ -{-# LANGUAGE CPP #-} -{-# LANGUAGE ForeignFunctionInterface #-} -{-# LANGUAGE JavaScriptFFI #-} -module Utils where - -import Control.Monad.IO.Class -import Data.Coerce -import HtmlT -import Wasm.Compat.Prim -import Wasm.Compat.Marshal -import Unsafe.Coerce - -mkUrlHashRef :: MonadReactive m => m (DynRef JSString) -mkUrlHashRef = do - initial <- liftIO js_readUrlHash - routeRef <- newRef initial - win <- getCurrentWindow - popStateCb <- liftIO $ js_dynExport1 \_ -> - js_readUrlHash >>= dynStep . writeRef routeRef - liftIO $ js_addEventListener win ((\(JSString j) -> j) $ toJSString "onpopstate") popStateCb - return routeRef - -pushUrl :: MonadIO m => JSString -> m () -pushUrl url = liftIO $ js_pushHref url - -highlightHaskell :: JSString -> JSString -highlightHaskell = js_highlightHaskell - -insertScript :: JSString -> IO () -insertScript = js_insertScript - -#if defined(wasm32_HOST_ARCH) -foreign import javascript unsafe - "(function(el, code){\ - if (!code) return;\ - var svgGroup = el.querySelector('#' + code); if (!svgGroup) return;\ - var svgPaths = svgGroup instanceof SVGPathElement ? [svgGroup] : svgGroup.querySelectorAll('path');\ - for (var i = 0; i < svgPaths.length; i++) {\ - svgPaths[i].classList.add('selected');\ - }\ - svgGroup.parentElement.appendChild(svgGroup);\ - })($1,$2)" - js_selectCountry :: DOMElement -> Nullable JSVal -> IO () - -foreign import javascript unsafe - "(function(event){\ - var iter = event.target;\ - for(;;){\ - if (!iter || !iter.parentNode) break;\ - /* immediate children contains the country code */\ - if (iter.parentNode instanceof SVGSVGElement) return iter.id;\ - iter = iter.parentNode;\ - }\ - return null;\ - })($1)" - js_svgClickGetCountryCode :: DOMEvent -> IO (Nullable JSVal) - -foreign import javascript unsafe - "Prism.highlight($1, Prism.languages.haskell, 'haskell')" - js_highlightHaskell :: JSString -> JSString - -foreign import javascript unsafe - "(function(script){\ - var scriptEl = document.createElement('script');\ - scriptEl.innerText = script;\ - document.head.appendChild(scriptEl);\ - })($1)" - js_insertScript :: JSString -> IO () -foreign import javascript unsafe - "location.hash" - js_readUrlHash :: IO JSString -foreign import javascript unsafe - "location = $1;" - js_pushHref :: JSString -> IO () -#else -js_selectCountry :: DOMElement -> Nullable JSVal -> IO () = errorGhcjsOnly -js_svgClickGetCountryCode :: DOMEvent -> IO (Nullable JSVal) = errorGhcjsOnly -js_highlightHaskell :: JSString -> JSString = errorGhcjsOnly -js_insertScript :: JSString -> IO () = errorGhcjsOnly -js_readUrlHash :: IO JSString = errorGhcjsOnly -js_pushHref :: JSString -> IO () = errorGhcjsOnly -#endif diff --git a/examples/simple-routing/simple-routing.hs b/examples/simple-routing/simple-routing.hs deleted file mode 100644 index f3ad9b3..0000000 --- a/examples/simple-routing/simple-routing.hs +++ /dev/null @@ -1,72 +0,0 @@ -import Control.Monad -import Control.Monad.IO.Class -import Data.Maybe -import Data.Functor -import HtmlT -import Wasm.Compat.Prim -import Wasm.Compat.Marshal - -import "this" Pages -import "this" Router -import "this" Utils -import "this" Assets - -main :: IO () -main = return () - -foreign export ccall wasm_main :: IO () -wasm_main = void $ attachToBody do - liftIO $ insertScript prismJs - el "style" (text awsmCss) - el "style" (text customCss) - el "style" (text prismCss) - urlHashRef <- mkUrlHashRef - let routeDyn = fromMaybe HomeR . fromUrl <$> fromRef urlHashRef - header_ do - h1_ "Simple in-browser routing example" - p_ do - "See the source on the " - a_ [href_ "https://github.com/lagunoff/htmlt/blob/master/examples/\ - \simple-routing/"] "github" - nav_ $ ul_ do - let link t r = li_ $ a_ [href_ (toUrl r)] $ text t - link "Home" HomeR - link "List of Countries" $ CountriesListR defaultCountriesListQ - link "Countries on the Map" $ CountriesMapR defaultCountriesMapQ - main_ $ dyn $ routeDyn <&> \case - HomeR -> homePage - CountriesMapR q -> countriesMapPage q - CountriesListR q -> countriesListPage q - footer_ $ p_ $ a_ [href_ "https://github.com/lagunoff"] "Vladislav Lagunov" - -customCss :: JSString -customCss = "\ - \body header, body main, body footer, body article {\ - \ max-width: 80rem;\ - \}\ - \pre {\ - \ border-left: solid 8px rgb(0 0 0 / 14%);\ - \ padding-left: 16px;\ - \ background: transparent;\ - \}\ - \.CountriesList table {\ - \ width: 100%;;\ - \}\ - \.CountriesList table th, .CountriesList table td {\ - \ white-space: nowrap;\ - \}\ - \.CountriesList table th:last-child, .CountriesList table td:last-child {\ - \ width: 99%;\ - \ text-align: right;\ - \}\ - \.CountriesMap svg path.selected {\ - \ fill: #bfd3ff !important;\ - \ stroke: #4175e8;\ - \ stroke-width: 1;\ - \}\ - \.CountriesMap svg path {\ - \ cursor: pointer;\ - \}\ - \.CountriesMap svg path:hover {\ - \ fill: #ccc;\ - \}" diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs deleted file mode 100644 index 1eca558..0000000 --- a/examples/todomvc/TodoItem.hs +++ /dev/null @@ -1,113 +0,0 @@ -module TodoItem where - -import Control.Monad.State -import Data.Maybe -import GHC.Generics (Generic) -import HtmlT -import Data.Text -import Wasm.Compat.Marshal -import Wasm.Compat.Prim - -import "this" Utils - -data TodoItemConfig = TodoItemConfig - { self :: DynRef TodoItemState - , is_hidden_dyn :: Dynamic Bool - , ask_delete_item :: RI () - } - -data TodoItemState = TodoItemState - { title :: Text - , completed :: Bool - , editing :: Maybe Text - } deriving stock (Show, Eq, Generic) - -data TodoItemAction a where - CancelAction :: TodoItemConfig -> TodoItemAction () - CommitAction :: TodoItemConfig -> TodoItemAction () - InputAction :: TodoItemConfig -> Text -> TodoItemAction () - DoubleClickAction :: TodoItemConfig -> JSVal -> TodoItemAction () - CheckedAction :: TodoItemConfig -> Bool -> TodoItemAction () - KeydownAction :: TodoItemConfig -> Int -> TodoItemAction () - -eval :: TodoItemAction a -> RI a -eval = \case - CancelAction cfg -> - modifyRef cfg.self \s -> s{editing=Nothing} - CommitAction cfg -> do - state <- readRef cfg.self - case state.editing of - Just "" -> - cfg.ask_delete_item - Just t -> - modifyRef cfg.self \s -> s {editing=Nothing, title = t} - Nothing -> - pure () - InputAction cfg newVal -> - modifyRef cfg.self \s -> s{editing = Just newVal} - DoubleClickAction cfg targetEl -> do - modifyRef cfg.self \s -> s {editing = Just s.title} - liftIO $ js_todoItemInputFocus targetEl - CheckedAction cfg isChecked -> do - modifyRef cfg.self \s -> s{completed = isChecked} - KeydownAction cfg key -> case key of - 13 {- Enter -} -> eval (CommitAction cfg) - 27 {- Escape -} -> eval (CancelAction cfg) - _ -> return () - -html :: TodoItemConfig -> Html () -html cfg = li_ do - let - completedDyn = (.completed) <$> fromRef cfg.self - editingDyn = isJust . (.editing) <$> fromRef cfg.self - valueDyn = fromMaybe "" . (.editing) <$> fromRef cfg.self - toggleClass "completed" completedDyn - toggleClass "editing" editingDyn - toggleClass "hidden" cfg.is_hidden_dyn - div_ [class_ "view"] do - on @DblClickWithTarget $ eval . DoubleClickAction cfg - input_ [class_ "toggle", type_ "checkbox"] do - dynChecked $ (.completed) <$> fromRef cfg.self - on @"checkbox/change" $ eval . CheckedAction cfg - label_ $ dynText $ (.title) <$> fromRef cfg.self - button_ [class_ "destroy"] do - on @"click" cfg.ask_delete_item - input_ [class_ "edit", type_ "text"] do - dynValue valueDyn - on @"input" $ eval . InputAction cfg - on @"keydown" $ eval . KeydownAction cfg - on @"input/blur" $ const $ eval (CommitAction cfg) - -emptyTodoItemState :: TodoItemState -emptyTodoItemState = TodoItemState "" False Nothing - -instance ToJSVal TodoItemState where - toJSVal s = do - title <- toJSVal s.title - completed <- toJSVal s.completed - editing <- toJSVal s.editing - return $ js_buildObjectI3 - (toJSValPure @JSString "title") title - (toJSValPure @JSString "completed") completed - (toJSValPure @JSString "editing") editing - -instance FromJSVal TodoItemState where - fromJSVal j = do - mtitle <- fromJSVal =<< js_getProp j "title" - mcompleted <- fromJSVal =<< js_getProp j "completed" - mediting <- fromJSVal =<< js_getProp j "editing" - return do - title <- mtitle - completed <- mcompleted - editing <- mediting - return TodoItemState {..} - -data DblClickWithTarget - -instance IsEventName DblClickWithTarget where - type EventListenerCb DblClickWithTarget = JSVal -> RI () - addEventListenerArgs = AddEventListenerArgs - { event_name = "dblclick" - , listener_options = defaultEventListenerOptions - , mk_callback = \k j -> liftIO (js_getProp j "target") >>= k - } diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs deleted file mode 100644 index bf5ac3a..0000000 --- a/examples/todomvc/TodoList.hs +++ /dev/null @@ -1,586 +0,0 @@ -module TodoList where - -import Control.Monad.IO.Class -import Data.Foldable -import Data.List qualified as List -import Data.Maybe -import GHC.Generics (Generic) -import HtmlT -import Wasm.Compat.Marshal -import Wasm.Compat.Prim -import Data.Text (Text) -import Data.Text qualified as Text - -import "this" TodoItem qualified as TodoItem -import "this" Utils - -data TodoListConfig = TodoListConfig - { self :: DynRef TodoListState - } - -data TodoListState = TodoListState - { title :: Text - , todos :: [TodoItem.TodoItemState] - , filter :: Filter - } deriving (Show, Eq, Generic) - -data Filter = All | Active | Completed - deriving (Show, Eq, Generic) - -newtype LocalStorageTodoItems = LocalStorageTodoItems - { unLocalStorageTodoItems :: [TodoItem.TodoItemState] - } deriving newtype (ToJSVal, FromJSVal) - -data TodoListAction a where - UpdateFilter :: Filter -> TodoListAction () - PersistCurrentState :: TodoListAction () - ToggleAllAction :: Bool -> TodoListAction () - InputAction :: Text -> TodoListAction () - CommitAction :: TodoListAction () - KeydownAction :: Int -> TodoListAction () - DeleteItemAction :: Int -> TodoListAction () - ClearCompletedAction :: TodoListAction () - -new :: Filter -> RI (DynRef TodoListState) -new filter = do - todos <- fromMaybe [] . fmap unLocalStorageTodoItems <$> liftIO localStorageGet - newRef TodoListState - { todos - , filter - , title = "" - } - -eval :: TodoListConfig -> TodoListAction a -> RI a -eval cfg = \case - UpdateFilter filter -> - modifyRef cfg.self \s -> s {filter} - PersistCurrentState -> do - todosState <- readRef cfg.self - liftIO $ localStorageSet $ LocalStorageTodoItems todosState.todos - ToggleAllAction isChecked -> - modifyRef cfg.self \s -> s - { todos = - fmap (\i -> i {TodoItem.completed = isChecked}) s.todos - } - InputAction newVal -> do - modifyRef cfg.self \s -> s {title = newVal} - CommitAction -> do - title <- Text.strip . (.title) <$> readRef cfg.self - case title of - "" -> return () - t -> modifyRef cfg.self \s -> s - { todos = s.todos <> [mkNewItem t] - , title = "" - } - KeydownAction key -> case key of - 13 {- Enter -} -> eval cfg CommitAction - _ -> return () - DeleteItemAction itemIx -> - modifyRef cfg.self \s -> s {todos = deleteIx itemIx s.todos} - ClearCompletedAction -> - modifyRef cfg.self \s -> s - {todos = (List.filter (not . TodoItem.completed)) s.todos} - where - deleteIx :: Int -> [a] -> [a] - deleteIx _ [] = [] - deleteIx i (a:as) - | i == 0 = as - | otherwise = a : deleteIx (i-1) as - mkNewItem t = - TodoItem.emptyTodoItemState {TodoItem.title = t} - -html :: TodoListConfig -> Html () -html cfg = do - el "style" $ text styles - div_ do - section_ [class_ "todoapp"] do - headerWidget - mainWidget - footerWidget - footerInfoWidget - where - headerWidget = header_ [class_ "header"] do - h1_ (text "todos") - input_ [class_ "new-todo", placeholder_ "What needs to be done?", autofocus_ True] do - dynValue $ (.title) <$> fromRef cfg.self - on @"input" $ eval cfg . InputAction - on @"keydown" $ eval cfg . KeydownAction - mainWidget = section_ [class_ "main"] do - toggleClass "hidden" hiddenDyn - input_ [id_ "toggle-all", class_ "toggle-all", type_ "checkbox"] do - on @"checkbox/change" $ eval cfg . ToggleAllAction - return () - label_ do - attr "for" "toggle-all" - text "Mark all as completed" - ul_ [class_ "todo-list"] do - simpleList itemsDyn \idx todoRef -> - TodoItem.html $ TodoItem.TodoItemConfig - { TodoItem.self = todoRef - { modifier = todoItemModifier cfg idx todoRef.modifier - } - , TodoItem.is_hidden_dyn = - isTodoItemHidden <$> fromRef cfg.self <*> fromRef todoRef - , TodoItem.ask_delete_item = eval cfg (DeleteItemAction idx) - } - footerWidget = footer_ [class_ "footer"] do - toggleClass "hidden" hiddenDyn - span_ [class_ "todo-count"] do - strong_ $ dynText $ Text.pack . show <$> itemsLeftDyn - dynText $ pluralize " item left" " todos left" <$> itemsLeftDyn - ul_ [class_ "filters"] do - for_ [All, Active, Completed] filterWidget - button_ [class_ "clear-completed"] do - on @"click" $ eval cfg ClearCompletedAction - text "Clear completed" - footerInfoWidget = footer_ [class_ "info"] do - p_ "Double-click to edit a todo" - p_ do - text "Created by " - a_ [href_ "https://github.com/lagunoff"] "Vlad Lagunov" - p_ do - text "Part of " - a_ [href_ "http://todomvc.com"] "TodoMVC" - filterWidget flt = li_ do - a_ [href_ (printFilter flt)] do - toggleClass "selected" $ filterSelectedDyn flt - text $ Text.pack $ show flt - hiddenDyn = - Prelude.null . (.todos) <$> fromRef cfg.self - itemsLeftDyn = - countItemsLeft <$> fromRef cfg.self - filterSelectedDyn flt = - (==flt) . (.filter) <$> fromRef cfg.self - itemsDyn = - (.todos) <$> fromRef cfg.self - countItemsLeft TodoListState{todos} = - foldl (\acc TodoItem.TodoItemState{completed} -> - if not completed then acc + 1 else acc) 0 todos - isTodoItemHidden listState itemState = - case (listState.filter, itemState.completed) of - (Active, True) -> True - (Completed, False) -> True - _ -> False - --- | Synchronize changes inside TodoItem widget with the outer --- TodoList widget. -todoItemModifier - :: TodoListConfig - -> Int - -> Modifier TodoItem.TodoItemState - -> Modifier TodoItem.TodoItemState -todoItemModifier cfg idx elemModifier = Modifier \upd f -> do - -- Update the local TodoItem element widget - ((old, new), result) <- unModifier elemModifier upd \old -> - let (new, result) = f old in (new, ((old, new), result)) - let - -- When False, the update event won't be propagated into the outer - -- widget for the sake of optimization - needsUpdate = upd && (old.completed /= new.completed) - -- Update the outer widget - unModifier cfg.self.modifier needsUpdate \old -> - (old {todos = overIx idx (const new) old.todos}, ()) - return result - where - overIx :: Int -> (a -> a) -> [a] -> [a] - overIx 0 f (x:xs) = f x : xs - overIx n f (x:xs) = x : overIx (pred n) f xs - overIx n _ [] = [] - -pluralize :: Text -> Text -> Int -> Text -pluralize singular plural 0 = singular -pluralize singular plural _ = plural - -parseFilter :: Text -> Maybe Filter -parseFilter = \case - "#/" -> Just All - "#/active" -> Just Active - "#/completed" -> Just Completed - _ -> Nothing - -printFilter :: Filter -> Text -printFilter = \case - All -> "#/" - Active -> "#/active" - Completed -> "#/completed" - -styles :: Text -styles = "\ - \body {\ - \ margin: 0;\ - \ padding: 0;\ - \}\ - \\ - \button {\ - \ margin: 0;\ - \ padding: 0;\ - \ border: 0;\ - \ background: none;\ - \ font-size: 100%;\ - \ vertical-align: baseline;\ - \ font-family: inherit;\ - \ font-weight: inherit;\ - \ color: inherit;\ - \ -webkit-appearance: none;\ - \ appearance: none;\ - \ -webkit-font-smoothing: antialiased;\ - \ -moz-osx-font-smoothing: grayscale;\ - \}\ - \\ - \body {\ - \ font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;\ - \ line-height: 1.4em;\ - \ background: #f5f5f5;\ - \ color: #4d4d4d;\ - \ min-width: 230px;\ - \ max-width: 550px;\ - \ margin: 0 auto;\ - \ -webkit-font-smoothing: antialiased;\ - \ -moz-osx-font-smoothing: grayscale;\ - \ font-weight: 300;\ - \}\ - \\ - \:focus {\ - \ outline: 0;\ - \}\ - \\ - \.hidden {\ - \ display: none;\ - \}\ - \\ - \.todoapp {\ - \ background: #fff;\ - \ margin: 130px 0 40px 0;\ - \ position: relative;\ - \ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),\ - \ 0 25px 50px 0 rgba(0, 0, 0, 0.1);\ - \}\ - \\ - \.todoapp input::-webkit-input-placeholder {\ - \ font-style: italic;\ - \ font-weight: 300;\ - \ color: #e6e6e6;\ - \}\ - \\ - \.todoapp input::-moz-placeholder {\ - \ font-style: italic;\ - \ font-weight: 300;\ - \ color: #e6e6e6;\ - \}\ - \\ - \.todoapp input::input-placeholder {\ - \ font-style: italic;\ - \ font-weight: 300;\ - \ color: #e6e6e6;\ - \}\ - \\ - \.todoapp h1 {\ - \ position: absolute;\ - \ top: -155px;\ - \ width: 100%;\ - \ font-size: 100px;\ - \ font-weight: 100;\ - \ text-align: center;\ - \ color: rgba(175, 47, 47, 0.15);\ - \ -webkit-text-rendering: optimizeLegibility;\ - \ -moz-text-rendering: optimizeLegibility;\ - \ text-rendering: optimizeLegibility;\ - \}\ - \\ - \.new-todo,\ - \.edit {\ - \ position: relative;\ - \ margin: 0;\ - \ width: 100%;\ - \ font-size: 24px;\ - \ font-family: inherit;\ - \ font-weight: inherit;\ - \ line-height: 1.4em;\ - \ border: 0;\ - \ color: inherit;\ - \ padding: 6px;\ - \ border: 1px solid #999;\ - \ box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);\ - \ box-sizing: border-box;\ - \ -webkit-font-smoothing: antialiased;\ - \ -moz-osx-font-smoothing: grayscale;\ - \}\ - \\ - \.new-todo {\ - \ padding: 16px 16px 16px 60px;\ - \ border: none;\ - \ background: rgba(0, 0, 0, 0.003);\ - \ box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);\ - \}\ - \\ - \.main {\ - \ position: relative;\ - \ z-index: 2;\ - \ border-top: 1px solid #e6e6e6;\ - \}\ - \\ - \.toggle-all {\ - \ width: 1px;\ - \ height: 1px;\ - \ border: none; /* Mobile Safari */\ - \ opacity: 0;\ - \ position: absolute;\ - \ right: 100%;\ - \ bottom: 100%;\ - \}\ - \\ - \.toggle-all + label {\ - \ width: 60px;\ - \ height: 34px;\ - \ font-size: 0;\ - \ position: absolute;\ - \ top: -52px;\ - \ left: -13px;\ - \ -webkit-transform: rotate(90deg);\ - \ transform: rotate(90deg);\ - \}\ - \\ - \.toggle-all + label:before {\ - \ content: '❯';\ - \ font-size: 22px;\ - \ color: #e6e6e6;\ - \ padding: 10px 27px 10px 27px;\ - \}\ - \\ - \.toggle-all:checked + label:before {\ - \ color: #737373;\ - \}\ - \\ - \.todo-list {\ - \ margin: 0;\ - \ padding: 0;\ - \ list-style: none;\ - \}\ - \\ - \.todo-list li {\ - \ position: relative;\ - \ font-size: 24px;\ - \ border-bottom: 1px solid #ededed;\ - \}\ - \\ - \.todo-list li:last-child {\ - \ border-bottom: none;\ - \}\ - \\ - \.todo-list li.editing {\ - \ border-bottom: none;\ - \ padding: 0;\ - \}\ - \\ - \.todo-list li.editing .edit {\ - \ display: block;\ - \ width: calc(100% - 43px);\ - \ padding: 12px 16px;\ - \ margin: 0 0 0 43px;\ - \}\ - \\ - \.todo-list li.editing .view {\ - \ display: none;\ - \}\ - \\ - \.todo-list li .toggle {\ - \ text-align: center;\ - \ width: 40px;\ - \ /* auto, since non-WebKit browsers doesn't support input styling */\ - \ height: auto;\ - \ position: absolute;\ - \ top: 0;\ - \ bottom: 0;\ - \ margin: auto 0;\ - \ border: none; /* Mobile Safari */\ - \ -webkit-appearance: none;\ - \ appearance: none;\ - \}\ - \\ - \.todo-list li .toggle {\ - \ opacity: 0;\ - \}\ - \\ - \.todo-list li .toggle + label {\ - \ /*\ - \ Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433\ - \ IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/\ - \ */\ - \ background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');\ - \ background-repeat: no-repeat;\ - \ background-position: center left;\ - \}\ - \\ - \.todo-list li .toggle:checked + label {\ - \ background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');\ - \}\ - \\ - \.todo-list li label {\ - \ word-break: break-all;\ - \ padding: 15px 15px 15px 60px;\ - \ display: block;\ - \ line-height: 1.2;\ - \ transition: color 0.4s;\ - \}\ - \\ - \.todo-list li.completed label {\ - \ color: #d9d9d9;\ - \ text-decoration: line-through;\ - \}\ - \\ - \.todo-list li .destroy {\ - \ display: none;\ - \ position: absolute;\ - \ top: 0;\ - \ right: 10px;\ - \ bottom: 0;\ - \ width: 40px;\ - \ height: 40px;\ - \ margin: auto 0;\ - \ font-size: 30px;\ - \ color: #cc9a9a;\ - \ margin-bottom: 11px;\ - \ transition: color 0.2s ease-out;\ - \}\ - \\ - \.todo-list li .destroy:hover {\ - \ color: #af5b5e;\ - \}\ - \\ - \.todo-list li .destroy:after {\ - \ content: '×';\ - \}\ - \\ - \.todo-list li:hover .destroy {\ - \ display: block;\ - \}\ - \\ - \.todo-list li .edit {\ - \ display: none;\ - \}\ - \\ - \.todo-list li.editing:last-child {\ - \ margin-bottom: -1px;\ - \}\ - \\ - \.footer {\ - \ color: #777;\ - \ padding: 10px 15px;\ - \ height: 20px;\ - \ text-align: center;\ - \ border-top: 1px solid #e6e6e6;\ - \}\ - \\ - \.footer:before {\ - \ content: '';\ - \ position: absolute;\ - \ right: 0;\ - \ bottom: 0;\ - \ left: 0;\ - \ height: 50px;\ - \ overflow: hidden;\ - \ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),\ - \ 0 8px 0 -3px #f6f6f6,\ - \ 0 9px 1px -3px rgba(0, 0, 0, 0.2),\ - \ 0 16px 0 -6px #f6f6f6,\ - \ 0 17px 2px -6px rgba(0, 0, 0, 0.2);\ - \}\ - \\ - \.todo-count {\ - \ float: left;\ - \ text-align: left;\ - \}\ - \\ - \.todo-count strong {\ - \ font-weight: 300;\ - \}\ - \\ - \.filters {\ - \ margin: 0;\ - \ padding: 0;\ - \ list-style: none;\ - \ position: absolute;\ - \ right: 0;\ - \ left: 0;\ - \}\ - \\ - \.filters li {\ - \ display: inline;\ - \}\ - \\ - \.filters li a {\ - \ color: inherit;\ - \ margin: 3px;\ - \ padding: 3px 7px;\ - \ text-decoration: none;\ - \ border: 1px solid transparent;\ - \ border-radius: 3px;\ - \}\ - \\ - \.filters li a:hover {\ - \ border-color: rgba(175, 47, 47, 0.1);\ - \}\ - \\ - \.filters li a.selected {\ - \ border-color: rgba(175, 47, 47, 0.2);\ - \}\ - \\ - \.clear-completed,\ - \html .clear-completed:active {\ - \ float: right;\ - \ position: relative;\ - \ line-height: 20px;\ - \ text-decoration: none;\ - \ cursor: pointer;\ - \}\ - \\ - \.clear-completed:hover {\ - \ text-decoration: underline;\ - \}\ - \\ - \.info {\ - \ margin: 65px auto 0;\ - \ color: #bfbfbf;\ - \ font-size: 10px;\ - \ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\ - \ text-align: center;\ - \}\ - \\ - \.info p {\ - \ line-height: 1;\ - \}\ - \\ - \.info a {\ - \ color: inherit;\ - \ text-decoration: none;\ - \ font-weight: 400;\ - \}\ - \\ - \.info a:hover {\ - \ text-decoration: underline;\ - \}\ - \\ - \/*\ - \ Hack to remove background from Mobile Safari.\ - \ Can't use it globally since it destroys checkboxes in Firefox\ - \*/\ - \@media screen and (-webkit-min-device-pixel-ratio:0) {\ - \ .toggle-all,\ - \ .todo-list li .toggle {\ - \ background: none;\ - \ }\ - \\ - \ .todo-list li .toggle {\ - \ height: 40px;\ - \ }\ - \}\ - \\ - \@media (max-width: 430px) {\ - \ .footer {\ - \ height: 50px;\ - \ }\ - \\ - \ .filters {\ - \ bottom: 10px;\ - \ }\ - \}" diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs deleted file mode 100644 index 86626f8..0000000 --- a/examples/todomvc/Utils.hs +++ /dev/null @@ -1,80 +0,0 @@ -{-# LANGUAGE CPP #-} -{-# LANGUAGE ForeignFunctionInterface #-} -{-# LANGUAGE JavaScriptFFI #-} -module Utils where - -import Control.Monad -import Control.Monad.Reader -import Data.Typeable -import HtmlT -import Data.Text (Text) -import Wasm.Compat.Prim -import Wasm.Compat.Marshal - -mkUrlHashRef :: RI (DynRef Text) -mkUrlHashRef = do - reactiveEnv <- ask - initial <- liftIO $ textFromJSString =<< js_readUrlHash - routeRef <- newRef initial - win <- getCurrentWindow - popStateCb <- liftIO $ js_dynExport1 \_ -> - js_readUrlHash >>= textFromJSString >>= launchReactiveT reactiveEnv . writeRef routeRef - liftIO $ js_addEventListener win ((\(JSString j) -> j) $ toJSString "popstate") popStateCb - return routeRef - -localStorageSet :: forall a m. (MonadIO m, ToJSVal a, Typeable a) => a -> m () -localStorageSet val = - liftIO (toJSVal val >>= js_setItem key) - where - key = toJSString . show $ typeRepFingerprint $ typeRep (Proxy @a) - -localStorageGet :: forall a m. (MonadIO m, FromJSVal a, Typeable a) => m (Maybe a) -localStorageGet = liftIO do - mval <- nullableToMaybe <$> (js_getItem key) - liftIO $ js_consoleLog . (.unNullable) =<< js_getItem key - join <$> forM mval fromJSVal - where - key = toJSString . show . typeRepFingerprint $ typeRep (Proxy @a) - -#if defined(wasm32_HOST_ARCH) -foreign import javascript unsafe - "setTimeout(function() {\ - var inputEl = $1.parentNode.parentNode.querySelector('input.edit');\ - inputEl.focus();\ - }, 0)" - js_todoItemInputFocus :: JSVal -> IO () - -foreign import javascript unsafe - "localStorage.setItem($1, JSON.stringify($2));" - js_setItem :: JSString -> JSVal -> IO () - -foreign import javascript unsafe - "console.log($1)" - js_consoleLog :: JSVal -> IO () - -foreign import javascript unsafe - "var itemText = localStorage.getItem($1);\ - return itemText ? JSON.parse(itemText) : null;" - js_getItem :: JSString -> IO (Nullable JSVal) - -foreign import javascript unsafe - "location.hash" - js_readUrlHash :: IO JSString - --- Need this because GHC.JS.Prim.Internal.Build buildObjectI3 is --- broken. The FFI declarations were not migrated from GHCJS style --- properly, they throw ReferenceError: $1 is not defined -foreign import javascript unsafe - "(function(k1, v1, k2, v2, k3, v3){\ - var res = {};\ - res[k1] = v1; res[k2] = v2; res[k3] = v3;\ - return res;\ - })($1,$2,$3,$4,$5,$6)" - js_buildObjectI3 :: JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -#else -js_todoItemInputFocus :: JSVal -> IO () = errorGhcjsOnly -js_setItem :: JSString -> JSVal -> IO () = errorGhcjsOnly -js_getItem :: JSString -> IO (Nullable JSVal) = errorGhcjsOnly -js_readUrlHash :: IO JSString = errorGhcjsOnly -js_buildObjectI3 :: JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal = errorGhcjsOnly -#endif diff --git a/examples/todomvc/todomvc.hs b/examples/todomvc/todomvc.hs deleted file mode 100644 index 7df4c3a..0000000 --- a/examples/todomvc/todomvc.hs +++ /dev/null @@ -1,25 +0,0 @@ -import Control.Monad -import Control.Monad.Reader -import HtmlT -import Data.Maybe - -import "this" TodoList qualified as TodoList -import "this" Utils - -main :: IO () -main = return () - -foreign export ccall wasm_main :: IO () -wasm_main = void $ attachToBody do - reactiveEnv <- lift ask - urlHashRef <- lift mkUrlHashRef - let parseFilter = fromMaybe TodoList.All . TodoList.parseFilter - filter <- parseFilter <$> readRef urlHashRef - todosListInst <- lift $ TodoList.new filter - let cfg = TodoList.TodoListConfig todosListInst - lift $ urlHashRef.dynamic.updates.subscribe \newUrl -> do - let newFilter = parseFilter newUrl - TodoList.eval cfg $ TodoList.UpdateFilter newFilter - liftIO $ onBeforeUnload $ launchReactiveT reactiveEnv $ - TodoList.eval cfg TodoList.PersistCurrentState - TodoList.html cfg diff --git a/htmlt.cabal b/htmlt.cabal index f8ec6df..6b8a27b 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -89,8 +89,8 @@ library -- HtmlT.Main -- HtmlT.Property -- HtmlT.Types - HtmlT.Sketch - HtmlT.Sketch.FFI + Sketch + Sketch.FFI Wasm.Compat.Prim Wasm.Compat.Marshal diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index f9648f9..f37b2bf 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -98,14 +98,14 @@ newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v), getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), -ZC0ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, -ZC2ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC1ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC($1,a1)), -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3,$4) => {var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); $1.addEventListener(e, $4);}, -ZC4ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: () => (document.body), -ZC5ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); $1[k] = v;}, -ZC6ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, -ZC7ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); $1.appendChild(n); return n;}, -ZC8ZChtmltzm0zi1zi0zi0zminplaceZCHtmlTziSketchziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); $1.appendChild(n); return n;}, +ZC0ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, +ZC2ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC1ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC($1,a1)), +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3,$4) => {var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); $1.addEventListener(e, $4);}, +ZC4ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: () => (document.body), +ZC5ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); $1[k] = v;}, +ZC6ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, +ZC7ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); $1.appendChild(n); return n;}, +ZC8ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); $1.appendChild(n); return n;}, ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, diff --git a/src/HtmlT.hs b/src/HtmlT.hs deleted file mode 100644 index ebfb2c3..0000000 --- a/src/HtmlT.hs +++ /dev/null @@ -1,15 +0,0 @@ - -module HtmlT (module X) where - -import HtmlT.Base as X -import HtmlT.DOM as X -import HtmlT.Element as X -import HtmlT.Main as X -import HtmlT.Property as X -import HtmlT.Types as X - -import HtmlT.Event as X hiding - ( unsafeSubscribe - , unsafeTrigger - , Lens' - ) diff --git a/src/HtmlT/Base.hs b/src/HtmlT/Base.hs deleted file mode 100644 index 1d59962..0000000 --- a/src/HtmlT/Base.hs +++ /dev/null @@ -1,296 +0,0 @@ -{-| -Most essential public definions --} -module HtmlT.Base where - -import Control.Monad -import Control.Monad.Reader -import Data.Text -import Data.IORef -import Data.Foldable - -import HtmlT.DOM -import HtmlT.Event -import HtmlT.Internal -import HtmlT.Types -import Wasm.Compat.Marshal -import Wasm.Compat.Prim - --- | Create a DOM element with a given tag name and attach it to --- 'html_current_element'. Attributes, properties and children nodes can --- be added from inside the second argument --- --- > el "div" do --- > prop "className" "container" --- > el "span" $ text "Lorem Ipsum" -el :: Text -> Html a -> Html a -el tag child = do - newRootEl <- liftIO (createElement tag) - appendHtmlT newRootEl child - --- | Same as 'el' but allows to specify element's namespace --- https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS --- --- > elns "http://www.w3.org/2000/svg" "svg" do --- > prop "height" "210" --- > prop "width" "400" --- > elns "http://www.w3.org/2000/svg" "path" do --- > prop "d" "M150 0 L75 200 L225 200 Z" -elns :: Text -> Text -> Html a -> Html a -elns ns tag child = do - newRootEl <- liftIO (createElementNS ns tag) - appendHtmlT newRootEl child - --- | Create a TextNode and attach it to 'html_current_element' -text :: Text -> Html () -text txt = do - textNode <- liftIO (createTextNode txt) - insertNode textNode - --- | Create a TextNode with dynamic content -dynText :: Dynamic Text -> Html () -dynText d = do - txt <- readDyn d - textNode <- liftIO (createTextNode txt) - lift $ d.updates.subscribe \new -> void $ liftIO do - setTextValue textNode new - insertNode textNode - --- | Assign a property to 'html_current_element'. Don't confuse --- attributes and properties --- https://stackoverflow.com/questions/6003819/what-is-the-difference-between-properties-and-attributes-in-html -prop :: ToJSVal v => Text -> v -> Html () -prop key val = do - rootEl <- asks html_current_element - jkey <- liftIO $ textToJSString key - jval <- liftIO $ toJSVal val - liftIO $ js_setProp rootEl.unDOMElement jkey jval - --- | Assign a property with dynamic content to the root element -dynProp - :: (ToJSVal v, FromJSVal v) - => Text - -> Dynamic v - -> Html () -dynProp key dyn = do - jKey <- liftIO $ textToJSString key - el <- asks html_current_element - let setup el t = toJSVal t >>= js_setProp el.unDOMElement jKey - lift $ performDyn $ liftIO . setup el <$> dyn - --- | Assign an attribute to the root element. Don't confuse attributes --- and properties --- https://stackoverflow.com/questions/6003819/what-is-the-difference-between-properties-and-attributes-in-html -attr :: Text -> Text -> Html () -attr k v = do - el <- asks html_current_element - liftIO $ setAttribute el k v - --- | Assign an attribute with dynamic content to the root element -dynAttr :: Text -> Dynamic Text -> Html () -dynAttr k d = do - el <- asks html_current_element - lift $ performDyn $ liftIO . setAttribute el k <$> d - --- | Assign CSS classes to the current root element. Compared to @prop --- "className"@ can be used multiple times for the same root --- --- > el "div" do --- > classes "container row" --- > classes "mt-1 mb-2" --- classes :: Text -> Html () --- classes cs = do --- rootEl <- asks html_current_element --- for_ (T.splitOn " " cs) $ liftIO . classListAdd rootEl - --- | Assign a single CSS class dynamically based on the value held by --- the given Dynamic --- --- > showRef <- newRef False --- > el "div" do --- > toggleClass "show" $ fromRef showRef --- > el "button" do --- > on_ "click" $ modifyRef showRef not --- > text "Toggle visibility" -toggleClass :: Text -> Dynamic Bool -> Html () -toggleClass cs dyn = do - rootEl <- asks html_current_element - lift $ performDyn $ liftIO . setup rootEl cs <$> dyn - where - setup rootEl cs = \case - True -> classListAdd rootEl cs - False -> classListRemove rootEl cs - --- | Assign a boolean attribute dynamically based on the value held by --- the given Dynamic --- --- > hiddenRef <- newRef True --- > el "div" do --- > toggleAttr "hidden" $ fromRef hiddenRef --- > el "button" do --- > on_ "click" $ modifyRef hiddenRef not --- > text "Toggle visibility" -toggleAttr :: Text -> Dynamic Bool -> Html () -toggleAttr att dyn = do - rootEl <- asks html_current_element - lift $ performDyn $ liftIO . setup rootEl att <$> dyn - where - setup rootEl name = \case - True -> setAttribute rootEl name "on" - False -> removeAttribute rootEl name - --- | Assign a CSS property to the root dynamically based on the value --- held by the given Dynamic --- --- > colorRef <- newRef True --- > el "button" do --- > dynStyle "background" $ bool "initial" "red" <$> fromRef colorRef --- > on_ "click" $ modifyRef colorRef not --- > text "Toggle background color" -dynStyle :: Text -> Dynamic Text -> Html () -dynStyle cssProp dyn = do - rootEl <- asks html_current_element - jCssProp <- liftIO $ textToJSString cssProp - lift $ performDyn $ liftIO . setup jCssProp rootEl <$> dyn - where - setup jCssProp el t = do - styleVal <- js_getProp el.unDOMElement $ toJSString "style" - cssVal <- toJSVal t - js_setProp styleVal jCssProp cssVal - --- | Alias for @pure ()@, useful when some Html action is expected. -blank :: Applicative m => m () -blank = pure () - --- | Attach a dynamic list to the root. Convenient for displaying --- small dynamic collections (<100 elements). --- --- > listRef <- newRef ["One", "Two", "Three"] --- > el "ul" do --- > simpleList listRef \_idx elemRef -> do --- > el "li" $ dynText $ fromRef elemRef --- > el "button" do --- > on_ "click" $ modifyRef listRef ("New Item":) --- > text "Append new item" -simpleList - :: forall a. Dynamic [a] - -- ^ Some dynamic data from the above scope - -> (Int -> DynRef a -> Html ()) - -- ^ Function to build children widget. Accepts the index inside the - -- collection and dynamic data for that particular element - -> Html () -simpleList listDyn h = do - outerBoundary <- insertBoundary - htmlEnv <- asks \h -> h {html_content_boundary = Just outerBoundary} - outerReactiveEnv <- lift ask - prevValue <- liftIO $ newIORef [] - elemEnvsRef <- liftIO $ newIORef ([] :: [ElemEnv a]) - let - exec :: ElemEnv a -> Html x -> RI x - exec e = local (const e.ee_reactive_env) . - execHtmlT e.ee_html_env - setup :: Int -> [a] -> [ElemEnv a] -> RI [ElemEnv a] - setup idx new existing = case (existing, new) of - ([], []) -> return [] - -- New list is longer, append new elements - ([], x:xs) -> do - elementScope <- newReactiveScope - elementRef <- newRef x - elementBoundary <- execHtmlT htmlEnv insertBoundary - let - elementHtmlEnv = htmlEnv - { html_content_boundary = Just elementBoundary - } - elementReactiveEnv = outerReactiveEnv - { scope = elementScope - } - let elementEnv = ElemEnv elementHtmlEnv elementReactiveEnv elementRef - exec elementEnv $ h idx elementRef - fmap (elementEnv:) $ setup (idx + 1) xs [] - -- New list is shorter, delete the elements that no longer - -- present in the new list - (r:rs, []) -> do - finalizeElems True (r:rs) - return [] - -- Update child elements along the way - (r:rs, y:ys) -> do - writeRef (ee_dyn_ref r) y - fmap (r:) $ setup (idx + 1) ys rs - finalizeElems remove = traverse_ \ee -> do - when remove $ - liftIO $ mapM_ removeBoundary $ ee.ee_html_env.html_content_boundary - freeScope ee.ee_reactive_env.scope - updateList new = do - old <- liftIO $ atomicModifyIORef' prevValue (new,) - eenvs <- liftIO $ readIORef elemEnvsRef - newEenvs <- setup 0 new eenvs - liftIO $ writeIORef elemEnvsRef newEenvs - cleanup = do - old <- liftIO $ readIORef elemEnvsRef - finalizeElems False old - lift $ performDyn $ fmap updateList listDyn - lift $ installFinalizer cleanup - --- | First build a DOM with the widget that is currently held by the --- given Dynamic, then rebuild it every time Dynamic's value --- changes. Useful for SPA routing, tabbed components etc. --- --- > routeRef <- newRef Home --- > el "div" do --- > dyn $ routeRef <&> \case --- > Home -> homeWidget --- > Blog -> blogWidget --- > Resume -> resumeWidget --- > el "button" do --- > on_ "click" $ writeRef routeRef Blog --- > text "Show my blog page" -dyn :: Dynamic (Html ()) -> Html () -dyn d = do - htmlEnv <- ask - boundary <- insertBoundary - newScope <- lift newReactiveScope - initialVal <- readDyn d - let - update html = do - liftIO $ clearBoundary boundary - html - exec = local (\s -> s {scope = newScope}) . - execHtmlT htmlEnv {html_content_boundary = Just boundary} - lift $ exec $ update initialVal - lift $ d.updates.subscribe \newVal -> do - freeScope newScope - exec $ update newVal - --- | Attach resulting DOM to the given node instead of --- 'html_current_element'. Might be useful for implementing modal --- dialogs, tooltips etc. Similar to what called portals in React --- ecosystem -portal :: DOMElement -> Html a -> Html a -portal newRootEl html = do - boundary <- local (\e -> e - { html_current_element = newRootEl - , html_content_boundary = Nothing - }) insertBoundary - result <- local (\e -> e - { html_current_element = newRootEl - , html_content_boundary = Just boundary - }) html - lift $ installFinalizer $ liftIO $ removeBoundary boundary - return result - --- | Parse given text as HTML and attach the resulting tree to --- 'html_current_element'. This way you can create not only HTML but --- anything that @innerHTML@ property can create (e.g. SVG) --- --- > -- Create a div with an SVG image inside that shows a black --- > -- circle --- > div_ [] do --- > unsafeHtml "\ --- > \\ --- > \" -unsafeHtml :: Text -> Html () -unsafeHtml htmlText = do - henv <- ask - let anchor = fmap (.boundary_end) henv.html_content_boundary - liftIO $ unsafeInsertHtml henv.html_current_element anchor - htmlText diff --git a/src/HtmlT/DOM.hs b/src/HtmlT/DOM.hs deleted file mode 100644 index 26f5ff5..0000000 --- a/src/HtmlT/DOM.hs +++ /dev/null @@ -1,518 +0,0 @@ -{-| -Functions and definitions to manipulate and query the DOM tree --} -{-# OPTIONS_GHC -fno-warn-orphans #-} -{-# LANGUAGE CPP #-} -{-# LANGUAGE ForeignFunctionInterface #-} - -#if defined(wasm32_HOST_ARCH) -{-# LANGUAGE JavaScriptFFI #-} -#endif -module HtmlT.DOM where - -import Control.Monad.Reader -import Data.Kind -import Data.Text -import GHC.Exts as Exts -import GHC.Generics hiding (RI) -import HtmlT.Event -import HtmlT.Types -import Wasm.Compat.Marshal -import Wasm.Compat.Prim - -data EventListenerOptions = EventListenerOptions - { prevent_default :: Bool - , stop_propagation :: Bool - } deriving stock (Generic, Show, Eq) - -defaultEventListenerOptions :: EventListenerOptions -defaultEventListenerOptions = EventListenerOptions - { prevent_default = False - , stop_propagation = False - } - -on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> Html () -on k = addEventListener (addEventListenerArgs @eventName) k - -data AddEventListenerArgs callback = AddEventListenerArgs - { event_name :: Text - , listener_options :: EventListenerOptions - , mk_callback :: callback -> JSVal -> RI () - } deriving (Generic) - -addEventListener :: AddEventListenerArgs callback -> callback -> Html () -addEventListener args k = do - el <- asks (.html_current_element) - addEventListenerTarget el.unDOMElement args k - --- | EventTarget.addEventListener() --- https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener -addEventListenerTarget - :: JSVal - -> AddEventListenerArgs callback - -> callback - -> Html () -addEventListenerTarget target args k = do - e <- lift ask - cb <- liftIO $ js_dynExport1 $ launchReactiveT e . args.mk_callback k - jEventName <- liftIO $ toJSVal args.event_name - -- jscb <- withopts hscb - liftIO $ js_addEventListener target jEventName cb - let reactiveScope = 1::Int - installFinalizer _ _ = return () - installFinalizer reactiveScope do - js_addEventListener target jEventName cb - freeJSVal cb - -class IsEventName eventName where - type EventListenerCb eventName :: Type - addEventListenerArgs :: AddEventListenerArgs (EventListenerCb eventName) - -instance IsEventName "click" where - type EventListenerCb "click" = RI () - addEventListenerArgs = pointerEventArgs "click" - -instance IsEventName "mousedown" where - type EventListenerCb "mousedown" = RI () - addEventListenerArgs = pointerEventArgs "mousedown" - -instance IsEventName "mouseup" where - type EventListenerCb "mouseup" = RI () - addEventListenerArgs = pointerEventArgs "mouseup" - -instance IsEventName "dblclick" where - type EventListenerCb "dblclick" = RI () - addEventListenerArgs = pointerEventArgs "dblclick" - -instance IsEventName "submit" where - type EventListenerCb "submit" = RI () - addEventListenerArgs = submitEventArgs - -instance IsEventName "input" where - type EventListenerCb "input" = Text -> RI () - addEventListenerArgs = inputEventArgs - -instance IsEventName "keydown" where - type EventListenerCb "keydown" = Int -> RI () - addEventListenerArgs = keyboardEventArgs "keydown" - -instance IsEventName "keyup" where - type EventListenerCb "keyup" = Int -> RI () - addEventListenerArgs = keyboardEventArgs "keyup" - -instance IsEventName "focus" where - type EventListenerCb "focus" = RI () - addEventListenerArgs = pointerEventArgs "focus" - -instance IsEventName "blur" where - type EventListenerCb "blur" = RI () - addEventListenerArgs = pointerEventArgs "blur" - -instance IsEventName "input/blur" where - type EventListenerCb "input/blur" = Text -> RI () - addEventListenerArgs = inputEventArgs {event_name = "blur"} - -instance IsEventName "input/focus" where - type EventListenerCb "input/focus" = Text -> RI () - addEventListenerArgs = inputEventArgs {event_name = "focus"} - -instance IsEventName "checkbox/change" where - type EventListenerCb "checkbox/change" = Bool -> RI () - addEventListenerArgs = checkboxChangeEventArgs - -instance IsEventName "select/change" where - type EventListenerCb "select/change" = Text -> RI () - addEventListenerArgs = selectChangeEventArgs - --- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event -pointerEventArgs :: Text -> AddEventListenerArgs (RI ()) -pointerEventArgs event_name = AddEventListenerArgs - { event_name - , listener_options = defaultEventListenerOptions - , mk_callback = \k _ -> k - } - --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event -submitEventArgs :: AddEventListenerArgs (RI ()) -submitEventArgs = AddEventListenerArgs - { event_name = "submit" - , listener_options = defaultSubmitOptions - , mk_callback = \k _ -> k - } - where - defaultSubmitOptions = EventListenerOptions True True - --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event -inputEventArgs :: AddEventListenerArgs (Text -> RI ()) -inputEventArgs = AddEventListenerArgs - { event_name = "input" - , listener_options = defaultEventListenerOptions - , mk_callback = \k event -> do - target <- liftIO $ js_getProp event "target" - value <- liftIO $ js_getProp target "value" - liftIO (fromJSVal value) >>= mapM_ k - } - --- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardEventArgs :: Text -> AddEventListenerArgs (Int -> RI ()) -keyboardEventArgs event_name = AddEventListenerArgs - { event_name - , listener_options = defaultEventListenerOptions - , mk_callback = \k event -> do - keyCode <- liftIO $ js_getProp event "keyCode" - liftIO (fromJSVal keyCode) >>= mapM_ k - } - --- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event -focusEventArgs :: Text -> AddEventListenerArgs (RI ()) -focusEventArgs event_name = AddEventListenerArgs - { event_name - , listener_options = defaultEventListenerOptions - , mk_callback = \k _ -> k - } - --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -checkboxChangeEventArgs :: AddEventListenerArgs (Bool -> RI ()) -checkboxChangeEventArgs = AddEventListenerArgs - { event_name = "change" - , listener_options = defaultEventListenerOptions - , mk_callback = \k event -> do - target <- liftIO $ js_getProp event "target" - checked <- liftIO $ js_getProp target "checked" - liftIO (fromJSVal checked) >>= mapM_ k - } - --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -selectChangeEventArgs :: AddEventListenerArgs (Text -> RI ()) -selectChangeEventArgs = AddEventListenerArgs - { event_name = "change" - , listener_options = defaultEventListenerOptions - , mk_callback = \k event -> do - target <- liftIO $ js_getProp event "target" - value <- liftIO $ js_getProp target "value" - liftIO (fromJSVal value) >>= mapM_ k - } - -data Location = Location - { protocol :: Text - -- ^ A string containing the protocol scheme of the URL, including - -- the final ':' - , hostname :: Text - -- ^ A string containing the domain of the URL. - , port :: Text - -- ^ A string containing the port number of the URL. - , pathname :: Text - -- ^ A string containing an initial '/' followed by the path of the - -- URL, not including the query string or fragment. - , search :: Text - -- ^ A string containing a '?' followed by the parameters or - -- "querystring" of the URL - , hash :: Text - -- ^ A string containing a '#' followed by the fragment identifier - -- of the URL. - } deriving stock (Show, Eq, Generic) - --- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event -popstateEventArgs :: AddEventListenerArgs (Location -> RI ()) -popstateEventArgs = AddEventListenerArgs - { event_name = "popstate" - , listener_options = defaultEventListenerOptions - , mk_callback = \k _event -> do - win <- liftIO js_getCurrentWindow - loc <- liftIO $ js_getProp win "location" - mprotocol <- liftIO $ fromJSVal =<< js_getProp loc "protocol" - mhostname <- liftIO $ fromJSVal =<< js_getProp loc "hostname" - mport <- liftIO $ fromJSVal =<< js_getProp loc "port" - mpathname <- liftIO $ fromJSVal =<< js_getProp loc "pathname" - msearch <- liftIO $ fromJSVal =<< js_getProp loc "search" - mhash <- liftIO $ fromJSVal =<< js_getProp loc "hash" - mapM_ k do - protocol <- mprotocol - hostname <- mhostname - port <- mport - pathname <- mpathname - search <- msearch - hash <- mhash - return Location {..} - } - --- | Get global Window object @window@ --- https://developer.mozilla.org/en-US/docs/Web/API/Window -getCurrentWindow :: MonadIO m => m JSVal -getCurrentWindow = liftIO js_getCurrentWindow - --- | Get global Document object --- https://developer.mozilla.org/en-US/docs/Web/API/Document -getCurrentDocument :: MonadIO m => m JSVal -getCurrentDocument = liftIO js_getCurrentDocument - --- | Get Document.body property --- https://developer.mozilla.org/en-US/docs/Web/API/Document/body -getCurrentBody :: MonadIO m => m DOMElement -getCurrentBody = liftIO $ fmap DOMElement js_getCurrentBody - --- | DOMElement.appendChild() --- https://developer.mozilla.org/en-US/docs/Web/API/DOMNode/appendChild -appendChild :: DOMElement -> DOMNode -> IO () -appendChild = js_appendChild - --- | Element.setAttribute() --- https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute -setAttribute :: DOMElement -> Text -> Text -> IO () -setAttribute e k v = do - jk <- textToJSString k - jv <- textToJSString v - js_setAttribute e jk jv - --- | Element.removeAttribute() --- https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute -removeAttribute :: DOMElement -> Text -> IO () -removeAttribute e k = do - jk <- textToJSString k - js_removeAttribute e jk - --- | DOMNode.removeChild() --- https://developer.mozilla.org/en-US/docs/Web/API/DOMNode/removeChild -removeChild :: DOMElement -> DOMNode -> IO () -removeChild = js_removeChild - --- | Document.createElement() --- https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement -createElement :: Text -> IO DOMElement -createElement tagName = do - jTagName <- textToJSString tagName - js_createElement jTagName - --- | Document.createElementNS() --- https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS -createElementNS :: Text -> Text -> IO DOMElement -createElementNS ns tagName = do - jNs <- textToJSString ns - jTagName <- textToJSString tagName - js_createElementNS jNs jTagName - --- | Document.createTextNode() --- https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode -createTextNode :: Text -> IO DOMNode -createTextNode t = do - jt <- textToJSString t - js_createTextNode jt - --- | Document.createComment() --- https://developer.mozilla.org/en-US/docs/Web/API/Document/createComment -createComment :: Text -> IO DOMNode -createComment c = do - jc <- textToJSString c - js_createComment jc - --- | Element.classList.add() --- https://developer.mozilla.org/en-US/docs/Web/API/Element/classList -classListAdd :: DOMElement -> Text -> IO () -classListAdd e c = do - jc <- textToJSString c - js_classListAdd e jc - --- | Element.classList.remove() --- https://developer.mozilla.org/en-US/docs/Web/API/Element/classList -classListRemove :: DOMElement -> Text -> IO () -classListRemove e c = do - jc <- textToJSString c - js_classListRemove e jc - --- | Assign text to DOMNode.nodeValue --- https://developer.mozilla.org/en-US/docs/Web/API/DOMNode/nodeValue -setTextValue :: DOMNode -> Text -> IO () -setTextValue n v = do - jv <- textToJSString v - js_setTextValue n jv - --- | Insert raw HTML code, similar to @parent.innerHTML = rawHtml@ but --- does not removes siblings -unsafeInsertHtml :: DOMElement -> Maybe DOMNode -> Text -> IO () -unsafeInsertHtml parent manchor rawHtml = do - jRawHtml <- textToJSString rawHtml - js_unsafeInsertHtml parent (maybeToNullable manchor) jRawHtml - --- | Assuming given 'ContentBoundary' was inserted into the @parent@ --- element remove all the content inside the boundary. -clearBoundary :: ContentBoundary -> IO () -clearBoundary b = - js_clearBoundary b.boundary_begin b.boundary_end - --- | Detach 'ContentBoundary' from the DOM and everything inside the --- boundary. -removeBoundary :: ContentBoundary -> IO () -removeBoundary b = do - js_clearBoundary b.boundary_begin b.boundary_end - js_detachBoundary b.boundary_begin b.boundary_end - --- | Run a given callback on BeforeUnloadEvent --- https://developer.mozilla.org/en-US/docs/Web/API/BeforeUnloadEvent -onBeforeUnload :: IO () -> IO () -onBeforeUnload cb = do - jscb <- js_dynExport1 (const cb) - js_onBeforeUnload jscb - return () - --- | Collection of deltaX, deltaY and deltaZ properties from WheelEvent --- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent -data MouseDelta = MouseDelta - { md_delta_x :: Int - , md_delta_y :: Int - , md_delta_z :: Int - } deriving stock (Eq, Show, Generic) - --- | Pair of two values, might denote either a size or coordinates in --- different contexts -data Point a = Point - { pt_x :: a - , pt_y :: a - } deriving stock (Eq, Show, Ord, Functor, Generic) - -errorGhcjsOnly :: a -errorGhcjsOnly = error "Only GHCJS is supported" - -#if !defined(wasm32_HOST_ARCH) -js_onBeforeUnload :: JSVal {-Callback a-} -> IO () -js_onBeforeUnload = errorGhcjsOnly - -js_appendChild :: DOMElement -> DOMNode -> IO () = errorGhcjsOnly -js_insertBefore :: DOMElement -> DOMNode -> DOMNode -> IO () = errorGhcjsOnly -js_clearBoundary :: DOMNode -> DOMNode -> IO () = errorGhcjsOnly -js_detachBoundary :: DOMNode -> DOMNode -> IO () = errorGhcjsOnly -js_setAttribute :: DOMElement -> JSString -> JSString -> IO () = errorGhcjsOnly -js_removeAttribute :: DOMElement -> JSString -> IO () = errorGhcjsOnly -js_removeChild :: DOMElement -> DOMNode -> IO () = errorGhcjsOnly -js_replaceChild :: DOMElement -> DOMNode -> DOMNode -> IO () = errorGhcjsOnly -js_createElement :: JSString -> IO DOMElement = errorGhcjsOnly -js_createElementNS :: JSString -> JSString -> IO DOMElement = errorGhcjsOnly -js_createTextNode :: JSString -> IO DOMNode = errorGhcjsOnly -js_createComment :: JSString -> IO DOMNode = errorGhcjsOnly -js_classListAdd :: DOMElement -> JSString -> IO () = errorGhcjsOnly -js_classListRemove :: DOMElement -> JSString -> IO () = errorGhcjsOnly -js_setTextValue :: DOMNode -> JSString -> IO () = errorGhcjsOnly -js_getCurrentWindow :: IO JSVal = errorGhcjsOnly -js_getCurrentDocument :: IO JSVal = errorGhcjsOnly -js_getCurrentBody :: IO JSVal = errorGhcjsOnly -js_unsafeInsertHtml :: DOMElement -> Nullable DOMNode -> JSString -> IO () = errorGhcjsOnly -js_waitDocumentLoad :: IO () = errorGhcjsOnly -js_callbackWithOptions :: Bool -> Bool -> JSVal {-Callback (JSVal -> IO ())-} -> IO JSVal {-(Callback (JSVal -> IO ()))-} = errorGhcjsOnly -js_setProp :: JSVal -> JSString -> JSVal -> IO () = errorGhcjsOnly -js_dynExport1 :: (JSVal -> IO ()) -> IO JSVal = errorGhcjsOnly -js_addEventListener :: JSVal -> JSVal -> JSVal -> IO () = errorGhcjsOnly -js_removeEventListener :: JSVal -> JSVal -> JSVal -> IO () = errorGhcjsOnly - -#else -foreign import javascript unsafe - "$1.appendChild($2)" - js_appendChild :: DOMElement -> DOMNode -> IO () -foreign import javascript unsafe - "$1.insertBefore($2, $3)" - js_insertBefore :: DOMElement -> DOMNode -> DOMNode -> IO () -foreign import javascript unsafe - "$1.setAttribute($2, $3)" - js_setAttribute :: DOMElement -> JSString -> JSString -> IO () -foreign import javascript unsafe - "$1.removeAttribute($2)" - js_removeAttribute :: DOMElement -> JSString -> IO () -foreign import javascript unsafe - "$1.removeChild($2)" - js_removeChild :: DOMElement -> DOMNode -> IO () -foreign import javascript unsafe - "$1.replaceChild($2, $3)" - js_replaceChild :: DOMElement -> DOMNode -> DOMNode -> IO () -foreign import javascript unsafe - "document.createElement($1)" - js_createElement :: JSString -> IO DOMElement -foreign import javascript unsafe - "document.createElementNS($1, $2)" - js_createElementNS :: JSString -> JSString -> IO DOMElement -foreign import javascript unsafe - "document.createTextNode($1)" - js_createTextNode :: JSString -> IO DOMNode -foreign import javascript unsafe - "document.createComment($1)" - js_createComment :: JSString -> IO DOMNode -foreign import javascript unsafe - "$1.classList.add($2);" - js_classListAdd :: DOMElement -> JSString -> IO () -foreign import javascript unsafe - "$1.classList.remove($2);" - js_classListRemove :: DOMElement -> JSString -> IO () -foreign import javascript unsafe - "$1.nodeValue = $2;" - js_setTextValue :: DOMNode -> JSString -> IO () -foreign import javascript safe - "window.addEventListener('beforeunload', $1)" - js_onBeforeUnload :: JSVal -> IO () -foreign import javascript unsafe - "return window" - js_getCurrentWindow :: IO JSVal -foreign import javascript unsafe - "window.document" - js_getCurrentDocument :: IO JSVal -foreign import javascript unsafe - "window.document.body" - js_getCurrentBody :: IO JSVal -foreign import javascript unsafe - "for (;;){\ - if (!$2.previousSibling\ - || !$2.previousSibling.parentNode\ - || $2.previousSibling === $1\ - ) break;\ - $2.previousSibling.parentNode.removeChild($2.previousSibling);\ - }" - js_clearBoundary :: DOMNode -> DOMNode -> IO () -foreign import javascript unsafe - "if ($1.parentNode) $1.parentNode.removeChild($1);\ - if ($2.parentNode) $2.parentNode.removeChild($2);" - js_detachBoundary :: DOMNode -> DOMNode -> IO () -foreign import javascript unsafe - "div.innerHTML = $3;\ - var tempChilds = [];\ - for (var i = 0; i < div.childNodes.length; i++) {\ - tempChilds.push(div.childNodes[i]);\ - }\ - for (var j = 0; j < tempChilds.length; j++) {\ - div.removeChild(tempChilds[j]);\ - if ($2) {\ - $1.insertBefore(tempChilds[j], $2);\ - } else{\ - $1.appendChild(tempChilds[j]);\ - }\ - }" - js_unsafeInsertHtml :: DOMElement -> Nullable DOMNode -> JSString -> IO () -foreign import javascript interruptible - "if (document.readyState == 'loading') {\ - addEventListener('DOMContentLoaded', $c);\ - } else {\ - $c();\ - }" - js_waitDocumentLoad :: IO () -foreign import javascript unsafe - "$1[$2] = $3;" - js_setProp :: JSVal -> JSString -> JSVal -> IO () -foreign import javascript "wrapper" - js_dynExport1 :: (JSVal -> IO ()) -> IO JSVal -foreign import javascript safe - "$1.addEventListener($2, $3)" - js_addEventListener :: JSVal -> JSVal -> JSVal -> IO () -foreign import javascript safe - "$1.removeEventListener($2, $3)" - js_removeEventListener :: JSVal -> JSVal -> JSVal -> IO () -#endif - -instance (a ~ (), MonadIO m) => IsString (HtmlT m a) where - fromString s = do - HtmlEnv{html_current_element, html_content_boundary} <- ask - let jsstr = toJSString s - textNode <- liftIO $ js_createTextNode jsstr - case html_content_boundary of - Just b -> liftIO $ - js_insertBefore html_current_element textNode b.boundary_end - Nothing -> liftIO $ appendChild html_current_element textNode - {-# INLINE fromString #-} diff --git a/src/HtmlT/Element.hs b/src/HtmlT/Element.hs deleted file mode 100644 index 0987c9b..0000000 --- a/src/HtmlT/Element.hs +++ /dev/null @@ -1,403 +0,0 @@ -{-| -Shortcuts for most common HTML5 elements --} -module HtmlT.Element where - -import HtmlT.Base -import HtmlT.Types -import Wasm.Compat.Prim -import Data.Text - --- | This typeclass allows for tag constructors to have variable --- length arguments. Each tag constructor like 'div_' defined below --- can be called with one or two arguments --- --- > div_ $ text "A Div without attributes" --- > div_ [class_ "wrapper"] $ text "A Div with a class" --- --- Unceremoniously copied from the amazing @lucid@ library, see --- https://github.com/chrisdone/lucid/blob/fb3b0e7c189c2acd8d88838d4a13923f24542ee8/src/Lucid/Base.hs#L272 -class Term arg result | result -> arg where - term - :: Text -- ^ Name. - -> arg -- ^ Some argument. - -> result -- ^ Result: either an element or an attribute. - --- | Given attributes, expect more child input. -instance f ~ Html a => Term [Html ()] (f -> Html a) where - term name attrs = el name . (sequence_ attrs *>) - {-# INLINE term #-} - --- | Given children immediately, just use that and expect no --- attributes. -instance Term (Html a) (Html a) where - term = el - {-# INLINE term #-} - -div_ :: Term arg result => arg -> result -div_ = term "div" -{-# INLINE div_ #-} - -table_ :: Term arg result => arg -> result -table_ = term "table" -{-# INLINE table_ #-} - -thead_ :: Term arg result => arg -> result -thead_ = term "thead" -{-# INLINE thead_ #-} - -tbody_ :: Term arg result => arg -> result -tbody_ = term "tbody" -{-# INLINE tbody_ #-} - -tr_ :: Term arg result => arg -> result -tr_ = term "tr" -{-# INLINE tr_ #-} - -th_ :: Term arg result => arg -> result -th_ = term "th" -{-# INLINE th_ #-} - -td_ :: Term arg result => arg -> result -td_ = term "td" -{-# INLINE td_ #-} - -tfoot_ :: Term arg result => arg -> result -tfoot_ = term "tfoot" -{-# INLINE tfoot_ #-} - -section_ :: Term arg result => arg -> result -section_ = term "section" -{-# INLINE section_ #-} - -header_ :: Term arg result => arg -> result -header_ = term "header" -{-# INLINE header_ #-} - -footer_ :: Term arg result => arg -> result -footer_ = term "footer" -{-# INLINE footer_ #-} - -button_ :: Term arg result => arg -> result -button_ = term "button" -{-# INLINE button_ #-} - -form_ :: Term arg result => arg -> result -form_ = term "form" -{-# INLINE form_ #-} - -p_ :: Term arg result => arg -> result -p_ = term "p" -{-# INLINE p_ #-} - -s_ :: Term arg result => arg -> result -s_ = term "s" -{-# INLINE s_ #-} - -ul_ :: Term arg result => arg -> result -ul_ = term "ul" -{-# INLINE ul_ #-} - -span_ :: Term arg result => arg -> result -span_ = term "span" -{-# INLINE span_ #-} - -strong_ :: Term arg result => arg -> result -strong_ = term "strong" -{-# INLINE strong_ #-} - -li_ :: Term arg result => arg -> result -li_ = term "li" -{-# INLINE li_ #-} - -h1_ :: Term arg result => arg -> result -h1_ = term "h1" -{-# INLINE h1_ #-} - -h2_ :: Term arg result => arg -> result -h2_ = term "h2" -{-# INLINE h2_ #-} - -h3_ :: Term arg result => arg -> result -h3_ = term "h3" -{-# INLINE h3_ #-} - -h4_ :: Term arg result => arg -> result -h4_ = term "h4" -{-# INLINE h4_ #-} - -h5_ :: Term arg result => arg -> result -h5_ = term "h5" -{-# INLINE h5_ #-} - -h6_ :: Term arg result => arg -> result -h6_ = term "h6" -{-# INLINE h6_ #-} - -hr_ :: Term arg result => arg -> result -hr_ = term "hr" -{-# INLINE hr_ #-} - -pre_ :: Term arg result => arg -> result -pre_ = term "pre" -{-# INLINE pre_ #-} - -input_ :: Term arg result => arg -> result -input_ = term "input" -{-# INLINE input_ #-} - -label_ :: Term arg result => arg -> result -label_ = term "label" -{-# INLINE label_ #-} - -a_ :: Term arg result => arg -> result -a_ = term "a" -{-# INLINE a_ #-} - -details_ :: Term arg result => arg -> result -details_ = term "details" -{-# INLINE details_ #-} - -summary_ :: Term arg result => arg -> result -summary_ = term "summary" -{-# INLINE summary_ #-} - -menuitem_ :: Term arg result => arg -> result -menuitem_ = term "menuitem" -{-# INLINE menuitem_ #-} - -menu_ :: Term arg result => arg -> result -menu_ = term "menu" -{-# INLINE menu_ #-} - -fieldset_ :: Term arg result => arg -> result -fieldset_ = term "fieldset" -{-# INLINE fieldset_ #-} - -legend_ :: Term arg result => arg -> result -legend_ = term "legend" -{-# INLINE legend_ #-} - -datalist_ :: Term arg result => arg -> result -datalist_ = term "datalist" -{-# INLINE datalist_ #-} - -optgroup_ :: Term arg result => arg -> result -optgroup_ = term "optgroup" -{-# INLINE optgroup_ #-} - -progress_ :: Term arg result => arg -> result -progress_ = term "progress" -{-# INLINE progress_ #-} - -meter_ :: Term arg result => arg -> result -meter_ = term "meter" -{-# INLINE meter_ #-} - -center_ :: Term arg result => arg -> result -center_ = term "center" -{-# INLINE center_ #-} - -audio_ :: Term arg result => arg -> result -audio_ = term "audio" -{-# INLINE audio_ #-} - -video_ :: Term arg result => arg -> result -video_ = term "video" -{-# INLINE video_ #-} - -source_ :: Term arg result => arg -> result -source_ = term "source" -{-# INLINE source_ #-} - -track_ :: Term arg result => arg -> result -track_ = term "track" -{-# INLINE track_ #-} - -embed_ :: Term arg result => arg -> result -embed_ = term "embed" -{-# INLINE embed_ #-} - -object_ :: Term arg result => arg -> result -object_ = term "object" -{-# INLINE object_ #-} - -param_ :: Term arg result => arg -> result -param_ = term "param" -{-# INLINE param_ #-} - -ins_ :: Term arg result => arg -> result -ins_ = term "ins" -{-# INLINE ins_ #-} - -del_ :: Term arg result => arg -> result -del_ = term "del" -{-# INLINE del_ #-} - -small_ :: Term arg result => arg -> result -small_ = term "small" -{-# INLINE small_ #-} - -cite_ :: Term arg result => arg -> result -cite_ = term "cite" -{-# INLINE cite_ #-} - -dfn_ :: Term arg result => arg -> result -dfn_ = term "dfn" -{-# INLINE dfn_ #-} - -abbr_ :: Term arg result => arg -> result -abbr_ = term "abbr" -{-# INLINE abbr_ #-} - -time_ :: Term arg result => arg -> result -time_ = term "time" -{-# INLINE time_ #-} - -var_ :: Term arg result => arg -> result -var_ = term "var" -{-# INLINE var_ #-} - -samp_ :: Term arg result => arg -> result -samp_ = term "samp" -{-# INLINE samp_ #-} - -kbd_ :: Term arg result => arg -> result -kbd_ = term "kbd" -{-# INLINE kbd_ #-} - -caption_ :: Term arg result => arg -> result -caption_ = term "caption" -{-# INLINE caption_ #-} - -colgroup_ :: Term arg result => arg -> result -colgroup_ = term "colgroup" -{-# INLINE colgroup_ #-} - -col_ :: Term arg result => arg -> result -col_ = term "col" -{-# INLINE col_ #-} - -nav_ :: Term arg result => arg -> result -nav_ = term "nav" -{-# INLINE nav_ #-} - -article_ :: Term arg result => arg -> result -article_ = term "article" -{-# INLINE article_ #-} - -aside_ :: Term arg result => arg -> result -aside_ = term "aside" -{-# INLINE aside_ #-} - -address_ :: Term arg result => arg -> result -address_ = term "address" -{-# INLINE address_ #-} - -main_ :: Term arg result => arg -> result -main_ = term "main" -{-# INLINE main_ #-} - -body_ :: Term arg result => arg -> result -body_ = term "body" -{-# INLINE body_ #-} - -figure_ :: Term arg result => arg -> result -figure_ = term "figure" -{-# INLINE figure_ #-} - -figcaption_ :: Term arg result => arg -> result -figcaption_ = term "figcaption" -{-# INLINE figcaption_ #-} - -dl_ :: Term arg result => arg -> result -dl_ = term "dl" -{-# INLINE dl_ #-} - -dt_ :: Term arg result => arg -> result -dt_ = term "dt" -{-# INLINE dt_ #-} - -dd_ :: Term arg result => arg -> result -dd_ = term "dd" -{-# INLINE dd_ #-} - -img_ :: Term arg result => arg -> result -img_ = term "img" -{-# INLINE img_ #-} - -iframe_ :: Term arg result => arg -> result -iframe_ = term "iframe" -{-# INLINE iframe_ #-} - -canvas_ :: Term arg result => arg -> result -canvas_ = term "canvas" -{-# INLINE canvas_ #-} - -math_ :: Term arg result => arg -> result -math_ = term "math" -{-# INLINE math_ #-} - -select_ :: Term arg result => arg -> result -select_ = term "select" -{-# INLINE select_ #-} - -option_ :: Term arg result => arg -> result -option_ = term "option" -{-# INLINE option_ #-} - -textarea_ :: Term arg result => arg -> result -textarea_ = term "textarea" -{-# INLINE textarea_ #-} - -sub_ :: Term arg result => arg -> result -sub_ = term "sub" -{-# INLINE sub_ #-} - -sup_ :: Term arg result => arg -> result -sup_ = term "sup" -{-# INLINE sup_ #-} - -br_ :: Html () -br_ = el "br" blank -{-# INLINE br_ #-} - -ol_ :: Term arg result => arg -> result -ol_ = term "ol" -{-# INLINE ol_ #-} - -blockquote_ :: Term arg result => arg -> result -blockquote_ = term "blockquote" -{-# INLINE blockquote_ #-} - -code_ :: Term arg result => arg -> result -code_ = term "code" -{-# INLINE code_ #-} - -em_ :: Term arg result => arg -> result -em_ = term "em" -{-# INLINE em_ #-} - -i_ :: Term arg result => arg -> result -i_ = term "i" -{-# INLINE i_ #-} - -b_ :: Term arg result => arg -> result -b_ = term "b" -{-# INLINE b_ #-} - -u_ :: Term arg result => arg -> result -u_ = term "u" -{-# INLINE u_ #-} - -q_ :: Term arg result => arg -> result -q_ = term "q" -{-# INLINE q_ #-} - -script_ :: Term arg result => arg -> result -script_ = term "script" -{-# INLINE script_ #-} - -link_ :: Term arg result => arg -> result -link_ = term "link" -{-# INLINE link_ #-} diff --git a/src/HtmlT/Event.hs b/src/HtmlT/Event.hs deleted file mode 100644 index 731cabb..0000000 --- a/src/HtmlT/Event.hs +++ /dev/null @@ -1,475 +0,0 @@ -{-| - -This module offers clear and straightforward implementation of FRP -concepts such as Events and Dynamics, inspired by -Reflex. Additionally, it introduces DynRefs, which are represented by -a Dynamic along with a function to modify the value inside the -Dynamic. DynRef has similar inferface to IORef with functions like -readRef, writeRef, modifyRef etc. --} -module HtmlT.Event where - -import Control.Applicative -import Control.Monad -import Control.Monad.Catch -import Control.Monad.Fix -import Control.Monad.Reader -import Control.Monad.State -import Data.Foldable -import Data.IORef -import Data.Map (Map) -import Data.Map qualified as Map -import Data.Maybe -import Data.Set (Set) -import Data.Set qualified as Set -import Data.Tuple -import GHC.Exts -import GHC.Fingerprint -import GHC.Generics -import Unsafe.Coerce -import Data.List qualified as List -import Data.Function - -data ReactiveEnv = ReactiveEnv - { scope :: ReactiveScope - , reactive_state_ref :: IORef ReactiveState - } deriving (Generic) - -newReactiveEnv :: IO ReactiveEnv -newReactiveEnv = do - let scope = ReactiveScope emptyReactiveState.id_supply - reactive_state_ref <- newIORef emptyReactiveState - return ReactiveEnv {reactive_state_ref, scope} - -data ReactiveState = ReactiveState - { subscriptions :: Map EventId [(ReactiveScope, Any -> RI ())] - , scopes :: Map ReactiveScope ReactiveNode - , transaction_queue :: Map EventId (RI ()) - , id_supply :: Int - -- ^ Id supply for EventId and ReactiveScope - } deriving (Generic) - -emptyReactiveState :: ReactiveState -emptyReactiveState = ReactiveState - { subscriptions = Map.empty - , scopes = Map.empty - , transaction_queue = Map.empty - , id_supply = 0 - } - -newtype EventId = EventId { unEventId :: Int } - deriving newtype (Eq, Ord, Show, Num, Enum) - -newtype ReactiveScope = ReactiveScope { unReactiveScope :: Int } - deriving newtype (Show, Num, Ord, Eq) - --- | Represents a stream of event occurrences of type @a@. Its actual --- representation is simply a function that subscribes to the event -newtype Event a = Event { subscribe :: (a -> RI ()) -> RI () } - -instance Functor Event where - fmap f (Event s) = Event \k -> s . (. f) $ k - --- | Represens a value that changes over time. Provides operations for --- sampling the current value — 'readDyn' and for listening to future --- changes 'updates'. -data Dynamic a = Dynamic - { sample :: IO a - -- ^ Read current value held by Dynamic - , updates :: Event a - -- ^ Event fires every time value changes, carries the new value of - -- the Dynamic - } deriving stock Generic - -instance Functor Dynamic where - fmap f (Dynamic s u) = Dynamic (fmap f s) (fmap f u) - -instance Applicative Dynamic where - pure = constDyn - (<*>) = dynamicSplat - -dynamicSplat :: Dynamic (a -> b) -> Dynamic a -> Dynamic b -dynamicSplat df da = - let - updates = Event \k -> mdo - let - fire newF newA = defer queueId do - f <- liftIO $ maybe (readDyn df) pure newF - a <- liftIO $ maybe (readDyn da) pure newA - k (f a) - df.updates.subscribe \f -> fire (Just f) Nothing - da.updates.subscribe \a -> fire Nothing (Just a) - queueId <- EventId <$> reactive (const nextIntId) - return () - sample = liftA2 ($) df.sample da.sample - in - Dynamic {sample, updates} - --- | A mutable variable that allows for subscription to new values. It --- shares a similar API to 'IORef' (see 'readRef', 'writeRef', --- 'modifyRef') -data DynRef a = DynRef - { dynamic :: Dynamic a - -- ^ Holds the current value and an event that notifies about value - -- modifications - , modifier :: Modifier a - -- ^ Funtion to update the value - } deriving stock Generic - --- | Function that updates the value inside the 'DynRef' --- 'Bool' argument controls whether the modification should --- trigger an update event. It's possible to update the 'DynRef' --- without notifying the subscribers for optimization purposes, in --- cases when you know that all changes already been reflected in --- the DOM -newtype Modifier a = Modifier - { unModifier :: forall r. Bool -> (a -> (a, r)) -> RI r - } - -newtype ReactiveT m a = ReactiveT - { unReactiveT :: ReaderT ReactiveEnv m a - } - deriving newtype ( - Functor, Applicative, Monad, MonadIO, MonadFix, MonadCatch, MonadThrow, - MonadMask, MonadReader ReactiveEnv - ) - -instance MonadIO m => MonadReactive (ReactiveT m) where - reactive f = ReactiveT $ ReaderT $ \e -> - liftIO $ atomicModifyIORef' e.reactive_state_ref $ f e.scope - {-# INLINE reactive #-} - -type RI = ReactiveT IO - -type Callback a = a -> RI () - -type Subscriptions = Map EventId [(ReactiveScope, Any -> RI ())] - -type Finalizers = Map ReactiveScope ReactiveNode - -data ReactiveNode = ReactiveNode - { nodes :: [ReactiveScope] - , parent :: Maybe ReactiveScope - , finalizers :: [RI ()] - } deriving stock Generic - -freeScope :: ReactiveScope -> RI () -freeScope rscope = do - mRemovedNode <- reactive $ const $ freeScopeFn rscope - forM_ mRemovedNode \n -> do - sequence_ n.finalizers - forM_ n.nodes freeScope - -freeScopeFn :: ReactiveScope -> ReactiveState -> (ReactiveState, Maybe ReactiveNode) -freeScopeFn rscope s = - let - (mRemovedNode, scopes0) = Map.alterF (,Nothing) rscope $ s.scopes - removedParent = mRemovedNode >>= (.parent) - subscriptions = unsubscribe s.subscriptions - scopes = maybe scopes0 (unlinkParentScope scopes0) removedParent - in - ((s::ReactiveState) { subscriptions, scopes }, mRemovedNode) - where - unsubscribe :: Subscriptions -> Subscriptions - unsubscribe s = - let - removeCollectEmpty a k b = - let c = filterSubscriptions b - in (if List.null c then k:a else a, c) - (emptyKeys, s1) = Map.mapAccumWithKey removeCollectEmpty [] s - in - List.foldl' (flip Map.delete) s1 emptyKeys - - unlinkParentScope :: Finalizers -> ReactiveScope -> Finalizers - unlinkParentScope f r = - Map.alter (fmap (\n -> n { nodes = List.filter (/=rscope) n.nodes })) r f - - filterSubscriptions [] = [] - filterSubscriptions ((s, c):xs) | s == rscope = xs - | otherwise = (s, c) : filterSubscriptions xs - -unsafeSubscribeFn :: EventId -> (a -> RI ()) -> ReactiveScope -> ReactiveState -> ReactiveState -unsafeSubscribeFn eid k rs s = - let - insertSubscription (Just xs) = Just $ (rs, k . unsafeCoerce):xs - insertSubscription Nothing = Just [(rs, k . unsafeCoerce)] - in - s {subscriptions = Map.alter insertSubscription eid s.subscriptions } - -unsafeSubscribe :: EventId -> (a -> RI ()) -> RI () -unsafeSubscribe eid k = reactive_ (unsafeSubscribeFn eid k) - -installFinalizerFn :: RI () -> ReactiveScope -> ReactiveState -> ReactiveState -installFinalizerFn fin rs s = - let - insertFin (Just n) = Just $ n { finalizers = fin : n.finalizers} - insertFin Nothing = Nothing - in - s {scopes = Map.alter insertFin rs s.scopes } - -installFinalizer :: RI () -> RI () -installFinalizer fin = reactive_ (installFinalizerFn fin) - -unsafeTrigger :: EventId -> a -> RI () -unsafeTrigger eid a = do - defer eid do - callbacks <- reactive \_ s -> - (s, s.subscriptions & Map.lookup eid & fromMaybe []) - forM_ callbacks $ ($ unsafeCoerce @_ @Any a) . snd - -newReactiveScopeFn :: ReactiveScope -> ReactiveState -> (ReactiveState, ReactiveScope) -newReactiveScopeFn parent s0 = - let - (s1, intId) = nextIntId s0 - rscope = ReactiveScope intId - scopes = Map.insert rscope (ReactiveNode [] (Just parent) []) s1.scopes - in - (s1 {scopes}, rscope) - -newReactiveScope :: RI ReactiveScope -newReactiveScope = reactive newReactiveScopeFn - --- | Defers a computation (typically an event firing) until the end of --- the current reactive transaction. This allows for the avoidance of --- double firing of events constructed from multiple other events. -defer :: EventId -> RI () -> RI () -defer k act = reactive_ \_ s -> s {transaction_queue = Map.insert k act s.transaction_queue} - -newEvent :: RI (Event a, a -> RI ()) -newEvent = reactive \_ s0 -> - let - (s1, eventId) = nextIntId s0 - event = Event $ unsafeSubscribe $ EventId eventId - trig = unsafeTrigger $ EventId eventId - in - (s1, (event, trig)) - -newRef :: a -> RI (DynRef a) -newRef initial = do - ioRef <- liftIO $ newIORef initial - (event, push) <- newEvent - let - modifier = Modifier \u f -> do - (new, result) <- liftIO $ atomicModifyIORef' ioRef \old -> - let (new, result) = f old in - (new, (new, result)) - when u $ push new - return result - dynamic = Dynamic (readIORef ioRef) event - return DynRef {dynamic, modifier} - --- | Create a Dynamic that never changes its value -constDyn :: a -> Dynamic a -constDyn a = Dynamic (pure a) never - --- | Event that will never fire -never :: Event a -never = Event \ _ -> return () - --- | Write new value into a 'DynRef' --- --- > ref <- newRef "Initial dynamic" --- > transactionWrite ref "New dynamic" --- > readRef ref --- "New dynamic" -writeRef :: DynRef a -> a -> RI () -writeRef ref a = modifyRef ref (const a) - --- | Read the current value held by given 'DynRef' --- --- > ref <- newRef "Hello there!" --- > readRef ref --- "Hello there!" -readRef :: MonadIO m => DynRef a -> m a -readRef = readDyn . (.dynamic) - --- | Update a 'DynRef' by applying given function to the current value --- --- > ref <- newRef [1..3] --- > modifyRef ref $ fmap (*2) --- [2, 4, 6] -modifyRef :: DynRef a -> (a -> a) -> RI () -modifyRef (DynRef _ (Modifier mod)) f = mod True $ (,()) . f - --- | Update a 'DynRef' with first field of the tuple and return back --- the second field. The name is intended to be similar to --- 'atomicModifyIORef' but there are no atomicity guarantees --- whatsoever -atomicModifyRef :: DynRef a -> (a -> (a, r)) -> RI r -atomicModifyRef (DynRef _ (Modifier mod)) f = mod True f - --- | Extract a 'Dynamic' out of 'DynRef' -fromRef :: DynRef a -> Dynamic a -fromRef = (.dynamic) - --- | Read the dynamic held by a 'Dynamic' -readDyn :: MonadIO m => Dynamic a -> m a -readDyn = liftIO . (.sample) - --- | Executes an action currently held inside the 'Dynamic' and every --- time the dynamic changes. -performDyn :: Dynamic (RI ()) -> RI () -performDyn d = do - join $ liftIO d.sample - d.updates.subscribe id - --- | Return a 'Dynamic' for which updates only fire when the value --- actually changes according to Eq instance -holdUniqDyn :: Eq a => Dynamic a -> Dynamic a -holdUniqDyn = holdUniqDynBy (==) -{-# INLINE holdUniqDyn #-} - --- | Same as 'holdUniqDyn' but accepts arbitrary equality test --- function -holdUniqDynBy :: (a -> a -> Bool) -> Dynamic a -> Dynamic a -holdUniqDynBy equalFn da = - let - updates = Event \k -> do - old <- liftIO da.sample - oldRef <- liftIO $ newIORef old - da.updates.subscribe \new -> do - old <- liftIO $ atomicModifyIORef' oldRef (new,) - unless (old `equalFn` new) $ k new - in - Dynamic {sample = da.sample, updates} - --- | Produce a new Dynamic by applying a function to both the source --- (Dynamic a) and previous value of itself -foldDynMaybe :: (a -> b -> Maybe b) -> b -> Dynamic a -> RI (Dynamic b) -foldDynMaybe f initB dynA = do - initA <- liftIO dynA.sample - refB <- newRef $ fromMaybe initB $ f initA initB - dynA.updates.subscribe \newA -> do - oldB <- liftIO refB.dynamic.sample - forM_ (f newA oldB) $ writeRef refB - return refB.dynamic - -nextIntId :: ReactiveState -> (ReactiveState, Int) -nextIntId s = (s {id_supply = succ s.id_supply}, s.id_supply) - --- | Alternative version if 'fmap' where given function will only be --- called once every time 'Dynamic a' value changes, whereas in 'fmap' --- it would be called once for each subscription per change event. As --- a general guideline, if the function @f@ is inexpensive, choose --- @fmap f@. Otherwise, consider using @mapDyn f@. -mapDyn :: (a -> b) -> Dynamic a -> RI (Dynamic b) -mapDyn fun da = do - initialA <- liftIO $ da.sample - latestA <- liftIO $ newIORef initialA - latestB <- liftIO $ newIORef (fun initialA) - eventId <- EventId <$> reactive (const nextIntId) - let - updates = Event (unsafeSubscribe eventId) - fire = defer eventId do - newB <- liftIO $ fun <$> readIORef latestA - liftIO $ writeIORef latestB newB - unsafeTrigger eventId newB - da.updates.subscribe \newA -> do - liftIO $ writeIORef latestA newA - defer eventId fire - return $ Dynamic (readIORef latestB) updates - -mapDyn2 :: (a -> b -> c) -> Dynamic a -> Dynamic b -> RI (Dynamic c) -mapDyn2 fun da db = do - initialA <- liftIO $ da.sample - initialB <- liftIO $ db.sample - latestA <- liftIO $ newIORef initialA - latestB <- liftIO $ newIORef initialB - latestC <- liftIO $ newIORef (fun initialA initialB) - eventId <- EventId <$> reactive (const nextIntId) - let - updates = Event (unsafeSubscribe eventId) - fire = defer eventId do - newC <- liftIO $ fun <$> (readIORef latestA) <*> (readIORef latestB) - liftIO $ writeIORef latestC newC - unsafeTrigger eventId newC - da.updates.subscribe \newA -> do - liftIO $ writeIORef latestA newA - defer eventId fire - db.updates.subscribe \newB -> do - liftIO $ writeIORef latestB newB - defer eventId fire - return $ Dynamic (readIORef latestC) updates - --- | Takes a list of Dynamics and a function to generate the --- output. The positions of elements in the list of [Any] received by --- the function always correspond to the positions of [Dynamic Any] --- from which these values were generated. The Dynamic created by this --- function will fire at most once per transaction, and only if any of --- the input Dynamics change their values. -unsafeMapDynN - :: ([Any] -> IO a) - -- ^ Construct the output value, from list of input values from - -- corresponding positions of given Dynamics - -> [Dynamic Any] - -- ^ List of input Dynamics - -> RI (Dynamic a) -unsafeMapDynN fun dyns = do - initialInputs <- liftIO $ mapM (.sample) dyns - initialOutput <- liftIO $ fun initialInputs - latestInputsRef <- liftIO $ newIORef initialInputs - latestOutputRef <- liftIO $ newIORef initialOutput - eventId <- EventId <$> reactive (const nextIntId) - let - fire = defer eventId do - newOutput <- liftIO $ fun =<< readIORef latestInputsRef - liftIO $ writeIORef latestOutputRef newOutput - unsafeTrigger eventId newOutput - updates = Event $ unsafeSubscribe eventId - updateList _ _ [] = [] - updateList 0 a (_:xs) = a:xs - updateList n a (x:xs) = x : updateList (pred n) a xs - forM_ (zip [0..] dyns) \(i::Int, adyn) -> do - adyn.updates.subscribe \newVal -> do - liftIO $ modifyIORef latestInputsRef $ updateList i newVal - defer eventId fire - return $ Dynamic (readIORef latestOutputRef) updates - -type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s - --- | Apply a lens to the value inside 'DynRef' -lensMap :: forall s a. Lens' s a -> DynRef s -> DynRef a -lensMap l s = - let - dynamic = Dynamic - (fmap (getConst . l Const) s.dynamic.sample) - (fmap (getConst . l Const) s.dynamic.updates) - modifier = Modifier \u f -> - unModifier s.modifier u $ swap . l (swap . f) - in - DynRef {dynamic, modifier} - --- | Loop until transaction_queue is empty -trampoline :: RI a -> RI a -trampoline act = loop0 act where - loop0 :: RI a -> RI a - loop0 before = do - r <- before - mcont <- popQueue - forM_ mcont loop1 - return r - loop1 :: RI () -> RI () - loop1 before = do - before - mcont <- popQueue - forM_ mcont loop1 - popQueue :: RI (Maybe (RI ())) - popQueue = reactive \_ s -> - case Map.minViewWithKey s.transaction_queue of - Nothing -> (s, Nothing) - Just ((_, r), newQueue) -> (s {transaction_queue = newQueue}, Just r) - -launchReactiveT :: ReactiveEnv -> RI a -> IO a -launchReactiveT e = execReactiveT e . trampoline - -execReactiveT :: ReactiveEnv -> ReactiveT m a -> m a -execReactiveT e = flip runReaderT e . unReactiveT - -runReactiveT :: ReactiveT m a -> ReactiveEnv -> m a -runReactiveT = flip execReactiveT - -class MonadReactive m where - reactive :: (ReactiveScope -> ReactiveState -> (ReactiveState, a)) -> m a - -reactive_ :: MonadReactive m => (ReactiveScope -> ReactiveState -> ReactiveState) -> m () -reactive_ f = reactive (\r s -> (,()) $ f r s) diff --git a/src/HtmlT/Internal.hs b/src/HtmlT/Internal.hs deleted file mode 100644 index 0fab4e4..0000000 --- a/src/HtmlT/Internal.hs +++ /dev/null @@ -1,44 +0,0 @@ -module HtmlT.Internal where - -import Control.Monad.Reader -import GHC.Generics - -import HtmlT.Event -import HtmlT.Types -import HtmlT.DOM - --- | Auxiliary type helps to implement 'simpleList' -data ElemEnv a = ElemEnv - { ee_html_env :: HtmlEnv - , ee_reactive_env :: ReactiveEnv - , ee_dyn_ref :: DynRef a - } deriving Generic - --- | Insert given node to @html_current_element@ and run action with --- inserted node as a new root -appendHtmlT :: MonadIO m => DOMElement -> HtmlT m a -> HtmlT m a -appendHtmlT newRootEl html = do - result <- local (\env -> env - { html_current_element = newRootEl - , html_content_boundary = Nothing }) html - result <$ insertNode (nodeFromElement newRootEl) - --- | Insert new node to the end of current boundary -insertNode :: MonadIO m => DOMNode -> HtmlT m () -insertNode n = do - rootEl <- asks html_current_element - boundary <- asks html_content_boundary - case boundary of - Just b -> liftIO $ - js_insertBefore rootEl n b.boundary_end - Nothing -> liftIO $ appendChild rootEl n - --- | Insert two DOM Comment nodes intended to be used as a boundary for --- dynamic content. -insertBoundary :: MonadIO m => HtmlT m ContentBoundary -insertBoundary = do - boundary_begin <- liftIO $ createComment "ContentBoundary {{" - boundary_end <- liftIO $ createComment "}}" - insertNode boundary_begin - insertNode boundary_end - return ContentBoundary {boundary_begin, boundary_end} diff --git a/src/HtmlT/Main.hs b/src/HtmlT/Main.hs deleted file mode 100644 index 2bba32b..0000000 --- a/src/HtmlT/Main.hs +++ /dev/null @@ -1,74 +0,0 @@ --- | Start and stop browser application -module HtmlT.Main where - -import GHC.Generics -import HtmlT.DOM -import HtmlT.Event -import HtmlT.Types - -data AttachOptions = AttachOptions - { reactive_env :: ReactiveEnv - -- ^ Typically the program should only have one instance of - -- 'ReactiveEnv', so when there are multiple running 'HtmlT' - -- applications, use this field to share existing 'ReactiveEnv' - -- between all of them - , root_element :: DOMElement - -- ^ HTMLElement where to attach the elements created by the - -- application - , wait_document_load :: Bool - -- ^ If True block IO action until main document is fully loaded - , unload_call_finalizers :: Bool - -- ^ If True run finalizers on @beforeunload@ event. This happens - -- just before browser tab is closed, the code in finalizers should - -- only consist of non-blocking IO - } deriving Generic - --- | Needed to manually finalize and detach the application -data RunningApp = RunningApp - { runapp_html_env :: HtmlEnv - , runapp_reactive_env :: ReactiveEnv - , runapp_boundary :: ContentBoundary - } deriving Generic - --- | Start 'HtmlT' application applying customizations described by --- AttachOptions argument -attachWithOptions :: AttachOptions -> Html a -> IO (a, RunningApp) -attachWithOptions opt app = mdo - -- TODO: doesn't work with javascript-backend - -- when wait_document_load - -- js_waitDocumentLoad - begin <- createComment "ContentBoundary {{" - end <- createComment "}}" - appendChild opt.root_element begin - appendChild opt.root_element end - reactiveEnv <- newReactiveEnv - let - boundary = ContentBoundary begin end - htmlEnv = HtmlEnv - { html_current_element = opt.root_element - , html_content_boundary = Just boundary - } - runApp = RunningApp htmlEnv reactiveEnv boundary - result <- launchReactiveT reactiveEnv $ execHtmlT htmlEnv app - -- when opt.unload_call_finalizers $ onBeforeUnload $ do - -- finalizers <- readIORef $ renv_finalizers reactive_env - -- applyFinalizer reactive_env finalizers - return (result, runApp) - --- | Start the application and attach it to the given HTMLElement -attachTo :: DOMElement -> Html a -> IO (a, RunningApp) -attachTo root html = do - renv <- newReactiveEnv - attachWithOptions (AttachOptions renv root True True) html - --- | Start the application and attach it to current element -attachToBody :: Html a -> IO (a, RunningApp) -attachToBody html = do - body <- getCurrentBody - attachTo body html - --- | Run finalizers and detach created elements from the DOM -detach :: RunningApp -> IO () -detach app = do - launchReactiveT app.runapp_reactive_env $ freeScope app.runapp_reactive_env.scope - removeBoundary app.runapp_boundary diff --git a/src/HtmlT/Property.hs b/src/HtmlT/Property.hs deleted file mode 100644 index 40cbea5..0000000 --- a/src/HtmlT/Property.hs +++ /dev/null @@ -1,368 +0,0 @@ -{-| -Shortcuts for common HTML5 attributes and properties --} -module HtmlT.Property where - -import HtmlT.Base -import HtmlT.Event -import HtmlT.Types -import Data.Text -import Wasm.Compat.Prim - - --- TODO: Real-world usage has demonstrated that 'dynStyles' not --- sufficiently composable. For instance, if 'dynStyles' is used to --- set the CSS color for an element, essentially no other CSS property --- can be applied to this element, as they will be overwritten by --- 'dynStyles'. -dynStyles :: Dynamic Text -> Html () -dynStyles = dynProp "style" -{-# INLINE dynStyles #-} - -dynValue :: Dynamic Text -> Html () -dynValue = dynProp "value" -{-# INLINE dynValue #-} - -dynClass :: Dynamic Text -> Html () -dynClass = dynProp "className" -{-# INLINE dynClass #-} - -dynChecked :: Dynamic Bool -> Html () -dynChecked = dynProp "checked" -{-# INLINE dynChecked #-} - -dynDisabled :: Dynamic Bool -> Html () -dynDisabled = dynProp "disabled" -{-# INLINE dynDisabled #-} - -title_ :: Text -> Html () -title_ = prop "title" -{-# INLINE title_ #-} - -selected_ :: Bool -> Html () -selected_ = prop "selected" -{-# INLINE selected_ #-} - -hidden_ :: Bool -> Html () -hidden_ = prop "hidden" -{-# INLINE hidden_ #-} - -value_ :: Text -> Html () -value_ = prop "value" -{-# INLINE value_ #-} - -defaultValue_ :: Text -> Html () -defaultValue_ = prop "defaultValue" -{-# INLINE defaultValue_ #-} - -accept_ :: Text -> Html () -accept_ = prop "accept" -{-# INLINE accept_ #-} - -acceptCharset_ :: Text -> Html () -acceptCharset_ = prop "acceptCharset" -{-# INLINE acceptCharset_ #-} - -action_ :: Text -> Html () -action_ = prop "action" -{-# INLINE action_ #-} - -autocomplete_ :: Bool -> Html () -autocomplete_ b = prop @Text "autocomplete" (if b then "on" else "off") -{-# INLINE autocomplete_ #-} - -autosave_ :: Text -> Html () -autosave_ = prop "autosave" -{-# INLINE autosave_ #-} - -disabled_ :: Bool -> Html () -disabled_ = prop "disabled" -{-# INLINE disabled_ #-} - -enctype_ :: Text -> Html () -enctype_ = prop "enctype" -{-# INLINE enctype_ #-} - -formation_ :: Text -> Html () -formation_ = prop "formation" -{-# INLINE formation_ #-} - -list_ :: Text -> Html () -list_ = prop "list" -{-# INLINE list_ #-} - -maxlength_ :: Text -> Html () -maxlength_ = prop "maxlength" -{-# INLINE maxlength_ #-} - -minlength_ :: Text -> Html () -minlength_ = prop "minlength" -{-# INLINE minlength_ #-} - -method_ :: Text -> Html () -method_ = prop "method" -{-# INLINE method_ #-} - -multiple_ :: Bool -> Html () -multiple_ = prop "multiple" -{-# INLINE multiple_ #-} - -novalidate_ :: Bool -> Html () -novalidate_ = prop "noValidate" -{-# INLINE novalidate_ #-} - -pattern_ :: Text -> Html () -pattern_ = prop "pattern" -{-# INLINE pattern_ #-} - -readonly_ :: Bool -> Html () -readonly_ = prop "readOnly" -{-# INLINE readonly_ #-} - -required_ :: Bool -> Html () -required_ = prop "required" -{-# INLINE required_ #-} - -size_ :: Text -> Html () -size_ = prop "size" -{-# INLINE size_ #-} - -forProp_ :: Text -> Html () -forProp_ = prop "for" -{-# INLINE forProp_ #-} - -ref_ :: Text -> Html () -ref_ = prop "ref" -{-# INLINE ref_ #-} - -formProp_ :: Text -> Html () -formProp_ = prop "form" -{-# INLINE formProp_ #-} - -max_ :: Text -> Html () -max_ = prop "max" -{-# INLINE max_ #-} - -min_ :: Text -> Html () -min_ = prop "min" -{-# INLINE min_ #-} - -step_ :: Text -> Html () -step_ = prop "step" -{-# INLINE step_ #-} - -cols_ :: Text -> Html () -cols_ = prop "cols" -{-# INLINE cols_ #-} - -rows_ :: Text -> Html () -rows_ = prop "rows" -{-# INLINE rows_ #-} - -wrap_ :: Text -> Html () -wrap_ = prop "wrap" -{-# INLINE wrap_ #-} - -target_ :: Text -> Html () -target_ = prop "target" -{-# INLINE target_ #-} - -download_ :: Text -> Html () -download_ = prop "download" -{-# INLINE download_ #-} - -downloadAs_ :: Text -> Html () -downloadAs_ = prop "downloadAs" -{-# INLINE downloadAs_ #-} - -hreflang_ :: Text -> Html () -hreflang_ = prop "hreflang" -{-# INLINE hreflang_ #-} - -media_ :: Text -> Html () -media_ = prop "media" -{-# INLINE media_ #-} - -ping_ :: Text -> Html () -ping_ = prop "ping" -{-# INLINE ping_ #-} - -rel_ :: Text -> Html () -rel_ = prop "rel" -{-# INLINE rel_ #-} - -ismap_ :: Text -> Html () -ismap_ = prop "ismap" -{-# INLINE ismap_ #-} - -usemap_ :: Text -> Html () -usemap_ = prop "usemap" -{-# INLINE usemap_ #-} - -shape_ :: Text -> Html () -shape_ = prop "shape" -{-# INLINE shape_ #-} - -coords_ :: Text -> Html () -coords_ = prop "coords" -{-# INLINE coords_ #-} - -src_ :: Text -> Html () -src_ = prop "src" -{-# INLINE src_ #-} - -height_ :: Text -> Html () -height_ = prop "height" -{-# INLINE height_ #-} - -width_ :: Text -> Html () -width_ = prop "width" -{-# INLINE width_ #-} - -alt_ :: Text -> Html () -alt_ = prop "alt" -{-# INLINE alt_ #-} - -autoplay_ :: Bool -> Html () -autoplay_ = prop "autoplay" -{-# INLINE autoplay_ #-} - -controls_ :: Bool -> Html () -controls_ = prop "controls" -{-# INLINE controls_ #-} - -loop_ :: Bool -> Html () -loop_ = prop "loop" -{-# INLINE loop_ #-} - -preload_ :: Text -> Html () -preload_ = prop "preload" -{-# INLINE preload_ #-} - -poster_ :: Text -> Html () -poster_ = prop "poster" -{-# INLINE poster_ #-} - -default_ :: Bool -> Html () -default_ = prop "default" -{-# INLINE default_ #-} - -kind_ :: Text -> Html () -kind_ = prop "kind" -{-# INLINE kind_ #-} - -srclang_ :: Text -> Html () -srclang_ = prop "srclang" -{-# INLINE srclang_ #-} - -sandbox_ :: Text -> Html () -sandbox_ = prop "sandbox" -{-# INLINE sandbox_ #-} - -seamless_ :: Text -> Html () -seamless_ = prop "seamless" -{-# INLINE seamless_ #-} - -srcdoc_ :: Text -> Html () -srcdoc_ = prop "srcdoc" -{-# INLINE srcdoc_ #-} - -reversed_ :: Text -> Html () -reversed_ = prop "reversed" -{-# INLINE reversed_ #-} - -start_ :: Text -> Html () -start_ = prop "start" -{-# INLINE start_ #-} - -align_ :: Text -> Html () -align_ = prop "align" -{-# INLINE align_ #-} - -colspan_ :: Text -> Html () -colspan_ = attr "colspan" -{-# INLINE colspan_ #-} - -rowspan_ :: Text -> Html () -rowspan_ = attr "rowspan" -{-# INLINE rowspan_ #-} - -headers_ :: Text -> Html () -headers_ = prop "headers" -{-# INLINE headers_ #-} - -scope_ :: Text -> Html () -scope_ = prop "scope" -{-# INLINE scope_ #-} - -async_ :: Text -> Html () -async_ = prop "async" -{-# INLINE async_ #-} - -charset_ :: Text -> Html () -charset_ = prop "charset" -{-# INLINE charset_ #-} - -content_ :: Text -> Html () -content_ = prop "content" -{-# INLINE content_ #-} - -defer_ :: Text -> Html () -defer_ = prop "defer" -{-# INLINE defer_ #-} - -httpEquiv_ :: Text -> Html () -httpEquiv_ = prop "httpEquiv" -{-# INLINE httpEquiv_ #-} - -language_ :: Text -> Html () -language_ = prop "language" -{-# INLINE language_ #-} - -scoped_ :: Text -> Html () -scoped_ = prop "scoped" -{-# INLINE scoped_ #-} - -type_ :: Text -> Html () -type_ = prop "type" -{-# INLINE type_ #-} - -name_ :: Text -> Html () -name_ = prop "name" -{-# INLINE name_ #-} - -href_ :: Text -> Html () -href_ = prop "href" -{-# INLINE href_ #-} - -id_ :: Text -> Html () -id_ = prop "id" -{-# INLINE id_ #-} - -placeholder_ :: Text -> Html () -placeholder_ = prop "placeholder" -{-# INLINE placeholder_ #-} - -checked_ :: Bool -> Html () -checked_ = prop "checked" -{-# INLINE checked_ #-} - -autofocus_ :: Bool -> Html () -autofocus_ = prop "autofocus" -{-# INLINE autofocus_ #-} - -class_ :: Text -> Html () -class_ = prop "className" -{-# INLINE class_ #-} - -data_ :: Text -> Text -> Html () -data_ k v = prop @Text ("data-" <> k) v -{-# INLINE data_ #-} - -role_ :: Text -> Html () -role_ = attr "role" -{-# INLINE role_ #-} - -style_ :: Text -> Html () -style_ = prop "style" -{-# INLINE style_ #-} diff --git a/src/HtmlT/Types.hs b/src/HtmlT/Types.hs deleted file mode 100644 index 9495a53..0000000 --- a/src/HtmlT/Types.hs +++ /dev/null @@ -1,71 +0,0 @@ -module HtmlT.Types where - -import Control.Monad.Catch -import Control.Monad.Reader -import Data.Coerce -import Data.String -import GHC.Generics -import HtmlT.Event -import Data.Text -import Control.Monad.Fix - -import Wasm.Compat.Prim - --- | HtmlT is nothing more than just a newtype over ReaderT HtmlEnv -newtype HtmlT m a = HtmlT {unHtmlT :: ReaderT HtmlEnv m a} - deriving newtype ( - Functor, Applicative, Monad, MonadIO, MonadReader HtmlEnv, - MonadFix, MonadCatch, MonadThrow, MonadMask, MonadTrans - ) - -data HtmlEnv = HtmlEnv - { html_current_element :: DOMElement - -- ^ A DOMElement that will be used as a parent to insert new - -- content, attributes, properties, listeners etc. - , html_content_boundary :: Maybe ContentBoundary - -- ^ Boundary defined by parent scope where new content should be - -- attached, when Nothing whole parent element is available - } deriving Generic - -type Html = HtmlT RI - --- | A newtype over JSVal which is an instance of Node --- https://developer.mozilla.org/en-US/docs/Web/API/Node -newtype DOMNode = DOMNode {unDOMNode :: JSVal} - --- | A newtype over JSVal which is an instance of HTMLElement --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement -newtype DOMElement = DOMElement {unDOMElement :: JSVal} - --- | A newtype over JSVal which is an instance of Event --- https://developer.mozilla.org/en-US/docs/Web/API/Event -newtype DOMEvent = DOMEvent {unDOMEvent :: JSVal} - --- | See https://developer.mozilla.org/en-US/docs/Web/Events for --- reference, what events are supported by particular elements -newtype EventName = EventName {unEventName :: JSString} - -instance IsString EventName where fromString = EventName . toJSString - --- | Two comment nodes that define a boundary and a placeholder to --- insert additional nodes within the DOM. -data ContentBoundary = ContentBoundary - { boundary_begin :: DOMNode - , boundary_end :: DOMNode - } deriving Generic - --- | Each DOMElement is also a valid DOMNode -nodeFromElement :: DOMElement -> DOMNode -nodeFromElement = coerce - -runHtmlT :: HtmlT m a -> HtmlEnv -> m a -runHtmlT h = runReaderT (unHtmlT h) - -execHtmlT :: HtmlEnv -> HtmlT m a -> m a -execHtmlT = flip runHtmlT - -instance (Semigroup a, Applicative m) => Semigroup (HtmlT m a) where - (<>) = liftA2 (<>) - -instance (Monoid a, Applicative m) => Monoid (HtmlT m a) where - mempty = HtmlT $ ReaderT \_ -> pure mempty diff --git a/src/HtmlT/Sketch.hs b/src/Sketch.hs similarity index 92% rename from src/HtmlT/Sketch.hs rename to src/Sketch.hs index 618d1ee..345fe4d 100644 --- a/src/HtmlT/Sketch.hs +++ b/src/Sketch.hs @@ -1,4 +1,4 @@ -module HtmlT.Sketch where +module Sketch where import Control.Monad import Control.Monad.Identity @@ -19,7 +19,7 @@ import GHC.Generics import GHC.Exts hiding (build) import GHC.TypeLits -import HtmlT.Sketch.FFI +import Sketch.FFI import Wasm.Compat.Prim -------------------------- @@ -324,12 +324,37 @@ attach s html = mdo plan <- build mod layout s body [] return res +--------------------------- +-- INCREMENTAL VARIABLES -- +--------------------------- + +data IncVar t a where + TipVar :: RefId -> IORef a -> IncVar '[] a + LensMapVar :: IncOptic s a -> IncVar t a + MapVar :: (s -> a) -> IncVar '[ 'GetterConstraint] a + +type RefId = Int + +data VarConstraint = GetterConstraint + ------------------------------- -- REATIVE STUFF RESURRECTED -- ------------------------------- -data IncRef t a where - TipRef :: RefId -> IORef a -> IncRef t a - MapRef :: IncOptic s a -> IncRef t a +data RunningState = RunningState + { sync_plan :: [(ScopeId, RefId, Any -> IO ())] + , finalizers :: [(ScopeId, RefId, Any -> IO ())] + } deriving (Generic) -type RefId = Int +type EventId = Int + +data ScopeId + = RootScope + | BranchScope ScopeId Int + deriving (Eq, Ord, Show) + +data ScopeNode = ScopeNode + { nodes :: [ScopeId] + , parent :: Maybe ScopeId + , finalizers :: [IO ()] + } deriving stock Generic diff --git a/src/HtmlT/Sketch/FFI.hs b/src/Sketch/FFI.hs similarity index 99% rename from src/HtmlT/Sketch/FFI.hs rename to src/Sketch/FFI.hs index d307e5d..4872d82 100644 --- a/src/HtmlT/Sketch/FFI.hs +++ b/src/Sketch/FFI.hs @@ -6,7 +6,7 @@ #if defined(wasm32_HOST_ARCH) {-# LANGUAGE JavaScriptFFI #-} #endif -module HtmlT.Sketch.FFI where +module Sketch.FFI where import Control.Monad.IO.Class import Wasm.Compat.Prim From 9e65e31337e06eb100b283b252f2f55d909f4327 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sat, 23 Mar 2024 02:36:49 +0400 Subject: [PATCH 11/64] WIP --- default.nix | 8 +- examples/charts/App.hs | 20 +- examples/charts/Charts.hs | 65 +++--- examples/charts/PairSelector.hs | 20 +- examples/charts/charts.hs | 6 +- htmlt.cabal | 5 +- jsbits/jsffi.js | 16 +- src/Clickable.hs | 299 +++++++++++++++++++++++++ src/{Sketch => Clickable}/FFI.hs | 60 +++++- src/Sketch.hs | 360 ------------------------------- 10 files changed, 428 insertions(+), 431 deletions(-) create mode 100644 src/Clickable.hs rename src/{Sketch => Clickable}/FFI.hs (68%) delete mode 100644 src/Sketch.hs diff --git a/default.nix b/default.nix index 24f33c8..f4859f6 100644 --- a/default.nix +++ b/default.nix @@ -22,10 +22,10 @@ let # th-compat = self.callCabal2nix "th-compat" ./packages/th-compat {}; tagged = self.callCabal2nix "tagged" ../fullstack-app/packages/tagged {}; - th-abstraction = self.callCabal2nix "th-abstraction" ./packages/th-abstraction {}; - vector = self.callCabal2nix "vector" ./packages/vector/vector {}; - vector-stream = self.callCabal2nix "vector-stream" ./packages/vector/vector-stream {}; - unordered-containers = self.callCabal2nix "unordered-containers" ./packages/unordered-containers {}; + th-abstraction = self.callCabal2nix "th-abstraction" ../fullstack-app/packages/th-abstraction {}; + vector = self.callCabal2nix "vector" ../fullstack-app/packages/vector/vector {}; + vector-stream = self.callCabal2nix "vector-stream" ../fullstack-app/packages/vector/vector-stream {}; + unordered-containers = self.callCabal2nix "unordered-containers" ../fullstack-app/packages/unordered-containers {}; # text-short = self.callCabal2nix "text-short" ./packages/text-short {}; generic-deriving = doJailbreak super.generic-deriving; bifunctors = doJailbreak super.bifunctors; diff --git a/examples/charts/App.hs b/examples/charts/App.hs index c2c92cf..090a71f 100644 --- a/examples/charts/App.hs +++ b/examples/charts/App.hs @@ -6,25 +6,25 @@ import Data.Proxy import Data.Text (Text) import Data.Text qualified as Text import GHC.Generics -import Sketch -import Sketch.FFI +import Clickable +import Clickable.FFI -data AppState = AppState - { charts_instance :: Charts.ChartState - } deriving (Show, Eq, Generic) +data AppInstance = AppInstance + { charts_instance :: Charts.ChartInstance + } deriving (Generic) -new :: IO AppState +new :: ClickM AppInstance new = do charts_instance <- Charts.new - return AppState + return AppInstance { charts_instance } -html :: BuilderM AppState () -html = do +html :: AppInstance -> HtmlM () +html self = do el "style" [] $ text styles - embedFld @"charts_instance" Charts.html + Charts.html self.charts_instance styles :: Text styles = "\ diff --git a/examples/charts/Charts.hs b/examples/charts/Charts.hs index adcd3b5..1ed4f53 100644 --- a/examples/charts/Charts.hs +++ b/examples/charts/Charts.hs @@ -6,8 +6,8 @@ import Data.Text (Text) import Data.Text qualified as Text import GHC.Generics -import Sketch -import Sketch.FFI +import Clickable +import Clickable.FFI import PairSelector qualified as PairSelector ------------------------------------------------------- @@ -18,37 +18,42 @@ data ChartState = ChartState { main_transform :: Transform2D , mouse_position :: Point , counter :: Int - , pair_selector_instance :: PairSelector.PairSelectorState } deriving (Show, Eq, Generic) -new :: IO ChartState +data ChartInstance = ChartInstance + { state_var :: IncVar ChartState + , pair_selector_instance :: IncVar PairSelector.PairSelectorState + } deriving (Generic) + +new :: ClickM ChartInstance new = do pair_selector_instance <- PairSelector.new - return ChartState + state_var <- newVar ChartState { main_transform = Transform2D 0 0 0 0 , mouse_position = Point 0 0 , counter = 0 - , pair_selector_instance } + return ChartInstance {state_var, pair_selector_instance} -html :: BuilderM ChartState () -html = do +html :: ChartInstance -> HtmlM () +html self = do el "style" [] $ text styles div_ [("className", "Charts-root")] do h1_ [] $ text "Canvas with candle chart" div_ [] do - embedFld @"pair_selector_instance" PairSelector.html + PairSelector.html self.pair_selector_instance div_ [] do button_ [] do - text "Click this button" + text "Clickable this button" on "click" \_ -> do - modifyFld @"counter" (+ 1) + modifyVar self.state_var \s -> s {counter = s.counter + 1 } button_ [] do text "Print state" on "click" \_ -> do - s <- get - consoleLog $ Text.pack $ show s.position - span_ [] $ dynText $ \s -> "You clicked " <> Text.pack (show s.counter) <> " times" + s <- liftIO $ readVar self.state_var + consoleLog $ Text.pack $ show s + span_ [] $ dynText $ TipVal self.state_var `MapVal` \s -> + "You clicked " <> Text.pack (show s.counter) <> " times" canvas_ [("className", "Charts-canvas")] $ return () styles :: Text @@ -78,21 +83,21 @@ data Point = Point , point_y :: Double } deriving (Eq, Show, Generic) -setMouseCoords :: Point -> Edit ChartState -setMouseCoords p = Fld (Proxy @"mouse_position") (Ins p) +-- setMouseCoords :: Point -> Edit ChartState +-- setMouseCoords p = Fld (Proxy @"mouse_position") (Ins p) -moveScreen :: Double -> Jet ChartState -> Jet ChartState -moveScreen dir old = - let - beg = negate old.position.main_transform.c / old.position.main_transform.a - end = (w - old.position.main_transform.c) / old.position.main_transform.a - inc = (end - beg) * dir - w = 1000 - c = old.position.main_transform.c - - (inc * old.position.main_transform.a) - new = old.position - { main_transform = old.position.main_transform {c} - } - in - Jet new (Fld (Proxy @"main_transform") (Fld (Proxy @"c") (Ins c)) : old.velocity) +-- moveScreen :: Double -> Jet ChartState -> Jet ChartState +-- moveScreen dir old = +-- let +-- beg = negate old.position.main_transform.c / old.position.main_transform.a +-- end = (w - old.position.main_transform.c) / old.position.main_transform.a +-- inc = (end - beg) * dir +-- w = 1000 +-- c = old.position.main_transform.c - +-- (inc * old.position.main_transform.a) +-- new = old.position +-- { main_transform = old.position.main_transform {c} +-- } +-- in +-- Jet new (Fld (Proxy @"main_transform") (Fld (Proxy @"c") (Ins c)) : old.velocity) diff --git a/examples/charts/PairSelector.hs b/examples/charts/PairSelector.hs index 48ba0ce..85764b3 100644 --- a/examples/charts/PairSelector.hs +++ b/examples/charts/PairSelector.hs @@ -6,8 +6,8 @@ import Data.Text qualified as Text import Data.Function hiding (on) import GHC.Generics -import Sketch -import Sketch.FFI +import Clickable +import Clickable.FFI data TradingPair = TradingPair { base :: Text @@ -20,24 +20,24 @@ data PairSelectorState = PairSelectorState , options :: [TradingPair] } deriving (Show, Eq, Generic) -new :: IO PairSelectorState +new :: ClickM (IncVar PairSelectorState) new = - return PairSelectorState + newVar PairSelectorState { selected_pair = Nothing , options = [] } -html :: BuilderM PairSelectorState () -html = do +html :: IncVar PairSelectorState -> HtmlM () +html self = do el "style" [] $ text styles div_ [("className", "PairSelector-root")] do button_ [] do text "Select pair" on "click" \_ -> do - modifyFld @"selected_pair" $ \case - Just _ -> Nothing - Nothing -> Just $ TradingPair "BTC" "USDT" "MEXC" - span_ [] $ dynText \s -> s.selected_pair & maybe + modifyVar self \s -> case s.selected_pair of + Just _ -> s {selected_pair = Nothing} + Nothing -> s {selected_pair = Just $ TradingPair "BTC" "USDT" "MEXC"} + span_ [] $ dynText $ TipVal self `MapVal` \s -> s.selected_pair & maybe "Nothing selected" (("Selected pair: " <>) . Text.pack . show) diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs index 01333be..46db5f1 100644 --- a/examples/charts/charts.hs +++ b/examples/charts/charts.hs @@ -1,8 +1,10 @@ -import Sketch +import Control.Monad.Reader +import Clickable import "this" App qualified as App main :: IO () main = return () foreign export ccall wasm_main :: IO () -wasm_main = App.new >>= flip attach App.html +wasm_main = attach do + (HtmlM $ ReaderT $ \_ -> App.new) >>= App.html diff --git a/htmlt.cabal b/htmlt.cabal index 6b8a27b..d1b849d 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -89,8 +89,8 @@ library -- HtmlT.Main -- HtmlT.Property -- HtmlT.Types - Sketch - Sketch.FFI + Clickable + Clickable.FFI Wasm.Compat.Prim Wasm.Compat.Marshal @@ -154,6 +154,7 @@ executable htmlt-charts text, mtl, other-modules: + App Charts PairSelector if !flag(examples) diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index f37b2bf..0dd9d38 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -98,14 +98,14 @@ newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v), getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), -ZC0ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, -ZC2ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC1ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC($1,a1)), -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3,$4) => {var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); $1.addEventListener(e, $4);}, -ZC4ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: () => (document.body), -ZC5ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); $1[k] = v;}, -ZC6ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, -ZC7ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); $1.appendChild(n); return n;}, -ZC8ZChtmltzm0zi1zi0zi0zminplaceZCSketchziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); $1.appendChild(n); return n;}, +ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC2ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), +ZC4ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4) => {var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); if ($1 instanceof Comment) { $1.parentNode.addEventListener(e, $4); } else { $1.addEventListener(e, $4); }}, +ZC5ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: () => (document.body), +ZC6ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); if ($1 instanceof Comment) { $1.parentNode[k] = v; } else { $1[k] = v; }}, +ZC7ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, +ZC8ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, +ZC9ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, diff --git a/src/Clickable.hs b/src/Clickable.hs new file mode 100644 index 0000000..51f80a7 --- /dev/null +++ b/src/Clickable.hs @@ -0,0 +1,299 @@ +module Clickable where + +import Control.Monad +import Data.Bifunctor +import Control.Monad.Identity +import Control.Monad.Reader +import Control.Monad.Trans +import Control.Monad.State +import Data.Foldable +import Data.Function ((&)) +import Data.Generics.Internal.VL hiding (build) +import Data.Generics.Product.Fields +import Data.Generics.Sum.Constructors +import Data.IORef +import Data.List qualified as List +import Data.Text (Text) +import Data.Tuple +import Data.Typeable +import Data.Map (Map) +import Data.Set (Set) +import Data.Map qualified as Map +import GHC.Generics +import GHC.Exts hiding (build) +import GHC.TypeLits +import Unsafe.Coerce + +import Clickable.FFI +import Wasm.Compat.Prim + +--------------------------- +-- INCREMENTAL VARIABLES -- +--------------------------- + +data IncVar a where + IncVar :: RefId -> IORef a -> IncVar a + +type RefId = Int + +data IncVal a where + TipVal :: IncVar a -> IncVal a + MapVal :: IncVal a -> (a -> b) -> IncVal b + +newVar :: a -> ClickM (IncVar a) +newVar a = do + ref <- liftIO $ newIORef a + state \s -> (IncVar s.next_id ref, s {next_id = s.next_id + 1}) + +readVal :: IncVal a -> IO a +readVal (TipVal (IncVar _ ref)) = readIORef ref +readVal (MapVal val f) = fmap f $ readVal val + +readVar :: IncVar a -> IO a +readVar (IncVar _ ref) = readIORef ref + +atomicModifyVar :: IncVar s -> (s -> (s, a)) -> ClickM a +atomicModifyVar var@(IncVar varId ref) f = do + (vals, a) <- liftIO $ atomicModifyIORef' ref g + modify $ varModifiedFn var vals + return a + where + g old = let (new, a) = f old in (new, ((old, new), a)) + +modifyVar :: IncVar s -> (s -> s) -> ClickM () +modifyVar var f = atomicModifyVar var ((,()) . f) + +subscribeFn :: + ScopeId -> + IncVal a -> + ((a, a) -> ClickM ()) -> + InternalState -> InternalState +subscribeFn s (TipVal (IncVar varId _)) fn old = + old { subscriptions = sub : old.subscriptions } + where + sub = (s, varId, fn . bimap unsafeCoerce unsafeCoerce) +subscribeFn s (MapVal v f) fn old = subscribeFn s v (fn . bimap f f) old + +subscribe :: IncVal a -> ((a, a) -> ClickM ()) -> ClickM () +subscribe val k = do + e <- ask + liftIO $ modifyIORef' e.internal_state_ref $ subscribeFn e.scope val k + +varModifiedFn :: + IncVar a -> + (a, a) -> + InternalState -> InternalState +varModifiedFn (IncVar varId _) vals = go0 where + go0 = defer varId $ gets (.subscriptions) >>= go1 + go1 [] = return () + go1 ((_, sVar, cb) : xs) + | sVar == varId = cb (bimap unsafeCoerce unsafeCoerce vals) >> go1 xs + | otherwise = go1 xs + +freeScopeFn :: Bool -> ScopeId -> InternalState -> (InternalState, [Finalizer]) +freeScopeFn unlink rscope old = + let + chkSub (s, _, _) = s /= rscope + chkFin True (s1, ScopeFinalizer s2) = s1 /= rscope && s2 /= rscope + chkFin True (s, _) = s /= rscope + chkFin False (s, _) = s /= rscope + (scopeFns, finalizers) = List.partition (chkFin unlink) old.finalizers + new = old + { subscriptions = List.filter chkSub old.subscriptions + , finalizers + } + in + (new, scopeFns) + +freeScope :: ScopeId -> ClickM () +freeScope s = f where + f = state (swap . freeScopeFn True s) >>= g + g [] = return () + g ((_, ScopeFinalizer s'):xs) = freeScope s' >> g xs + g ((_, CustomFinalizer x):xs) = x >> g xs + +clearScope :: ScopeId -> ClickM () +clearScope s = f where + f = state (swap . freeScopeFn False s) >>= g + g [] = return () + g ((_, ScopeFinalizer s'):xs) = freeScope s' >> g xs + g ((_, CustomFinalizer x):xs) = x >> g xs + +newScopeFn :: ScopeId -> InternalState -> (InternalState, ScopeId) +newScopeFn p old = + let + scopeId = old.next_id + new = old + { finalizers = (p, ScopeFinalizer scopeId) : old.finalizers + , next_id = old.next_id + 1 + } + in + (new, scopeId) + +newScope :: ClickM ScopeId +newScope = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ newScopeFn e.scope + +------------------------------- +-- REATIVE STUFF RESURRECTED -- +------------------------------- + +data InternalState = InternalState + { subscriptions :: [Subscription] + , finalizers :: [Finalizer] + , transaction_queue :: Map RefId (ClickM ()) + , next_id :: Int + } deriving (Generic) + +emptyInternalState :: InternalState +emptyInternalState = InternalState + { subscriptions = [] + , finalizers = [] + , transaction_queue = Map.empty + , next_id = 0 + } + +data InternalEnv = InternalEnv + { scope :: ScopeId + , internal_state_ref :: IORef InternalState + } deriving (Generic) + +newInternalEnv :: IO InternalEnv +newInternalEnv = do + let scope = emptyInternalState.next_id + internal_state_ref <- newIORef emptyInternalState + return InternalEnv {internal_state_ref, scope} + +type Subscription = (ScopeId, RefId, (Any, Any) -> ClickM ()) + +type Finalizer = (ScopeId, FinalizerVal) + +type EventId = Int + +type ScopeId = Int + +data FinalizerVal + = CustomFinalizer (ClickM ()) + | ScopeFinalizer ScopeId + +newtype HtmlM a = HtmlM { unHtmlM :: ReaderT JSVal ClickM a } + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader JSVal) + +newtype ClickM a = ClickM {unClickM :: ReaderT InternalEnv IO a } + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) + +instance MonadState InternalState ClickM where + state f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ swap . f + +liftClickM :: ClickM a -> HtmlM a +liftClickM = HtmlM . lift + +-- | Loop until transaction queue is empty. TODO: Is this even +-- worth-while to have? What if just let multiple DOM changes when it +-- depends on several sources? +trampoline :: ClickM a -> ClickM a +trampoline act = loop0 act where + loop0 :: ClickM a -> ClickM a + loop0 before = do + r <- before + mcont <- popQueue + forM_ mcont loop1 + return r + loop1 :: ClickM () -> ClickM () + loop1 before = do + before + mcont <- popQueue + forM_ mcont loop1 + popQueue :: ClickM (Maybe (ClickM ())) + popQueue = state \s -> + case Map.minViewWithKey s.transaction_queue of + Nothing -> (Nothing, s) + Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) + +defer :: RefId -> ClickM () -> InternalState -> InternalState +defer k act s = s { transaction_queue = Map.insert k act s.transaction_queue } + +------------------ +-- BUILDING DOM -- +------------------ + +el :: Text -> [(Text, Text)] -> HtmlM a -> HtmlM a +el t att ch = do + r <- ask + el <- liftIO $ insertElement r t + liftIO $ forM_ att \(k, v) -> setProperty el k v + local (const el) ch + +text :: Text -> HtmlM () +text t = do + r <- ask + void $ liftIO $ insertText r t + +dynText :: IncVal Text -> HtmlM () +dynText val = do + r <- ask + s <- HtmlM $ lift $ asks (.scope) + t <- liftIO $ readVal val + textNode <- liftIO $ insertText r t + HtmlM $ lift $ modify $ subscribeFn s val $ \(old, new) -> liftIO $ + when (old /= new) $ updateTextContent textNode new + +div_ :: [(Text, Text)] -> HtmlM a -> HtmlM a +div_ = el "div" + +canvas_ :: [(Text, Text)] -> HtmlM a -> HtmlM a +canvas_ = el "div" + +span_ :: [(Text, Text)] -> HtmlM a -> HtmlM a +span_ = el "div" + +h1_ :: [(Text, Text)] -> HtmlM a -> HtmlM a +h1_ = el "h1" + +button_ :: [(Text, Text)] -> HtmlM a -> HtmlM a +button_ = el "button" + +select_ :: [(Text, Text)] -> HtmlM a -> HtmlM a +select_ = el "select" + +on :: Text -> (JSVal -> ClickM ()) -> HtmlM () +on e l = do + root <- ask + env <- HtmlM $ lift ask + let cb = void . (`runReaderT` env) . unClickM . trampoline . l + jlisnr <- liftIO $ js_dynExport cb + liftIO $ addEventListener root e jlisnr + +--------------------- +-- DYNAMIC CONTENT -- +--------------------- + +dyn :: IncVal (HtmlM ()) -> HtmlM () +dyn val = do + root <- ask + closeBracket <- liftIO $ js_insertBrackets root + scope <- liftClickM newScope + initialVal <- liftIO $ readVal val + let + update html = do + liftIO $ js_clearBrackets closeBracket + html + exec = local (\s -> s {scope}) . + flip runReaderT closeBracket . unHtmlM + liftClickM $ exec $ update initialVal + liftClickM $ subscribe val \(_, newVal) -> do + clearScope scope + exec $ update newVal + return () + +-------------------------- +-- START AN APPLICATION -- +-------------------------- + +attach :: HtmlM a -> IO a +attach html = do + body <- documentBody + env <- newInternalEnv + html.unHtmlM + & flip runReaderT body + & unClickM + & flip runReaderT env diff --git a/src/Sketch/FFI.hs b/src/Clickable/FFI.hs similarity index 68% rename from src/Sketch/FFI.hs rename to src/Clickable/FFI.hs index 4872d82..bf05d86 100644 --- a/src/Sketch/FFI.hs +++ b/src/Clickable/FFI.hs @@ -6,7 +6,7 @@ #if defined(wasm32_HOST_ARCH) {-# LANGUAGE JavaScriptFFI #-} #endif -module Sketch.FFI where +module Clickable.FFI where import Control.Monad.IO.Class import Wasm.Compat.Prim @@ -17,6 +17,8 @@ import Data.Text.Internal import Data.Array.Byte +newtype DomBuilder = DomBuilder {unDomBuilder :: JSVal} + insertText :: JSVal -> Text -> IO JSVal insertText root (Text (ByteArray arr) off len) = do let addr = byteArrayContents# arr @@ -73,17 +75,31 @@ documentBody = undefined js_consoleLog :: Ptr Word8 -> Int -> IO () js_consoleLog = undefined +js_insertBrackets :: JSVal -> IO JSVal +js_insertBrackets = undefined + +js_clearBrackets :: JSVal -> IO () +js_clearBrackets = undefined + #else foreign import javascript unsafe "var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ var n = document.createTextNode(c);\ - $1.appendChild(n);\ + if ($1 instanceof Comment) {\ + $1.parentNode.insertBefore(n, $1);\ + } else {\ + $1.appendChild(n);\ + }\ return n;" js_insertText :: JSVal -> Ptr Word8 -> Int -> IO JSVal foreign import javascript unsafe "var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ var n = document.createElement(t);\ - $1.appendChild(n);\ + if ($1 instanceof Comment) {\ + $1.parentNode.insertBefore(n, $1);\ + } else {\ + $1.appendChild(n);\ + }\ return n;" js_insertElement :: JSVal -> Ptr Word8 -> Int -> IO JSVal foreign import javascript unsafe @@ -92,15 +108,49 @@ foreign import javascript unsafe foreign import javascript unsafe "var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5));\ - $1[k] = v;" + if ($1 instanceof Comment) {\ + $1.parentNode[k] = v;\ + } else {\ + $1[k] = v;\ + }" js_setProperty :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () foreign import javascript unsafe "document.body" documentBody :: IO JSVal foreign import javascript unsafe "var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ - $1.addEventListener(e, $4);" + if ($1 instanceof Comment) {\ + $1.parentNode.addEventListener(e, $4);\ + } else {\ + $1.addEventListener(e, $4);\ + }" js_addEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () foreign import javascript "wrapper" js_dynExport :: (JSVal -> IO ()) -> IO JSVal foreign import javascript unsafe "console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));" js_consoleLog :: Ptr Word8 -> Int -> IO () +foreign import javascript unsafe + "var c1 = document.createComment('ContentBoundary {{');\ + var c2 = document.createComment('}}');\ + if ($1 instanceof Comment) {\ + $1.parentNode.insertBefore(c1, $1);\ + $1.parentNode.insertBefore(c2, $1);\ + } else {\ + $1.appendChild(c1);\ + $1.appendChild(c2);\ + }\ + return c2;" + js_insertBrackets :: JSVal -> IO JSVal +foreign import javascript unsafe + "function isOpenBracket(node) {return node instanceof Comment && node.textContent == 'ContentBoundary {{'}\ + function isCloseBracket(node) {return node instanceof Comment && node.textContent == '}}'}\ + var iter = $1;\ + var nestedCounter = 0;\ + for (;;){\ + if (!iter.previousSibling ||\ + (nestedCounter == 0 && isOpenBracket(iter.previousSibling))\ + ) break;\ + if (isCloseBracket(iter.previousSibling)) nestedCounter++;\ + else if (isOpenBracket(iter.previousSibling)) nestedCounter--;\ + iter.previousSibling.parentNode.removeChild(iter.previousSibling);\ + }" + js_clearBrackets :: JSVal -> IO () #endif diff --git a/src/Sketch.hs b/src/Sketch.hs deleted file mode 100644 index 345fe4d..0000000 --- a/src/Sketch.hs +++ /dev/null @@ -1,360 +0,0 @@ -module Sketch where - -import Control.Monad -import Control.Monad.Identity -import Control.Monad.Reader -import Control.Monad.State -import Data.Foldable -import Data.Generics.Internal.VL hiding (build) -import Data.Generics.Product.Fields -import Data.Generics.Sum.Constructors -import Data.IORef -import Data.List qualified as List -import Data.Text (Text) -import Data.Tuple -import Data.Typeable -import Data.Map (Map) -import Data.Map qualified as Map -import GHC.Generics -import GHC.Exts hiding (build) -import GHC.TypeLits - -import Sketch.FFI -import Wasm.Compat.Prim - --------------------------- --- DIFFING AND PATCHING -- --------------------------- - -data Edit a where - Ins :: a -> Edit a - Fld :: - ( HasField' f s a - , KnownSymbol f - , Typeable a - ) => - Proxy f -> Edit a -> Edit s - Ctor :: - ( AsConstructor' ctor s a - , KnownSymbol ctor - , Typeable a - ) => Proxy ctor -> Edit a -> Edit s - Sum :: SumCtor ctor s a => Edit a -> Edit s - Ix :: Int -> Edit e -> Edit [e] - Splice :: Int -> Int -> [e] -> Edit [e] - -type SyncPlan s = [SyncOp s] - -class SumCtor ctor s a | ctor s -> a - -instance SumCtor "In1" (Sum a b) a - -instance SumCtor "In2" (Sum a b) b - -patch :: Edit s -> s -> s -patch (Ins s) _ = s -patch (Fld p e) s = pfld p e s where - pfld :: forall f s a. HasField' f s a => Proxy f -> Edit a -> s -> s - pfld _ e s = over (field' @f) (patch e) s -patch (Ctor p e) s = pctor p e s where - pctor :: forall ctor s a. AsConstructor' ctor s a => Proxy ctor -> Edit a -> s -> s - pctor _ e s = over (_Ctor' @ctor) (patch e) s -patch (Ix i e) s = go i e s where - go :: Int -> Edit e -> [e] -> [e] - go 0 e (x:xs) = patch e x : xs - go _ _ [] = [] - go n e (x:xs) = x : go (n - 1) e xs -patch (Splice i rem ins) s = go ins i s where - go :: [e] -> Int -> [e] -> [e] - go ins 0 xs = ins <> List.drop rem xs - go ins n (x:xs) = x : go ins (n - 1) xs - go _ _ [] = [] - ------------------------------------------------------------- --- INCREMENTAL OPTICS USED FOR EMBEDDING COMPONENT STATES -- ------------------------------------------------------------- - -data IncOptic s a where - FldLens :: - ( HasField' f s a - , KnownSymbol f - , Typeable a - ) => Proxy f -> IncOptic s a - IxTrav :: - Int -> IncOptic [a] a - CtorPrism :: - ( AsConstructor' ctor s a - , KnownSymbol ctor - , Typeable a - ) => Proxy ctor -> IncOptic s a - Comp :: IncOptic s x -> IncOptic x a -> IncOptic s a - -type IncGetter s a = Jet s -> Jet a - ------------------ --- CORE TYPES -- ------------------ - -data Layout s where - EmbedNode :: (ModifierFn s -> ModifierFn t) -> (Jet s -> Jet t) -> [Layout t] -> Layout s - TextNode :: Text -> Layout s - DynText :: (s -> Text) -> Layout s - ElemNode :: Text -> [(Text, Text)] -> [Layout s] -> Layout s - EventListener :: Text -> (JSVal -> TransitionM s ()) -> Layout s - -- DynNode :: (Jet s -> Jet (Layout s)) -> Layout s - -- SimpleList :: (Jet s -> Jet [a]) -> (Edit [a] -> Edit s) -> Layout a -> Layout s - -data SyncOp s where - TextOp :: JSVal -> (s -> Text) -> SyncOp s - PropOp :: JSVal -> Text -> (s -> Text) -> SyncOp s - MapOp :: (Jet s -> Jet t) -> SyncOp t -> SyncOp s - -data Jet a = Jet { position :: a, velocity :: [Edit a] } - -newtype BuilderM s a = BuilderM { unBuilderM :: StateT [Layout s] Identity a } - deriving newtype (Functor, Applicative, Monad, MonadState [Layout s]) - -newtype TransitionM s a = TransitionM { unTransitionM :: ReaderT (ModifierFn s) IO a } - deriving newtype (Functor, Applicative, Monad, MonadIO) - -instance MonadState (Jet s) (TransitionM s) where - state f = TransitionM $ ReaderT \(ModifierFn mf) -> mf (swap . f) - -newtype ModifierFn s = ModifierFn {unModifierFn :: forall a. (Jet s -> (Jet s, a)) -> IO a } - ----------------------- --- STATE MANAGEMENT -- ----------------------- - -edit :: Edit s -> TransitionM s () -edit e = modify \j -> Jet (patch e j.position) (e : j.velocity) - -modifyFld :: forall f s a m. - ( HasField' f s a - , KnownSymbol f - , Typeable a - , MonadState (Jet s) m - ) => - (a -> a) -> - m () -modifyFld f = modify f0 where - f0 :: Jet s -> Jet s - f0 j = Jet s' (e : j.velocity) where - s' = over (field' @f) f j.position - e = Fld (Proxy @f) (Ins (getField @f s')) - -mapModifierFn :: forall s a. - (Edit a -> Edit s) -> - (Jet s -> Jet a) -> - ModifierFn s -> - ModifierFn a -mapModifierFn g f (ModifierFn ms) = ModifierFn f0 where - f0 :: forall x. (Jet a -> (Jet a, x)) -> IO x - f0 fa = ms (f1 fa) - - f1 :: forall x. (Jet a -> (Jet a, x)) -> Jet s -> (Jet s, x) - f1 fa js = (js', x) where - (ja, x) = fa (f js) - js' = Jet js.position (fmap g ja.velocity <> js.velocity) - -refModifier :: forall s. (Jet s -> IO ()) -> IORef s -> ModifierFn s -refModifier up ref = ModifierFn f0 where - f0 :: forall x. (Jet s -> (Jet s, x)) -> IO x - f0 f = do - (x, jet) <- atomicModifyIORef' ref $ f1 f - up jet - return x - - f1 :: forall x. (Jet s -> (Jet s, x)) -> s -> (s, (x, Jet s)) - f1 f s = let (js', x) = f (Jet s []) in (js'.position, (x, js')) - -fldModifierFn :: forall f s a. - ( HasField' f s a - , KnownSymbol f - , Typeable a - ) => - ModifierFn s -> - ModifierFn a -fldModifierFn (ModifierFn ms) = ModifierFn f0 where - f0 :: forall x. (Jet a -> (Jet a, x)) -> IO x - f0 fa = ms (f1 fa) - - f1 :: forall x. (Jet a -> (Jet a, x)) -> Jet s -> (Jet s, x) - f1 fa js = (js', x) where - a = getField @f js.position - s' = setField @f ja.position js.position - (ja, x) = fa (Jet a []) - js' = Jet s' (fmap (Fld (Proxy @f)) ja.velocity <> js.velocity) - -fldJet :: forall f s a. - ( HasField' f s a - , KnownSymbol f - , Typeable a - ) => - Jet s -> Jet a -fldJet js = Jet (getField @f js.position) (fltc js.velocity) where - fltc :: [Edit s] -> [Edit a] - fltc [] = [] - fltc ((Fld p e) : xs) - | Just e' <- chkfld p e = e' : fltc xs - | otherwise = fltc xs - fltc (_ : xs) = fltc xs - - chkfld :: forall f' a'. - ( HasField' f' s a' - , KnownSymbol f' - , Typeable a' - ) => - Proxy f' -> Edit a' -> Maybe (Edit a) - chkfld _ e - | Just Refl <- eqT @f' @f - , Just Refl <- eqT @a' @a = Just e - | otherwise = Nothing - ------------------- --- BUILDING DOM -- ------------------- - -el :: Text -> [(Text, Text)] -> BuilderM s a -> BuilderM s a -el tagName attrs children = do - let (res, layout) = runIdentity $ runStateT children.unBuilderM [] - modify (ElemNode tagName attrs layout :) - return res - -text :: Text -> BuilderM s () -text content = modify (TextNode content :) - -dynText :: (s -> Text) -> BuilderM s () -dynText f = modify (DynText f :) - -div_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a -div_ = el "div" - -canvas_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a -canvas_ = el "div" - -span_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a -span_ = el "div" - -h1_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a -h1_ = el "h1" - -button_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a -button_ = el "button" - -select_ :: [(Text, Text)] -> BuilderM s a -> BuilderM s a -select_ = el "select" - -on :: Text -> (JSVal -> TransitionM s ()) -> BuilderM s () -on e l = modify (EventListener e l :) - --------------------------- --- COMPONENT EMBEDDING -- --------------------------- - -embedFld :: forall f s a x. - ( HasField' f s a - , KnownSymbol f - , Typeable a - ) => - BuilderM a x -> - BuilderM s x -embedFld b = BuilderM $ StateT st where - st l = Identity (x, (n:l)) - n = EmbedNode (fldModifierFn @f) (fldJet @f) l' - (x, l') = runIdentity $ runStateT b.unBuilderM [] - -data Sum a b = In1 a | In2 b deriving Generic - -embedSum :: - BuilderM a x -> - BuilderM b x -> - BuilderM (Sum a b) x -embedSum b = undefined - --------------------------- --- START AN APPLICATION -- --------------------------- - -build :: - ModifierFn s -> - [Layout s] -> - s -> - JSVal -> - SyncPlan s -> - IO (SyncPlan s) -build m = go0 . List.reverse where - go0 [] _ _ p = return p - go0 (x:xs) s r p = do { p' <- go1 m x s r p; go0 xs s r p' } - - go1 m (EmbedNode f g l) s r p = do - p' <- build (f m) l ((g (Jet s [])).position) r [] - return $ fmap (MapOp g) p' <> p - go1 m (TextNode t) s r p = - insertText r t >> return p - go1 m (DynText f) s r p = do - textNode <- liftIO $ insertText r $ f s - return $ TextOp textNode f : p - go1 m (ElemNode tagName attrs children) s r p = do - el <- insertElement r tagName - forM_ attrs \(k, v) -> setProperty el k v - -- TODO: Could use insertBefore() to avoid reversing the list! - foldM (\p h -> go1 m h s el p) p $ List.reverse children - go1 m (EventListener eventName listenr) s r p = do - jlisnr <- js_dynExport \event -> flip runReaderT m $ unTransitionM $ listenr event - addEventListener r eventName jlisnr - return p - -sync :: SyncPlan s -> Jet s -> IO () -sync [] _ = return () -sync (x:xs) s = go x s >> sync xs s where - go :: forall s. SyncOp s -> Jet s -> IO () - go (MapOp f op0) s = do - let t = f s - unless (List.null t.velocity) $ go op0 t - go (TextOp textNode f) s = updateTextContent textNode $ f s.position - go (PropOp elemNode propName f) s = setProperty elemNode propName $ f s.position - -attach :: s -> BuilderM s a -> IO a -attach s html = mdo - stateRef <- newIORef s - body <- documentBody - let (res, layout) = runIdentity $ runStateT html.unBuilderM [] - let mod = refModifier (sync plan) stateRef - plan <- build mod layout s body [] - return res - ---------------------------- --- INCREMENTAL VARIABLES -- ---------------------------- - -data IncVar t a where - TipVar :: RefId -> IORef a -> IncVar '[] a - LensMapVar :: IncOptic s a -> IncVar t a - MapVar :: (s -> a) -> IncVar '[ 'GetterConstraint] a - -type RefId = Int - -data VarConstraint = GetterConstraint - -------------------------------- --- REATIVE STUFF RESURRECTED -- -------------------------------- - -data RunningState = RunningState - { sync_plan :: [(ScopeId, RefId, Any -> IO ())] - , finalizers :: [(ScopeId, RefId, Any -> IO ())] - } deriving (Generic) - -type EventId = Int - -data ScopeId - = RootScope - | BranchScope ScopeId Int - deriving (Eq, Ord, Show) - -data ScopeNode = ScopeNode - { nodes :: [ScopeId] - , parent :: Maybe ScopeId - , finalizers :: [IO ()] - } deriving stock Generic From 4da49419b61a41316e83d82e4e86e2b762c79941 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sun, 24 Mar 2024 18:26:30 +0400 Subject: [PATCH 12/64] WIP --- examples/charts/App.hs | 31 ++- examples/charts/Charts.hs | 28 +-- examples/charts/PairSelector.hs | 20 +- examples/charts/charts.hs | 2 +- htmlt.cabal | 6 +- jsbits/jsffi.js | 19 +- src/Clickable.hs | 307 +----------------------- src/Clickable/Core.hs | 312 +++++++++++++++++++++++++ src/Clickable/DOM.hs | 256 ++++++++++++++++++++ src/Clickable/Element.hs | 402 ++++++++++++++++++++++++++++++++ src/Clickable/FFI.hs | 74 ++++++ src/Clickable/Property.hs | 366 +++++++++++++++++++++++++++++ src/Wasm/Compat/Marshal.hs | 140 ++++++++++- 13 files changed, 1614 insertions(+), 349 deletions(-) create mode 100644 src/Clickable/Core.hs create mode 100644 src/Clickable/DOM.hs create mode 100644 src/Clickable/Element.hs create mode 100644 src/Clickable/Property.hs diff --git a/examples/charts/App.hs b/examples/charts/App.hs index 090a71f..568a3af 100644 --- a/examples/charts/App.hs +++ b/examples/charts/App.hs @@ -11,20 +11,43 @@ import Clickable.FFI data AppInstance = AppInstance - { charts_instance :: Charts.ChartInstance + { state_var :: DynVar AppTab } deriving (Generic) +data AppTab + = ChartsTab Charts.ChartInstance + | HelpTab + new :: ClickM AppInstance new = do charts_instance <- Charts.new + state_var <- newVar $ ChartsTab charts_instance return AppInstance - { charts_instance + { state_var } html :: AppInstance -> HtmlM () html self = do - el "style" [] $ text styles - Charts.html self.charts_instance + el "style" $ text styles + div_ do + button_ do + text "Open Charts" + on @"click" do + inst <- Charts.new + modifyVar self.state_var $ const $ ChartsTab inst + button_ do + text "Open Help" + on @"click" $ modifyVar self.state_var $ const HelpTab + dyn $ self.state_var `mapVar` \case + ChartsTab inst -> Charts.html inst + HelpTab -> p_ $ text + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod \ + \tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim \ + \veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea \ + \commodo consequat. Duis aute irure dolor in reprehenderit in voluptate \ + \velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint \ + \occaecat cupidatat non proident, sunt in culpa qui officia deserunt \ + \mollit anim id est laborum." styles :: Text styles = "\ diff --git a/examples/charts/Charts.hs b/examples/charts/Charts.hs index 1ed4f53..224ea22 100644 --- a/examples/charts/Charts.hs +++ b/examples/charts/Charts.hs @@ -21,8 +21,8 @@ data ChartState = ChartState } deriving (Show, Eq, Generic) data ChartInstance = ChartInstance - { state_var :: IncVar ChartState - , pair_selector_instance :: IncVar PairSelector.PairSelectorState + { state_var :: DynVar ChartState + , pair_selector_instance :: DynVar PairSelector.PairSelectorState } deriving (Generic) new :: ClickM ChartInstance @@ -37,24 +37,24 @@ new = do html :: ChartInstance -> HtmlM () html self = do - el "style" [] $ text styles - div_ [("className", "Charts-root")] do - h1_ [] $ text "Canvas with candle chart" - div_ [] do + el "style" $ text styles + div_ [class_ "Charts-root"] do + h1_ $ text "Canvas with candle chart" + div_ do PairSelector.html self.pair_selector_instance - div_ [] do - button_ [] do + div_ do + button_ do text "Clickable this button" - on "click" \_ -> do + on @"click" do modifyVar self.state_var \s -> s {counter = s.counter + 1 } - button_ [] do + button_ do text "Print state" - on "click" \_ -> do - s <- liftIO $ readVar self.state_var + on @"click" do + s <- readVar self.state_var consoleLog $ Text.pack $ show s - span_ [] $ dynText $ TipVal self.state_var `MapVal` \s -> + span_ [] $ dynText $ self.state_var `mapVar` \s -> "You clicked " <> Text.pack (show s.counter) <> " times" - canvas_ [("className", "Charts-canvas")] $ return () + canvas_ [class_ "Charts-canvas"] $ return () styles :: Text styles = "\ diff --git a/examples/charts/PairSelector.hs b/examples/charts/PairSelector.hs index 85764b3..d82fee0 100644 --- a/examples/charts/PairSelector.hs +++ b/examples/charts/PairSelector.hs @@ -7,7 +7,6 @@ import Data.Function hiding (on) import GHC.Generics import Clickable -import Clickable.FFI data TradingPair = TradingPair { base :: Text @@ -20,24 +19,23 @@ data PairSelectorState = PairSelectorState , options :: [TradingPair] } deriving (Show, Eq, Generic) -new :: ClickM (IncVar PairSelectorState) +new :: ClickM (DynVar PairSelectorState) new = newVar PairSelectorState { selected_pair = Nothing , options = [] } -html :: IncVar PairSelectorState -> HtmlM () +html :: DynVar PairSelectorState -> HtmlM () html self = do - el "style" [] $ text styles - div_ [("className", "PairSelector-root")] do - button_ [] do + el "style" $ text styles + div_ [class_ "PairSelector-root"] do + button_ do text "Select pair" - on "click" \_ -> do - modifyVar self \s -> case s.selected_pair of - Just _ -> s {selected_pair = Nothing} - Nothing -> s {selected_pair = Just $ TradingPair "BTC" "USDT" "MEXC"} - span_ [] $ dynText $ TipVal self `MapVal` \s -> s.selected_pair & maybe + on @"click" $ modifyVar self \s -> case s.selected_pair of + Just _ -> s {selected_pair = Nothing} + Nothing -> s {selected_pair = Just $ TradingPair "BTC" "USDT" "MEXC"} + span_ $ dynText $ self `mapVar` \s -> s.selected_pair & maybe "Nothing selected" (("Selected pair: " <>) . Text.pack . show) diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs index 46db5f1..978d2b3 100644 --- a/examples/charts/charts.hs +++ b/examples/charts/charts.hs @@ -7,4 +7,4 @@ main = return () foreign export ccall wasm_main :: IO () wasm_main = attach do - (HtmlM $ ReaderT $ \_ -> App.new) >>= App.html + liftClickM App.new >>= App.html diff --git a/htmlt.cabal b/htmlt.cabal index d1b849d..e0e5cc5 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -90,6 +90,10 @@ library -- HtmlT.Property -- HtmlT.Types Clickable + Clickable.Core + Clickable.DOM + Clickable.Element + Clickable.Property Clickable.FFI Wasm.Compat.Prim Wasm.Compat.Marshal @@ -104,7 +108,7 @@ library transformers, ghc-experimental, ghc-prim, - generic-lens, + -- generic-lens, -- executable htmlt-counter -- import: htmlt-common diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index 0dd9d38..dc8d8bd 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -98,14 +98,17 @@ newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v), getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), -ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC2ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), -ZC4ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4) => {var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); if ($1 instanceof Comment) { $1.parentNode.addEventListener(e, $4); } else { $1.addEventListener(e, $4); }}, -ZC5ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: () => (document.body), -ZC6ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); if ($1 instanceof Comment) { $1.parentNode[k] = v; } else { $1[k] = v; }}, -ZC7ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, -ZC8ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, -ZC9ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, +ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ($1()), +ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4) => {var j = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); if ($1 instanceof Comment) { return eval(j)($1.parentNode, $4); } else { return eval(j)($1, $4); }}, +ZC2ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => {function isOpenBracket(node) {return node instanceof Comment && node.textContent == 'ContentBoundary {{'} function isCloseBracket(node) {return node instanceof Comment && node.textContent == '}}'} var iter = $1; var nestedCounter = 0; for (;;){ if (!iter.previousSibling || (nestedCounter == 0 && isOpenBracket(iter.previousSibling)) ) break; if (isCloseBracket(iter.previousSibling)) nestedCounter++; else if (isOpenBracket(iter.previousSibling)) nestedCounter--; iter.previousSibling.parentNode.removeChild(iter.previousSibling); }}, +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => {var c1 = document.createComment('ContentBoundary {{'); var c2 = document.createComment('}}'); if ($1 instanceof Comment) { $1.parentNode.insertBefore(c1, $1); $1.parentNode.insertBefore(c2, $1); } else { $1.appendChild(c1); $1.appendChild(c2); } return c2;}, +ZC4ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, +ZC6ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC5ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), +ZC9ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: () => (document.body), +ZC12ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); if ($1 instanceof Comment) { $1.parentNode[k] = v; } else { $1[k] = v; }}, +ZC13ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, +ZC14ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, +ZC15ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, diff --git a/src/Clickable.hs b/src/Clickable.hs index 51f80a7..1e2b050 100644 --- a/src/Clickable.hs +++ b/src/Clickable.hs @@ -1,299 +1,8 @@ -module Clickable where - -import Control.Monad -import Data.Bifunctor -import Control.Monad.Identity -import Control.Monad.Reader -import Control.Monad.Trans -import Control.Monad.State -import Data.Foldable -import Data.Function ((&)) -import Data.Generics.Internal.VL hiding (build) -import Data.Generics.Product.Fields -import Data.Generics.Sum.Constructors -import Data.IORef -import Data.List qualified as List -import Data.Text (Text) -import Data.Tuple -import Data.Typeable -import Data.Map (Map) -import Data.Set (Set) -import Data.Map qualified as Map -import GHC.Generics -import GHC.Exts hiding (build) -import GHC.TypeLits -import Unsafe.Coerce - -import Clickable.FFI -import Wasm.Compat.Prim - ---------------------------- --- INCREMENTAL VARIABLES -- ---------------------------- - -data IncVar a where - IncVar :: RefId -> IORef a -> IncVar a - -type RefId = Int - -data IncVal a where - TipVal :: IncVar a -> IncVal a - MapVal :: IncVal a -> (a -> b) -> IncVal b - -newVar :: a -> ClickM (IncVar a) -newVar a = do - ref <- liftIO $ newIORef a - state \s -> (IncVar s.next_id ref, s {next_id = s.next_id + 1}) - -readVal :: IncVal a -> IO a -readVal (TipVal (IncVar _ ref)) = readIORef ref -readVal (MapVal val f) = fmap f $ readVal val - -readVar :: IncVar a -> IO a -readVar (IncVar _ ref) = readIORef ref - -atomicModifyVar :: IncVar s -> (s -> (s, a)) -> ClickM a -atomicModifyVar var@(IncVar varId ref) f = do - (vals, a) <- liftIO $ atomicModifyIORef' ref g - modify $ varModifiedFn var vals - return a - where - g old = let (new, a) = f old in (new, ((old, new), a)) - -modifyVar :: IncVar s -> (s -> s) -> ClickM () -modifyVar var f = atomicModifyVar var ((,()) . f) - -subscribeFn :: - ScopeId -> - IncVal a -> - ((a, a) -> ClickM ()) -> - InternalState -> InternalState -subscribeFn s (TipVal (IncVar varId _)) fn old = - old { subscriptions = sub : old.subscriptions } - where - sub = (s, varId, fn . bimap unsafeCoerce unsafeCoerce) -subscribeFn s (MapVal v f) fn old = subscribeFn s v (fn . bimap f f) old - -subscribe :: IncVal a -> ((a, a) -> ClickM ()) -> ClickM () -subscribe val k = do - e <- ask - liftIO $ modifyIORef' e.internal_state_ref $ subscribeFn e.scope val k - -varModifiedFn :: - IncVar a -> - (a, a) -> - InternalState -> InternalState -varModifiedFn (IncVar varId _) vals = go0 where - go0 = defer varId $ gets (.subscriptions) >>= go1 - go1 [] = return () - go1 ((_, sVar, cb) : xs) - | sVar == varId = cb (bimap unsafeCoerce unsafeCoerce vals) >> go1 xs - | otherwise = go1 xs - -freeScopeFn :: Bool -> ScopeId -> InternalState -> (InternalState, [Finalizer]) -freeScopeFn unlink rscope old = - let - chkSub (s, _, _) = s /= rscope - chkFin True (s1, ScopeFinalizer s2) = s1 /= rscope && s2 /= rscope - chkFin True (s, _) = s /= rscope - chkFin False (s, _) = s /= rscope - (scopeFns, finalizers) = List.partition (chkFin unlink) old.finalizers - new = old - { subscriptions = List.filter chkSub old.subscriptions - , finalizers - } - in - (new, scopeFns) - -freeScope :: ScopeId -> ClickM () -freeScope s = f where - f = state (swap . freeScopeFn True s) >>= g - g [] = return () - g ((_, ScopeFinalizer s'):xs) = freeScope s' >> g xs - g ((_, CustomFinalizer x):xs) = x >> g xs - -clearScope :: ScopeId -> ClickM () -clearScope s = f where - f = state (swap . freeScopeFn False s) >>= g - g [] = return () - g ((_, ScopeFinalizer s'):xs) = freeScope s' >> g xs - g ((_, CustomFinalizer x):xs) = x >> g xs - -newScopeFn :: ScopeId -> InternalState -> (InternalState, ScopeId) -newScopeFn p old = - let - scopeId = old.next_id - new = old - { finalizers = (p, ScopeFinalizer scopeId) : old.finalizers - , next_id = old.next_id + 1 - } - in - (new, scopeId) - -newScope :: ClickM ScopeId -newScope = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ newScopeFn e.scope - -------------------------------- --- REATIVE STUFF RESURRECTED -- -------------------------------- - -data InternalState = InternalState - { subscriptions :: [Subscription] - , finalizers :: [Finalizer] - , transaction_queue :: Map RefId (ClickM ()) - , next_id :: Int - } deriving (Generic) - -emptyInternalState :: InternalState -emptyInternalState = InternalState - { subscriptions = [] - , finalizers = [] - , transaction_queue = Map.empty - , next_id = 0 - } - -data InternalEnv = InternalEnv - { scope :: ScopeId - , internal_state_ref :: IORef InternalState - } deriving (Generic) - -newInternalEnv :: IO InternalEnv -newInternalEnv = do - let scope = emptyInternalState.next_id - internal_state_ref <- newIORef emptyInternalState - return InternalEnv {internal_state_ref, scope} - -type Subscription = (ScopeId, RefId, (Any, Any) -> ClickM ()) - -type Finalizer = (ScopeId, FinalizerVal) - -type EventId = Int - -type ScopeId = Int - -data FinalizerVal - = CustomFinalizer (ClickM ()) - | ScopeFinalizer ScopeId - -newtype HtmlM a = HtmlM { unHtmlM :: ReaderT JSVal ClickM a } - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader JSVal) - -newtype ClickM a = ClickM {unClickM :: ReaderT InternalEnv IO a } - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) - -instance MonadState InternalState ClickM where - state f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ swap . f - -liftClickM :: ClickM a -> HtmlM a -liftClickM = HtmlM . lift - --- | Loop until transaction queue is empty. TODO: Is this even --- worth-while to have? What if just let multiple DOM changes when it --- depends on several sources? -trampoline :: ClickM a -> ClickM a -trampoline act = loop0 act where - loop0 :: ClickM a -> ClickM a - loop0 before = do - r <- before - mcont <- popQueue - forM_ mcont loop1 - return r - loop1 :: ClickM () -> ClickM () - loop1 before = do - before - mcont <- popQueue - forM_ mcont loop1 - popQueue :: ClickM (Maybe (ClickM ())) - popQueue = state \s -> - case Map.minViewWithKey s.transaction_queue of - Nothing -> (Nothing, s) - Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) - -defer :: RefId -> ClickM () -> InternalState -> InternalState -defer k act s = s { transaction_queue = Map.insert k act s.transaction_queue } - ------------------- --- BUILDING DOM -- ------------------- - -el :: Text -> [(Text, Text)] -> HtmlM a -> HtmlM a -el t att ch = do - r <- ask - el <- liftIO $ insertElement r t - liftIO $ forM_ att \(k, v) -> setProperty el k v - local (const el) ch - -text :: Text -> HtmlM () -text t = do - r <- ask - void $ liftIO $ insertText r t - -dynText :: IncVal Text -> HtmlM () -dynText val = do - r <- ask - s <- HtmlM $ lift $ asks (.scope) - t <- liftIO $ readVal val - textNode <- liftIO $ insertText r t - HtmlM $ lift $ modify $ subscribeFn s val $ \(old, new) -> liftIO $ - when (old /= new) $ updateTextContent textNode new - -div_ :: [(Text, Text)] -> HtmlM a -> HtmlM a -div_ = el "div" - -canvas_ :: [(Text, Text)] -> HtmlM a -> HtmlM a -canvas_ = el "div" - -span_ :: [(Text, Text)] -> HtmlM a -> HtmlM a -span_ = el "div" - -h1_ :: [(Text, Text)] -> HtmlM a -> HtmlM a -h1_ = el "h1" - -button_ :: [(Text, Text)] -> HtmlM a -> HtmlM a -button_ = el "button" - -select_ :: [(Text, Text)] -> HtmlM a -> HtmlM a -select_ = el "select" - -on :: Text -> (JSVal -> ClickM ()) -> HtmlM () -on e l = do - root <- ask - env <- HtmlM $ lift ask - let cb = void . (`runReaderT` env) . unClickM . trampoline . l - jlisnr <- liftIO $ js_dynExport cb - liftIO $ addEventListener root e jlisnr - ---------------------- --- DYNAMIC CONTENT -- ---------------------- - -dyn :: IncVal (HtmlM ()) -> HtmlM () -dyn val = do - root <- ask - closeBracket <- liftIO $ js_insertBrackets root - scope <- liftClickM newScope - initialVal <- liftIO $ readVal val - let - update html = do - liftIO $ js_clearBrackets closeBracket - html - exec = local (\s -> s {scope}) . - flip runReaderT closeBracket . unHtmlM - liftClickM $ exec $ update initialVal - liftClickM $ subscribe val \(_, newVal) -> do - clearScope scope - exec $ update newVal - return () - --------------------------- --- START AN APPLICATION -- --------------------------- - -attach :: HtmlM a -> IO a -attach html = do - body <- documentBody - env <- newInternalEnv - html.unHtmlM - & flip runReaderT body - & unClickM - & flip runReaderT env +module Clickable (module Exports) where + +import Clickable.DOM as Exports +import Clickable.Core as Exports +import Clickable.Element as Exports +import Clickable.Property as Exports +import Wasm.Compat.Marshal as Exports +import Wasm.Compat.Prim as Exports diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs new file mode 100644 index 0000000..2aa62ce --- /dev/null +++ b/src/Clickable/Core.hs @@ -0,0 +1,312 @@ +module Clickable.Core where + +import Control.Monad +import Control.Monad.Reader +import Control.Monad.State +import Data.Function ((&)) +import Data.IORef +import Data.List qualified as List +import Data.Text (Text) +import Data.Tuple +import Data.Map (Map) +import Data.Map qualified as Map +import GHC.Generics +import GHC.Exts hiding (build) +import Unsafe.Coerce + +import Clickable.FFI +import Wasm.Compat.Prim + +data DynVar a where + DynVar :: RefId -> IORef a -> DynVar a + +type RefId = Int + +data DynVal a where + TipVal :: DynVar a -> DynVal a + TupleVal :: DynVal a -> DynVal b -> RefId -> DynVal (a, b) + MapVal :: DynVal a -> (a -> b) -> DynVal b + +------------------------------- +-- REATIVE STUFF RESURRECTED -- +------------------------------- + +newtype HtmlM a = HtmlM { unHtmlM :: ReaderT JSVal ClickM a } + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader JSVal) + +newtype ClickM a = ClickM {unClickM :: ReaderT InternalEnv IO a } + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) + +instance MonadState InternalState ClickM where + state f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ swap . f + +data InternalEnv = InternalEnv + { scope :: ScopeId + , internal_state_ref :: IORef InternalState + } deriving (Generic) + +data InternalState = InternalState + { subscriptions :: [Subscription] + , finalizers :: [Finalizer] + , transaction_queue :: Map RefId (ClickM ()) + , next_id :: Int + } deriving (Generic) + +type Subscription = (ScopeId, RefId, Any -> ClickM ()) + +type Finalizer = (ScopeId, FinalizerVal) + +type EventId = Int + +type ScopeId = Int + +data FinalizerVal + = CustomFinalizer (ClickM ()) + | ScopeFinalizer ScopeId + +emptyInternalState :: InternalState +emptyInternalState = InternalState [] [] Map.empty 0 + +newInternalEnv :: IO InternalEnv +newInternalEnv = do + let scope = emptyInternalState.next_id + internal_state_ref <- newIORef emptyInternalState + {next_id = emptyInternalState.next_id + 1} + return InternalEnv {internal_state_ref, scope} + +liftClickM :: ClickM a -> HtmlM a +liftClickM = HtmlM . lift + +--------------------------------------- +-- OPERATIONS OVER DYNAMIC VARIABLES -- +--------------------------------------- + +mapVar :: DynVar a -> (a -> b) -> DynVal b +mapVar var = MapVal (TipVal var) + +newVar :: a -> ClickM (DynVar a) +newVar a = do + ref <- liftIO $ newIORef a + state \s -> (DynVar s.next_id ref, s {next_id = s.next_id + 1}) + +readVal :: DynVal a -> ClickM a +readVal (TipVal (DynVar _ ref)) = liftIO $ readIORef ref +readVal (TupleVal a b _) = liftA2 (,) (readVal a) (readVal b) +readVal (MapVal val f) = fmap f $ readVal val + +readVar :: DynVar a -> ClickM a +readVar (DynVar _ ref) = liftIO $ readIORef ref + +atomicModifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a +atomicModifyVar var@(DynVar varId ref) f = do + (newVal, a) <- liftIO $ atomicModifyIORef' ref g + modify $ varModifiedFn var newVal + return a + where + g old = let (new, a) = f old in (new, (new, a)) + +varModifiedFn :: + DynVar a -> + a -> + InternalState -> InternalState +varModifiedFn (DynVar varId _) vals = go0 where + go0 = defer varId $ gets (.subscriptions) >>= go1 + go1 [] = return () + go1 ((_, sVar, cb) : xs) + | sVar == varId = cb (unsafeCoerce vals) >> go1 xs + | otherwise = go1 xs + +varModifiedFn1 :: RefId -> a -> InternalState -> InternalState +varModifiedFn1 varId vals = go0 where + go0 = defer varId $ gets (.subscriptions) >>= go1 + go1 [] = return () + go1 ((_, sVar, cb) : xs) + | sVar == varId = cb (unsafeCoerce vals) >> go1 xs + | otherwise = go1 xs + +modifyVar :: DynVar s -> (s -> s) -> ClickM () +modifyVar var f = atomicModifyVar var ((,()) . f) + +--------------------------------------------- +-- RESOURCE MANAGEMENT AND DYNAMIC UPDATES -- +--------------------------------------------- + +newScopeFn :: ScopeId -> InternalState -> (InternalState, ScopeId) +newScopeFn p s = + let + scopeId = s.next_id + finalizers = (p, ScopeFinalizer scopeId) : s.finalizers + next_id = s.next_id + 1 + in + (s {finalizers, next_id}, scopeId) + +newScope :: ClickM ScopeId +newScope = ClickM $ ReaderT $ \e -> + atomicModifyIORef' e.internal_state_ref $ newScopeFn e.scope + +freeScopeFn :: Bool -> ScopeId -> InternalState -> (InternalState, [Finalizer]) +freeScopeFn unlink rscope s = + let + chkSub (s, _, _) = s /= rscope + chkFin True (s1, ScopeFinalizer s2) = s1 /= rscope && s2 /= rscope + chkFin True (s, _) = s /= rscope + chkFin False (s, _) = s /= rscope + (scopeFns, finalizers) = List.partition (chkFin unlink) s.finalizers + subscriptions = List.filter chkSub s.subscriptions + in + (s {subscriptions, finalizers}, scopeFns) + +freeScope :: Bool -> ScopeId -> ClickM () +freeScope unlink s = f where + f = state (swap . freeScopeFn unlink s) >>= g + g [] = return () + g ((_, ScopeFinalizer s'):xs) = freeScope True s' >> g xs + g ((_, CustomFinalizer x):xs) = x >> g xs + +installFinalizerFn :: ScopeId -> ClickM () -> InternalState -> InternalState +installFinalizerFn scope k s = s {finalizers = (scope, CustomFinalizer k) : s.finalizers } + +installFinalizer :: ClickM () -> ClickM () +installFinalizer k = ask >>= \e -> modify (installFinalizerFn e.scope k) + +subscribeFn :: + ScopeId -> + DynVal a -> + (a -> ClickM ()) -> + InternalState -> InternalState +subscribeFn scope (TipVal (DynVar varId _)) fn s = s + { subscriptions = sub : s.subscriptions } + where + sub = (scope, varId, fn . unsafeCoerce) +subscribeFn scope (TupleVal a b varid) fn s = + subscribeFn scope b g $ subscribeFn scope a f s + where + f a = do + bval <- readVal b + modify $ varModifiedFn1 varid (a, bval) + g b = do + aval <- readVal a + modify $ varModifiedFn1 varid (aval, b) +subscribeFn scope (MapVal v f) fn s = subscribeFn scope v (fn . f) s + +subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () +subscribe val k = do + e :: InternalEnv <- ask + liftIO $ modifyIORef' e.internal_state_ref $ subscribeFn e.scope val k + +-- | Loop until transaction queue is empty. TODO: Is this even +-- worth-while to have? What if just let multiple DOM changes when it +-- depends on several sources? +trampoline :: ClickM a -> ClickM a +trampoline act = loop0 act where + loop0 :: ClickM a -> ClickM a + loop0 before = do + r <- before + mcont <- popQueue + forM_ mcont loop1 + return r + loop1 :: ClickM () -> ClickM () + loop1 before = do + before + mcont <- popQueue + forM_ mcont loop1 + popQueue :: ClickM (Maybe (ClickM ())) + popQueue = state \s -> + case Map.minViewWithKey s.transaction_queue of + Nothing -> (Nothing, s) + Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) + +defer :: RefId -> ClickM () -> InternalState -> InternalState +defer k act s = s { transaction_queue = Map.insert k act s.transaction_queue } + +------------------ +-- BUILDING DOM -- +------------------ + +el :: Text -> HtmlM a -> HtmlM a +el t ch = do + r <- ask + el <- liftIO $ insertElement r t + local (const el) ch + +property :: Text -> Text -> HtmlM () +property k v = do + root <- ask + liftIO $ setProperty root k v + +boolProperty :: Text -> Bool -> HtmlM () +boolProperty k v = do + root <- ask + liftIO $ setBoolProperty root k v + +attribute :: Text -> Text -> HtmlM () +attribute k v = do + root <- ask + liftIO $ setAttribute root k v + +text :: Text -> HtmlM () +text t = do + r <- ask + void $ liftIO $ insertText r t + +dynText :: DynVal Text -> HtmlM () +dynText val = do + r <- ask + t <- liftClickM $ readVal val + textNode <- liftIO $ insertText r t + liftClickM $ subscribe val $ \new -> + liftIO $ updateTextContent textNode new + +dynProp :: Text -> DynVal Text -> HtmlM () +dynProp k val = do + root <- ask + v <- liftClickM $ readVal val + liftIO $ setProperty root k v + liftClickM $ subscribe val $ \new -> + liftIO $ setProperty root k new + +dynBoolProp :: Text -> DynVal Bool -> HtmlM () +dynBoolProp k val = do + root <- ask + v <- liftClickM $ readVal val + liftIO $ setBoolProperty root k v + liftClickM $ subscribe val $ \new -> + liftIO $ setBoolProperty root k new + +blank :: Applicative m => m () +blank = pure () + +--------------------- +-- DYNAMIC CONTENT -- +--------------------- + +dyn :: DynVal (HtmlM ()) -> HtmlM () +dyn val = do + root <- ask + scope <- liftClickM newScope + closeBracket <- liftIO $ js_insertBrackets root + initialVal <- liftClickM $ readVal val + let + update html = do + liftIO $ js_clearBrackets closeBracket + html + exec = local (\s -> s {scope}) . + flip runReaderT closeBracket . unHtmlM + liftClickM $ exec $ update initialVal + liftClickM $ subscribe val \newVal -> do + freeScope False scope + exec $ update newVal + return () + +-------------------------- +-- START AN APPLICATION -- +-------------------------- + +attach :: HtmlM a -> IO a +attach html = do + body <- documentBody + env <- newInternalEnv + html.unHtmlM + & flip runReaderT body + & unClickM + & flip runReaderT env diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs new file mode 100644 index 0000000..e192511 --- /dev/null +++ b/src/Clickable/DOM.hs @@ -0,0 +1,256 @@ +module Clickable.DOM where + +import Control.Monad +import Data.Bifunctor +import Control.Monad.Identity +import Control.Monad.Reader +import Control.Monad.Trans +import Control.Monad.State +import Data.Foldable +import Data.Function ((&)) +import Data.IORef +import Data.List qualified as List +import Data.Text (Text) +import Data.Tuple +import Data.Typeable +import Data.Map (Map) +import Data.Set (Set) +import Data.Kind +import Data.Map qualified as Map +import GHC.Generics +import GHC.Exts hiding (build) +import GHC.TypeLits +import Unsafe.Coerce + +import Clickable.FFI qualified as FFI +import Clickable.Core +import Wasm.Compat.Prim +import Wasm.Compat.Marshal + + +data EventListenerOptions = EventListenerOptions + { prevent_default :: Bool + , stop_propagation :: Bool + } deriving stock (Generic, Show, Eq) + +defaultEventListenerOptions :: EventListenerOptions +defaultEventListenerOptions = EventListenerOptions + { prevent_default = False + , stop_propagation = False + } + +addEventListener :: ConnectResourceArgs callback -> callback -> HtmlM () +addEventListener args k = do + rootElement <- ask + liftClickM $ connectResource rootElement args k + +data ConnectResourceArgs callback = ConnectResourceArgs + { js_wrapper :: RawJavaScript + , mk_callback :: callback -> JSVal -> ClickM () + } + +connectResource :: JSVal -> ConnectResourceArgs callback -> callback -> ClickM () +connectResource target args k = do + env <- ask + let hsCallback' = (`runReaderT` env) . unClickM . args.mk_callback k + hsCallback'' <- liftIO $ FFI.js_dynExport hsCallback' + cancel <- liftIO $ FFI.aquireResource target args.js_wrapper.unRawJavaScript hsCallback'' + installFinalizer do + liftIO $ FFI.apply0 cancel + liftIO $ freeJSVal hsCallback'' + +on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HtmlM () +on k = addEventListener (addEventListenerArgs @eventName) k + +class IsEventName eventName where + type EventListenerCb eventName :: Type + addEventListenerArgs :: ConnectResourceArgs (EventListenerCb eventName) + +instance IsEventName "click" where + type EventListenerCb "click" = ClickM () + addEventListenerArgs = pointerConnectArgs "click" + +instance IsEventName "mousedown" where + type EventListenerCb "mousedown" = ClickM () + addEventListenerArgs = pointerConnectArgs "mousedown" + +instance IsEventName "mouseup" where + type EventListenerCb "mouseup" = ClickM () + addEventListenerArgs = pointerConnectArgs "mouseup" + +instance IsEventName "dblclick" where + type EventListenerCb "dblclick" = ClickM () + addEventListenerArgs = pointerConnectArgs "dblclick" + +instance IsEventName "submit" where + type EventListenerCb "submit" = ClickM () + addEventListenerArgs = submitConnectArgs + +instance IsEventName "input" where + type EventListenerCb "input" = Text -> ClickM () + addEventListenerArgs = inputConnectArgs "input" + +instance IsEventName "keydown" where + type EventListenerCb "keydown" = Int -> ClickM () + addEventListenerArgs = keyboardConnectArgs "keydown" + +instance IsEventName "keyup" where + type EventListenerCb "keyup" = Int -> ClickM () + addEventListenerArgs = keyboardConnectArgs "keyup" + +instance IsEventName "focus" where + type EventListenerCb "focus" = ClickM () + addEventListenerArgs = pointerConnectArgs "focus" + +instance IsEventName "blur" where + type EventListenerCb "blur" = ClickM () + addEventListenerArgs = pointerConnectArgs "blur" + +instance IsEventName "input/blur" where + type EventListenerCb "input/blur" = Text -> ClickM () + addEventListenerArgs = inputConnectArgs "blur" + +instance IsEventName "input/focus" where + type EventListenerCb "input/focus" = Text -> ClickM () + addEventListenerArgs = inputConnectArgs "focus" + +instance IsEventName "checkbox/change" where + type EventListenerCb "checkbox/change" = Bool -> ClickM () + addEventListenerArgs = checkboxChangeConnectArgs + +instance IsEventName "select/change" where + type EventListenerCb "select/change" = Text -> ClickM () + addEventListenerArgs = selectChangeConnectArgs + +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event +pointerConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) +pointerConnectArgs eventName = ConnectResourceArgs + { js_wrapper = normalEventWrapper eventName defaultEventListenerOptions + , mk_callback = \k _ -> k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event +submitConnectArgs :: ConnectResourceArgs (ClickM ()) +submitConnectArgs = ConnectResourceArgs + { js_wrapper = normalEventWrapper "submit" EventListenerOptions + { prevent_default = True + , stop_propagation = True + } + , mk_callback = \k _ -> k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event +inputConnectArgs :: Text -> ConnectResourceArgs (Text -> ClickM ()) +inputConnectArgs eventName = ConnectResourceArgs + { js_wrapper = + "(function(target, haskellCb){\n\ + \ function listener(target){\n\ + \ haskellCb(event.target.value);\n\ + \ }\n\ + \ window.addEventListener('" <> RawJavaScript eventName <> "', listener);\n\ + \ return () => window.removeEventListener('" <> RawJavaScript eventName <> "', listener);\n\ + \})" + , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event +keyboardConnectArgs :: Text -> ConnectResourceArgs (Int -> ClickM ()) +keyboardConnectArgs eventName = ConnectResourceArgs + { js_wrapper = + "(function(target, haskellCb){\n\ + \ function listener(target){\n\ + \ haskellCb(event.target.value);\n\ + \ }\n\ + \ window.addEventListener('" <> RawJavaScript eventName <> "', listener);\n\ + \ return () => window.removeEventListener('" <> RawJavaScript eventName <> "', listener);\n\ + \})" + , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event +focusConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) +focusConnectArgs eventName = ConnectResourceArgs + { js_wrapper = normalEventWrapper eventName defaultEventListenerOptions + , mk_callback = \k _ -> k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event +checkboxChangeConnectArgs :: ConnectResourceArgs (Bool -> ClickM ()) +checkboxChangeConnectArgs = ConnectResourceArgs + { js_wrapper = + "(function(target, haskellCb){\n\ + \ function listener(target){\n\ + \ haskellCb(event.target.checked);\n\ + \ }\n\ + \ window.addEventListener('change', listener);\n\ + \ return () => window.removeEventListener('change', listener);\n\ + \})" + , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + } + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event +selectChangeConnectArgs :: ConnectResourceArgs (Text -> ClickM ()) +selectChangeConnectArgs = ConnectResourceArgs + { js_wrapper = + "(function(target, haskellCb){\n\ + \ function listener(target){\n\ + \ haskellCb(event.target.value);\n\ + \ }\n\ + \ window.addEventListener('change', listener);\n\ + \ return () => window.removeEventListener('change', listener);\n\ + \})" + , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + } + +normalEventWrapper :: Text -> EventListenerOptions -> RawJavaScript +normalEventWrapper eventName opt = + "(function(target, haskellCb){\n\ + \ function listener(event){\n\ + \ " <> preventDefaultStmt <> ";\n\ + \ " <> stopPropagationStmt <> ";\n\ + \ haskellCb(event);\n\ + \ }\n\ + \ target.addEventListener('" <> RawJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener(" <> RawJavaScript eventName <> ", listener);\n\ + \})" + where + preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" + stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" + +data Location = Location + { protocol :: Text + -- ^ A string containing the protocol scheme of the URL, including + -- the final ':' + , hostname :: Text + -- ^ A string containing the domain of the URL. + , port :: Text + -- ^ A string containing the port number of the URL. + , pathname :: Text + -- ^ A string containing an initial '/' followed by the path of the + -- URL, not including the query string or fragment. + , search :: Text + -- ^ A string containing a '?' followed by the parameters or + -- "querystring" of the URL + , hash :: Text + -- ^ A string containing a '#' followed by the fragment identifier + -- of the URL. + } deriving stock (Show, Eq, Generic) + deriving anyclass (FromJSVal, ToJSVal) + +-- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event +popstateConnectArgs :: ConnectResourceArgs (Location -> ClickM ()) +popstateConnectArgs = ConnectResourceArgs + { js_wrapper = + "(function(target, haskellCb){\n\ + \ function listener(){\n\ + \ haskellCb(location);\n\ + \ }\n\ + \ target.addEventListener('popstate', listener);\n\ + \ return () => target.removeEventListener('popstate', listener);\n\ + \})" + , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + } diff --git a/src/Clickable/Element.hs b/src/Clickable/Element.hs new file mode 100644 index 0000000..0753290 --- /dev/null +++ b/src/Clickable/Element.hs @@ -0,0 +1,402 @@ +{-| +Shortcuts for most common HTML5 elements +-} +module Clickable.Element where + +import Clickable.Core +import Wasm.Compat.Prim +import Data.Text + +-- | This typeclass allows for tag constructors to have variable +-- length arguments. Each tag constructor like 'div_' defined below +-- can be called with one or two arguments +-- +-- > div_ $ text "A Div without attributes" +-- > div_ [class_ "wrapper"] $ text "A Div with a class" +-- +-- Unceremoniously copied from the amazing @lucid@ library, see +-- https://github.com/chrisdone/lucid/blob/fb3b0e7c189c2acd8d88838d4a13923f24542ee8/src/Lucid/Base.hs#L272 +class Term arg result | result -> arg where + term + :: Text -- ^ Name. + -> arg -- ^ Some argument. + -> result -- ^ Result: either an element or an attribute. + +-- | Given attributes, expect more child input. +instance f ~ HtmlM a => Term [HtmlM ()] (f -> HtmlM a) where + term name attrs = el name . (sequence_ attrs *>) + {-# INLINE term #-} + +-- | Given children immediately, just use that and expect no +-- attributes. +instance Term (HtmlM a) (HtmlM a) where + term = el + {-# INLINE term #-} + +div_ :: Term arg result => arg -> result +div_ = term "div" +{-# INLINE div_ #-} + +table_ :: Term arg result => arg -> result +table_ = term "table" +{-# INLINE table_ #-} + +thead_ :: Term arg result => arg -> result +thead_ = term "thead" +{-# INLINE thead_ #-} + +tbody_ :: Term arg result => arg -> result +tbody_ = term "tbody" +{-# INLINE tbody_ #-} + +tr_ :: Term arg result => arg -> result +tr_ = term "tr" +{-# INLINE tr_ #-} + +th_ :: Term arg result => arg -> result +th_ = term "th" +{-# INLINE th_ #-} + +td_ :: Term arg result => arg -> result +td_ = term "td" +{-# INLINE td_ #-} + +tfoot_ :: Term arg result => arg -> result +tfoot_ = term "tfoot" +{-# INLINE tfoot_ #-} + +section_ :: Term arg result => arg -> result +section_ = term "section" +{-# INLINE section_ #-} + +header_ :: Term arg result => arg -> result +header_ = term "header" +{-# INLINE header_ #-} + +footer_ :: Term arg result => arg -> result +footer_ = term "footer" +{-# INLINE footer_ #-} + +button_ :: Term arg result => arg -> result +button_ = term "button" +{-# INLINE button_ #-} + +form_ :: Term arg result => arg -> result +form_ = term "form" +{-# INLINE form_ #-} + +p_ :: Term arg result => arg -> result +p_ = term "p" +{-# INLINE p_ #-} + +s_ :: Term arg result => arg -> result +s_ = term "s" +{-# INLINE s_ #-} + +ul_ :: Term arg result => arg -> result +ul_ = term "ul" +{-# INLINE ul_ #-} + +span_ :: Term arg result => arg -> result +span_ = term "span" +{-# INLINE span_ #-} + +strong_ :: Term arg result => arg -> result +strong_ = term "strong" +{-# INLINE strong_ #-} + +li_ :: Term arg result => arg -> result +li_ = term "li" +{-# INLINE li_ #-} + +h1_ :: Term arg result => arg -> result +h1_ = term "h1" +{-# INLINE h1_ #-} + +h2_ :: Term arg result => arg -> result +h2_ = term "h2" +{-# INLINE h2_ #-} + +h3_ :: Term arg result => arg -> result +h3_ = term "h3" +{-# INLINE h3_ #-} + +h4_ :: Term arg result => arg -> result +h4_ = term "h4" +{-# INLINE h4_ #-} + +h5_ :: Term arg result => arg -> result +h5_ = term "h5" +{-# INLINE h5_ #-} + +h6_ :: Term arg result => arg -> result +h6_ = term "h6" +{-# INLINE h6_ #-} + +hr_ :: Term arg result => arg -> result +hr_ = term "hr" +{-# INLINE hr_ #-} + +pre_ :: Term arg result => arg -> result +pre_ = term "pre" +{-# INLINE pre_ #-} + +input_ :: Term arg result => arg -> result +input_ = term "input" +{-# INLINE input_ #-} + +label_ :: Term arg result => arg -> result +label_ = term "label" +{-# INLINE label_ #-} + +a_ :: Term arg result => arg -> result +a_ = term "a" +{-# INLINE a_ #-} + +details_ :: Term arg result => arg -> result +details_ = term "details" +{-# INLINE details_ #-} + +summary_ :: Term arg result => arg -> result +summary_ = term "summary" +{-# INLINE summary_ #-} + +menuitem_ :: Term arg result => arg -> result +menuitem_ = term "menuitem" +{-# INLINE menuitem_ #-} + +menu_ :: Term arg result => arg -> result +menu_ = term "menu" +{-# INLINE menu_ #-} + +fieldset_ :: Term arg result => arg -> result +fieldset_ = term "fieldset" +{-# INLINE fieldset_ #-} + +legend_ :: Term arg result => arg -> result +legend_ = term "legend" +{-# INLINE legend_ #-} + +datalist_ :: Term arg result => arg -> result +datalist_ = term "datalist" +{-# INLINE datalist_ #-} + +optgroup_ :: Term arg result => arg -> result +optgroup_ = term "optgroup" +{-# INLINE optgroup_ #-} + +progress_ :: Term arg result => arg -> result +progress_ = term "progress" +{-# INLINE progress_ #-} + +meter_ :: Term arg result => arg -> result +meter_ = term "meter" +{-# INLINE meter_ #-} + +center_ :: Term arg result => arg -> result +center_ = term "center" +{-# INLINE center_ #-} + +audio_ :: Term arg result => arg -> result +audio_ = term "audio" +{-# INLINE audio_ #-} + +video_ :: Term arg result => arg -> result +video_ = term "video" +{-# INLINE video_ #-} + +source_ :: Term arg result => arg -> result +source_ = term "source" +{-# INLINE source_ #-} + +track_ :: Term arg result => arg -> result +track_ = term "track" +{-# INLINE track_ #-} + +embed_ :: Term arg result => arg -> result +embed_ = term "embed" +{-# INLINE embed_ #-} + +object_ :: Term arg result => arg -> result +object_ = term "object" +{-# INLINE object_ #-} + +param_ :: Term arg result => arg -> result +param_ = term "param" +{-# INLINE param_ #-} + +ins_ :: Term arg result => arg -> result +ins_ = term "ins" +{-# INLINE ins_ #-} + +del_ :: Term arg result => arg -> result +del_ = term "del" +{-# INLINE del_ #-} + +small_ :: Term arg result => arg -> result +small_ = term "small" +{-# INLINE small_ #-} + +cite_ :: Term arg result => arg -> result +cite_ = term "cite" +{-# INLINE cite_ #-} + +dfn_ :: Term arg result => arg -> result +dfn_ = term "dfn" +{-# INLINE dfn_ #-} + +abbr_ :: Term arg result => arg -> result +abbr_ = term "abbr" +{-# INLINE abbr_ #-} + +time_ :: Term arg result => arg -> result +time_ = term "time" +{-# INLINE time_ #-} + +var_ :: Term arg result => arg -> result +var_ = term "var" +{-# INLINE var_ #-} + +samp_ :: Term arg result => arg -> result +samp_ = term "samp" +{-# INLINE samp_ #-} + +kbd_ :: Term arg result => arg -> result +kbd_ = term "kbd" +{-# INLINE kbd_ #-} + +caption_ :: Term arg result => arg -> result +caption_ = term "caption" +{-# INLINE caption_ #-} + +colgroup_ :: Term arg result => arg -> result +colgroup_ = term "colgroup" +{-# INLINE colgroup_ #-} + +col_ :: Term arg result => arg -> result +col_ = term "col" +{-# INLINE col_ #-} + +nav_ :: Term arg result => arg -> result +nav_ = term "nav" +{-# INLINE nav_ #-} + +article_ :: Term arg result => arg -> result +article_ = term "article" +{-# INLINE article_ #-} + +aside_ :: Term arg result => arg -> result +aside_ = term "aside" +{-# INLINE aside_ #-} + +address_ :: Term arg result => arg -> result +address_ = term "address" +{-# INLINE address_ #-} + +main_ :: Term arg result => arg -> result +main_ = term "main" +{-# INLINE main_ #-} + +body_ :: Term arg result => arg -> result +body_ = term "body" +{-# INLINE body_ #-} + +figure_ :: Term arg result => arg -> result +figure_ = term "figure" +{-# INLINE figure_ #-} + +figcaption_ :: Term arg result => arg -> result +figcaption_ = term "figcaption" +{-# INLINE figcaption_ #-} + +dl_ :: Term arg result => arg -> result +dl_ = term "dl" +{-# INLINE dl_ #-} + +dt_ :: Term arg result => arg -> result +dt_ = term "dt" +{-# INLINE dt_ #-} + +dd_ :: Term arg result => arg -> result +dd_ = term "dd" +{-# INLINE dd_ #-} + +img_ :: Term arg result => arg -> result +img_ = term "img" +{-# INLINE img_ #-} + +iframe_ :: Term arg result => arg -> result +iframe_ = term "iframe" +{-# INLINE iframe_ #-} + +canvas_ :: Term arg result => arg -> result +canvas_ = term "canvas" +{-# INLINE canvas_ #-} + +math_ :: Term arg result => arg -> result +math_ = term "math" +{-# INLINE math_ #-} + +select_ :: Term arg result => arg -> result +select_ = term "select" +{-# INLINE select_ #-} + +option_ :: Term arg result => arg -> result +option_ = term "option" +{-# INLINE option_ #-} + +textarea_ :: Term arg result => arg -> result +textarea_ = term "textarea" +{-# INLINE textarea_ #-} + +sub_ :: Term arg result => arg -> result +sub_ = term "sub" +{-# INLINE sub_ #-} + +sup_ :: Term arg result => arg -> result +sup_ = term "sup" +{-# INLINE sup_ #-} + +br_ :: HtmlM () +br_ = el "br" blank +{-# INLINE br_ #-} + +ol_ :: Term arg result => arg -> result +ol_ = term "ol" +{-# INLINE ol_ #-} + +blockquote_ :: Term arg result => arg -> result +blockquote_ = term "blockquote" +{-# INLINE blockquote_ #-} + +code_ :: Term arg result => arg -> result +code_ = term "code" +{-# INLINE code_ #-} + +em_ :: Term arg result => arg -> result +em_ = term "em" +{-# INLINE em_ #-} + +i_ :: Term arg result => arg -> result +i_ = term "i" +{-# INLINE i_ #-} + +b_ :: Term arg result => arg -> result +b_ = term "b" +{-# INLINE b_ #-} + +u_ :: Term arg result => arg -> result +u_ = term "u" +{-# INLINE u_ #-} + +q_ :: Term arg result => arg -> result +q_ = term "q" +{-# INLINE q_ #-} + +script_ :: Term arg result => arg -> result +script_ = term "script" +{-# INLINE script_ #-} + +link_ :: Term arg result => arg -> result +link_ = term "link" +{-# INLINE link_ #-} diff --git a/src/Clickable/FFI.hs b/src/Clickable/FFI.hs index bf05d86..09f67c8 100644 --- a/src/Clickable/FFI.hs +++ b/src/Clickable/FFI.hs @@ -40,16 +40,40 @@ setProperty root (Text (ByteArray arr0) off0 len0) (Text (ByteArray arr1) off1 l let addr1 = byteArrayContents# arr1 js_setProperty root (Ptr addr0 `plusPtr` off0) len0 (Ptr addr1 `plusPtr` off1) len1 +setBoolProperty :: JSVal -> Text -> Bool -> IO () +setBoolProperty root (Text (ByteArray arr0) off0 len0) val = do + let addr0 = byteArrayContents# arr0 + js_setBoolProperty root (Ptr addr0 `plusPtr` off0) len0 (if val then 1 else 0) + +setAttribute :: JSVal -> Text -> Text -> IO () +setAttribute root (Text (ByteArray arr0) off0 len0) (Text (ByteArray arr1) off1 len1) = do + let addr0 = byteArrayContents# arr0 + let addr1 = byteArrayContents# arr1 + js_setAttribute root (Ptr addr0 `plusPtr` off0) len0 (Ptr addr1 `plusPtr` off1) len1 + addEventListener :: JSVal -> Text -> JSVal -> IO () addEventListener root (Text (ByteArray arr) off len) lisnr = do let addr = byteArrayContents# arr js_addEventListener root (Ptr addr `plusPtr` off) len lisnr +removeEventListener :: JSVal -> Text -> JSVal -> IO () +removeEventListener root (Text (ByteArray arr) off len) lisnr = do + let addr = byteArrayContents# arr + js_removeEventListener root (Ptr addr `plusPtr` off) len lisnr + consoleLog :: MonadIO m => Text -> m () consoleLog (Text (ByteArray arr) off len) = liftIO do let addr = byteArrayContents# arr js_consoleLog (Ptr addr `plusPtr` off) len +aquireResource :: JSVal -> Text -> JSVal -> IO JSVal +aquireResource root (Text (ByteArray arr) off len) lisnr = do + let addr = byteArrayContents# arr + js_aquireResource root (Ptr addr `plusPtr` off) len lisnr + +apply0 :: JSVal -> IO () +apply0 = js_apply0 + #if !defined(wasm32_HOST_ARCH) js_insertText :: JSVal -> Ptr Word8 -> Int -> IO JSVal js_insertText = undefined @@ -63,9 +87,18 @@ js_updateTextContent = undefined js_setProperty :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () js_setProperty = undefined +js_setBoolProperty :: JSVal -> Ptr Word8 -> Int -> Int -> IO () +js_setBoolProperty = undefined + +js_setAttribute :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () +js_setAttribute = undefined + js_addEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () js_addEventListener = undefined +js_removeEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () +js_removeEventListener = undefined + js_dynExport :: (JSVal -> IO ()) -> IO JSVal js_dynExport = undefined @@ -81,6 +114,12 @@ js_insertBrackets = undefined js_clearBrackets :: JSVal -> IO () js_clearBrackets = undefined +js_aquireResource :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO JSVal +js_aquireResource = undefined + +js_apply0 :: JSVal -> IO () +js_apply0 = undefined + #else foreign import javascript unsafe "var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ @@ -114,6 +153,23 @@ foreign import javascript unsafe $1[k] = v;\ }" js_setProperty :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () +foreign import javascript unsafe + "var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ + if ($1 instanceof Comment) {\ + $1.parentNode[k] = $4 == 0 ? false : true;\ + } else {\ + $1[k] = $4 == 0 ? false : true;\ + }" + js_setBoolProperty :: JSVal -> Ptr Word8 -> Int -> Int -> IO () +foreign import javascript unsafe + "var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ + var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5));\ + if ($1 instanceof Comment) {\ + $1.parentNode.setAttribute(k, v);\ + } else {\ + $1.setAttribute(k, v);\ + }" + js_setAttribute :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () foreign import javascript unsafe "document.body" documentBody :: IO JSVal foreign import javascript unsafe "var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ @@ -123,6 +179,14 @@ foreign import javascript unsafe $1.addEventListener(e, $4);\ }" js_addEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () +foreign import javascript unsafe + "var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ + if ($1 instanceof Comment) {\ + $1.parentNode.addEventListener(e, $4);\ + } else {\ + $1.removeEventListener(e, $4);\ + }" + js_removeEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () foreign import javascript "wrapper" js_dynExport :: (JSVal -> IO ()) -> IO JSVal foreign import javascript unsafe "console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));" @@ -153,4 +217,14 @@ foreign import javascript unsafe iter.previousSibling.parentNode.removeChild(iter.previousSibling);\ }" js_clearBrackets :: JSVal -> IO () +foreign import javascript unsafe + "var j = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ + if ($1 instanceof Comment) {\ + return eval(j)($1.parentNode, $4);\ + } else {\ + return eval(j)($1, $4);\ + }" + js_aquireResource :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO JSVal +foreign import javascript unsafe + "$1()" js_apply0 :: JSVal -> IO () #endif diff --git a/src/Clickable/Property.hs b/src/Clickable/Property.hs new file mode 100644 index 0000000..d807a0d --- /dev/null +++ b/src/Clickable/Property.hs @@ -0,0 +1,366 @@ +{-| +Shortcuts for common HTML5 attributes and properties +-} +module Clickable.Property where + +import Clickable.Core +import Data.Text +import Wasm.Compat.Prim + + +-- TODO: Real-world usage has demonstrated that 'dynStyles' not +-- sufficiently composable. For instance, if 'dynStyles' is used to +-- set the CSS color for an element, essentially no other CSS property +-- can be applied to this element, as they will be overwritten by +-- 'dynStyles'. +dynStyles :: DynVal Text -> HtmlM () +dynStyles = dynProp "style" +{-# INLINE dynStyles #-} + +dynValue :: DynVal Text -> HtmlM () +dynValue = dynProp "value" +{-# INLINE dynValue #-} + +dynClass :: DynVal Text -> HtmlM () +dynClass = dynProp "className" +{-# INLINE dynClass #-} + +dynChecked :: DynVal Bool -> HtmlM () +dynChecked = dynBoolProp "checked" +{-# INLINE dynChecked #-} + +dynDisabled :: DynVal Bool -> HtmlM () +dynDisabled = dynBoolProp "disabled" +{-# INLINE dynDisabled #-} + +title_ :: Text -> HtmlM () +title_ = property "title" +{-# INLINE title_ #-} + +selected_ :: Bool -> HtmlM () +selected_ = boolProperty "selected" +{-# INLINE selected_ #-} + +hidden_ :: Bool -> HtmlM () +hidden_ = boolProperty "hidden" +{-# INLINE hidden_ #-} + +value_ :: Text -> HtmlM () +value_ = property "value" +{-# INLINE value_ #-} + +defaultValue_ :: Text -> HtmlM () +defaultValue_ = property "defaultValue" +{-# INLINE defaultValue_ #-} + +accept_ :: Text -> HtmlM () +accept_ = property "accept" +{-# INLINE accept_ #-} + +acceptCharset_ :: Text -> HtmlM () +acceptCharset_ = property "acceptCharset" +{-# INLINE acceptCharset_ #-} + +action_ :: Text -> HtmlM () +action_ = property "action" +{-# INLINE action_ #-} + +autocomplete_ :: Bool -> HtmlM () +autocomplete_ b = property "autocomplete" (if b then "on" else "off") +{-# INLINE autocomplete_ #-} + +autosave_ :: Text -> HtmlM () +autosave_ = property "autosave" +{-# INLINE autosave_ #-} + +disabled_ :: Bool -> HtmlM () +disabled_ = boolProperty "disabled" +{-# INLINE disabled_ #-} + +enctype_ :: Text -> HtmlM () +enctype_ = property "enctype" +{-# INLINE enctype_ #-} + +formation_ :: Text -> HtmlM () +formation_ = property "formation" +{-# INLINE formation_ #-} + +list_ :: Text -> HtmlM () +list_ = property "list" +{-# INLINE list_ #-} + +maxlength_ :: Text -> HtmlM () +maxlength_ = property "maxlength" +{-# INLINE maxlength_ #-} + +minlength_ :: Text -> HtmlM () +minlength_ = property "minlength" +{-# INLINE minlength_ #-} + +method_ :: Text -> HtmlM () +method_ = property "method" +{-# INLINE method_ #-} + +multiple_ :: Bool -> HtmlM () +multiple_ = boolProperty "multiple" +{-# INLINE multiple_ #-} + +novalidate_ :: Bool -> HtmlM () +novalidate_ = boolProperty "noValidate" +{-# INLINE novalidate_ #-} + +pattern_ :: Text -> HtmlM () +pattern_ = property "pattern" +{-# INLINE pattern_ #-} + +readonly_ :: Bool -> HtmlM () +readonly_ = boolProperty "readOnly" +{-# INLINE readonly_ #-} + +required_ :: Bool -> HtmlM () +required_ = boolProperty "required" +{-# INLINE required_ #-} + +size_ :: Text -> HtmlM () +size_ = property "size" +{-# INLINE size_ #-} + +forProp_ :: Text -> HtmlM () +forProp_ = property "for" +{-# INLINE forProp_ #-} + +ref_ :: Text -> HtmlM () +ref_ = property "ref" +{-# INLINE ref_ #-} + +formProp_ :: Text -> HtmlM () +formProp_ = property "form" +{-# INLINE formProp_ #-} + +max_ :: Text -> HtmlM () +max_ = property "max" +{-# INLINE max_ #-} + +min_ :: Text -> HtmlM () +min_ = property "min" +{-# INLINE min_ #-} + +step_ :: Text -> HtmlM () +step_ = property "step" +{-# INLINE step_ #-} + +cols_ :: Text -> HtmlM () +cols_ = property "cols" +{-# INLINE cols_ #-} + +rows_ :: Text -> HtmlM () +rows_ = property "rows" +{-# INLINE rows_ #-} + +wrap_ :: Text -> HtmlM () +wrap_ = property "wrap" +{-# INLINE wrap_ #-} + +target_ :: Text -> HtmlM () +target_ = property "target" +{-# INLINE target_ #-} + +download_ :: Text -> HtmlM () +download_ = property "download" +{-# INLINE download_ #-} + +downloadAs_ :: Text -> HtmlM () +downloadAs_ = property "downloadAs" +{-# INLINE downloadAs_ #-} + +hreflang_ :: Text -> HtmlM () +hreflang_ = property "hreflang" +{-# INLINE hreflang_ #-} + +media_ :: Text -> HtmlM () +media_ = property "media" +{-# INLINE media_ #-} + +ping_ :: Text -> HtmlM () +ping_ = property "ping" +{-# INLINE ping_ #-} + +rel_ :: Text -> HtmlM () +rel_ = property "rel" +{-# INLINE rel_ #-} + +ismap_ :: Text -> HtmlM () +ismap_ = property "ismap" +{-# INLINE ismap_ #-} + +usemap_ :: Text -> HtmlM () +usemap_ = property "usemap" +{-# INLINE usemap_ #-} + +shape_ :: Text -> HtmlM () +shape_ = property "shape" +{-# INLINE shape_ #-} + +coords_ :: Text -> HtmlM () +coords_ = property "coords" +{-# INLINE coords_ #-} + +src_ :: Text -> HtmlM () +src_ = property "src" +{-# INLINE src_ #-} + +height_ :: Text -> HtmlM () +height_ = property "height" +{-# INLINE height_ #-} + +width_ :: Text -> HtmlM () +width_ = property "width" +{-# INLINE width_ #-} + +alt_ :: Text -> HtmlM () +alt_ = property "alt" +{-# INLINE alt_ #-} + +autoplay_ :: Bool -> HtmlM () +autoplay_ = boolProperty "autoplay" +{-# INLINE autoplay_ #-} + +controls_ :: Bool -> HtmlM () +controls_ = boolProperty "controls" +{-# INLINE controls_ #-} + +loop_ :: Bool -> HtmlM () +loop_ = boolProperty "loop" +{-# INLINE loop_ #-} + +preload_ :: Text -> HtmlM () +preload_ = property "preload" +{-# INLINE preload_ #-} + +poster_ :: Text -> HtmlM () +poster_ = property "poster" +{-# INLINE poster_ #-} + +default_ :: Bool -> HtmlM () +default_ = boolProperty "default" +{-# INLINE default_ #-} + +kind_ :: Text -> HtmlM () +kind_ = property "kind" +{-# INLINE kind_ #-} + +srclang_ :: Text -> HtmlM () +srclang_ = property "srclang" +{-# INLINE srclang_ #-} + +sandbox_ :: Text -> HtmlM () +sandbox_ = property "sandbox" +{-# INLINE sandbox_ #-} + +seamless_ :: Text -> HtmlM () +seamless_ = property "seamless" +{-# INLINE seamless_ #-} + +srcdoc_ :: Text -> HtmlM () +srcdoc_ = property "srcdoc" +{-# INLINE srcdoc_ #-} + +reversed_ :: Text -> HtmlM () +reversed_ = property "reversed" +{-# INLINE reversed_ #-} + +start_ :: Text -> HtmlM () +start_ = property "start" +{-# INLINE start_ #-} + +align_ :: Text -> HtmlM () +align_ = property "align" +{-# INLINE align_ #-} + +colspan_ :: Text -> HtmlM () +colspan_ = attribute "colspan" +{-# INLINE colspan_ #-} + +rowspan_ :: Text -> HtmlM () +rowspan_ = attribute "rowspan" +{-# INLINE rowspan_ #-} + +headers_ :: Text -> HtmlM () +headers_ = property "headers" +{-# INLINE headers_ #-} + +scope_ :: Text -> HtmlM () +scope_ = property "scope" +{-# INLINE scope_ #-} + +async_ :: Text -> HtmlM () +async_ = property "async" +{-# INLINE async_ #-} + +charset_ :: Text -> HtmlM () +charset_ = property "charset" +{-# INLINE charset_ #-} + +content_ :: Text -> HtmlM () +content_ = property "content" +{-# INLINE content_ #-} + +defer_ :: Text -> HtmlM () +defer_ = property "defer" +{-# INLINE defer_ #-} + +httpEquiv_ :: Text -> HtmlM () +httpEquiv_ = property "httpEquiv" +{-# INLINE httpEquiv_ #-} + +language_ :: Text -> HtmlM () +language_ = property "language" +{-# INLINE language_ #-} + +scoped_ :: Text -> HtmlM () +scoped_ = property "scoped" +{-# INLINE scoped_ #-} + +type_ :: Text -> HtmlM () +type_ = property "type" +{-# INLINE type_ #-} + +name_ :: Text -> HtmlM () +name_ = property "name" +{-# INLINE name_ #-} + +href_ :: Text -> HtmlM () +href_ = property "href" +{-# INLINE href_ #-} + +id_ :: Text -> HtmlM () +id_ = property "id" +{-# INLINE id_ #-} + +placeholder_ :: Text -> HtmlM () +placeholder_ = property "placeholder" +{-# INLINE placeholder_ #-} + +checked_ :: Bool -> HtmlM () +checked_ = boolProperty "checked" +{-# INLINE checked_ #-} + +autofocus_ :: Bool -> HtmlM () +autofocus_ = boolProperty "autofocus" +{-# INLINE autofocus_ #-} + +class_ :: Text -> HtmlM () +class_ = property "className" +{-# INLINE class_ #-} + +data_ :: Text -> Text -> HtmlM () +data_ k v = property ("data-" <> k) v +{-# INLINE data_ #-} + +role_ :: Text -> HtmlM () +role_ = attribute "role" +{-# INLINE role_ #-} + +style_ :: Text -> HtmlM () +style_ = property "style" +{-# INLINE style_ #-} diff --git a/src/Wasm/Compat/Marshal.hs b/src/Wasm/Compat/Marshal.hs index b534ea8..d09f3aa 100644 --- a/src/Wasm/Compat/Marshal.hs +++ b/src/Wasm/Compat/Marshal.hs @@ -11,11 +11,15 @@ module Wasm.Compat.Marshal where import Control.Monad import Data.Maybe import Data.String +import Data.Text qualified as Text +import Data.List qualified as List import Data.Coerce +import Data.Kind import Wasm.Compat.Prim import GHC.Prim import GHC.Ptr import GHC.Int +import GHC.Generics as G import GHC.IO import Data.Text.Internal import Data.Array.Byte @@ -40,8 +44,25 @@ pattern TypeNumber = TypeResult 2 pattern TypeString = TypeResult 3 pattern TypeArray = TypeResult 4 pattern TypeObject = TypeResult 5 +-------------------------------------------------------------------------------- -class FromJSVal v where fromJSVal :: JSVal -> IO (Maybe v) +instance IsString JSString where fromString = toJSString + +instance Semigroup JSString where (<>) = js_concatStr + +instance Monoid JSString where mempty = js_emptyStr + +instance Eq JSString where (==) a b = fromJSString a == fromJSString b + +instance Show JSString where show = show . fromJSString + +instance Ord JSString where compare a b = fromJSString a `compare` fromJSString b +-------------------------------------------------------------------------------- + +class FromJSVal a where + fromJSVal :: JSVal -> IO (Maybe a) + default fromJSVal :: (Generic a, GFromJSVal (Rep a)) => JSVal -> IO (Maybe a) + fromJSVal = fmap (fmap G.to) . gFromJSVal class FromJSValPure v where fromJSValPure :: JSVal -> Maybe v @@ -87,7 +108,24 @@ instance FromJSVal Text where TypeString -> fmap Just $ textFromJSString $ JSString j _ -> pure Nothing -class ToJSVal v where toJSVal :: v -> IO JSVal +instance (FromJSVal a, FromJSVal b) => FromJSVal (a, b) where + fromJSVal j = do + ma <- fromJSVal =<< js_arrayIndex j 0 + mb <- fromJSVal =<< js_arrayIndex j 1 + return $ liftA2 (,) ma mb + +instance (FromJSVal a, FromJSVal b, FromJSVal c) => FromJSVal (a, b, c) where + fromJSVal j = do + ma <- fromJSVal =<< js_arrayIndex j 0 + mb <- fromJSVal =<< js_arrayIndex j 1 + mc <- fromJSVal =<< js_arrayIndex j 2 + return $ (,,) <$> ma <*> mb <*> mc + +-------------------------------------------------------------------------------- +class ToJSVal a where + toJSVal :: a -> IO JSVal + default toJSVal :: (Generic a, GToJSVal (Rep a)) => a -> IO JSVal + toJSVal = gToJSVal . G.from class ToJSValPure v where toJSValPure :: v -> JSVal @@ -117,17 +155,87 @@ instance ToJSVal v => ToJSVal [v] where instance ToJSVal Text where toJSVal = fmap (\(JSString j) -> j) . textToJSString -instance IsString JSString where fromString = toJSString +instance (ToJSVal a, ToJSVal b) => ToJSVal (a, b) where + toJSVal (a, b) = do + ja <- toJSVal a + jb <- toJSVal b + toJSVal [ja, jb] -instance Semigroup JSString where (<>) = js_concatStr +instance (ToJSVal a, ToJSVal b, ToJSVal c) => ToJSVal (a, b, c) where + toJSVal (a, b, c) = do + ja <- toJSVal a + jb <- toJSVal b + jc <- toJSVal c + toJSVal [ja, jb, jc] -instance Monoid JSString where mempty = js_emptyStr +-------------------------------------------------------------------------------- -instance Eq JSString where (==) a b = fromJSString a == fromJSString b +class GFromJSVal (f :: Type -> Type) where + gFromJSVal :: JSVal -> IO (Maybe (f a)) -instance Show JSString where show = show . fromJSString +instance GFromJSVal f => GFromJSVal (M1 m c f) where + gFromJSVal = fmap (fmap M1) . gFromJSVal @f -instance Ord JSString where compare a b = fromJSString a `compare` fromJSString b +instance GFromJSObject (x :*: y) => GFromJSVal (x :*: y) where + gFromJSVal kvs = gFromJSObject kvs + +instance {-# OVERLAPPING #-} FromJSVal a => GFromJSVal (S1 s (Rec0 a)) where + gFromJSVal = fmap (fmap (M1 . K1)) . fromJSVal @a +-------------------------------------------------------------------------------- + +class GToJSVal (f :: Type -> Type) where + gToJSVal :: f x -> IO JSVal + +instance GToJSVal f => GToJSVal (M1 m c f) where + gToJSVal (M1 f) = gToJSVal f + +instance GToJSObject (x :*: y) => GToJSVal (x :*: y) where + gToJSVal (x :*: y) = do + o <- js_newObject + gToJSObject (x :*: y) o + return o + +instance {-# OVERLAPPING #-} (ToJSVal a) => GToJSVal (S1 s (Rec0 a)) where + gToJSVal (M1 (K1 a)) = toJSVal a +-------------------------------------------------------------------------------- + +class GToJSObject (f :: Type -> Type) where + gToJSObject :: f x -> JSVal -> IO () + +instance (GToJSObject x, GToJSObject y) => GToJSObject (x :*: y) where + gToJSObject (x :*: y) o = gToJSObject x o >> gToJSObject y o + +instance (GToJSObject f) => GToJSObject (M1 m c f) where + gToJSObject (M1 a) o = gToJSObject a o + +instance {-# OVERLAPPING #-} (ToJSVal a, Selector s) => GToJSObject (S1 s (Rec0 a)) where + gToJSObject (M1 (K1 a)) o = do + v <- toJSVal a + js_assignProp o addr len v + where + key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) + !(Text (ByteArray arr) off len) = key + addr = Ptr (byteArrayContents# arr) `plusPtr` off + +class GFromJSObject (f :: Type -> Type) where + gFromJSObject :: JSVal -> IO (Maybe (f x)) + +instance (GFromJSObject x, GFromJSObject y) => GFromJSObject (x :*: y) where + gFromJSObject kvs = do + x <- gFromJSObject kvs + y <- gFromJSObject kvs + return $ liftA2 (:*:) x y + +instance (GFromJSObject f) => GFromJSObject (M1 m c f) where + gFromJSObject = fmap (fmap M1) . gFromJSObject + +instance {-# OVERLAPPING #-} (FromJSVal a, Selector s) => GFromJSObject (S1 s (Rec0 a)) where + gFromJSObject kvs = js_getProp kvs addr len >>= fmap (fmap (M1 . K1)) . fromJSVal + where + key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) + !(Text (ByteArray arr) off len) = key + addr = Ptr (byteArrayContents# arr) `plusPtr` off +-------------------------------------------------------------------------------- textToJSString :: Text -> IO JSString textToJSString (Text (ByteArray arr) off len) = do @@ -143,6 +251,7 @@ textFromJSString j = IO \s0 -> in (# s4, (Text (ByteArray arr) 0 tlen) #) newtype RawJavaScript = RawJavaScript {unRawJavaScript :: Text} + deriving newtype (IsString, Semigroup, Monoid) evalJavaScript :: RawJavaScript -> IO JSVal evalJavaScript rjs = do @@ -197,7 +306,6 @@ js_unsafeInt :: JSVal -> Int = undefined js_unsafeBool :: JSVal -> Bool = undefined js_intJSVal :: Int -> JSVal = undefined js_boolJSVal :: Bool -> JSVal = undefined -js_getProp :: JSVal -> JSString -> IO JSVal = undefined js_concatStr :: JSString -> JSString -> JSString = undefined js_newEmptyArray :: IO JSVal = undefined js_arrayPush :: JSVal -> JSVal -> IO () = undefined @@ -211,6 +319,9 @@ js_evalJavaScript1 :: JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined js_evalJavaScript2 :: JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined js_evalJavaScript3 :: JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined js_evalJavaScript4 :: JSVal -> JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined +js_getProp :: JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined +js_assignProp :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () = undefined +js_newObject :: IO JSVal = undefined #else @@ -241,8 +352,6 @@ foreign import javascript unsafe "$1" js_intJSVal :: Int -> JSVal foreign import javascript unsafe "($1 ? true : false)" js_boolJSVal :: Bool -> JSVal -foreign import javascript unsafe - "$1[$2]" js_getProp :: JSVal -> JSString -> IO JSVal foreign import javascript unsafe "$1 + $2" js_concatStr :: JSString -> JSString -> JSString foreign import javascript unsafe @@ -277,4 +386,13 @@ foreign import javascript unsafe foreign import javascript unsafe "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $5, $6)))($1, $2, $3, $4)" js_evalJavaScript4 :: JSVal -> JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal +foreign import javascript unsafe + "$1[new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3))]" + js_getProp :: JSVal -> Ptr Word8 -> Int -> IO JSVal +foreign import javascript unsafe + "$1[new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3))] = $4;" + js_assignProp :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () +foreign import javascript unsafe + "{}" + js_newObject :: IO JSVal #endif From 4942a078a587100f59b6dca21a279ca144534bac Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 25 Mar 2024 16:34:29 +0400 Subject: [PATCH 13/64] Split code into more modules --- examples/charts/charts.hs | 5 +- htmlt.cabal | 3 + jsbits/jsffi.js | 18 ++-- src/Clickable.hs | 2 + src/Clickable/Core.hs | 178 ++++++------------------------------- src/Clickable/DOM.hs | 44 +++------ src/Clickable/Element.hs | 2 +- src/Clickable/FFI.hs | 20 +++++ src/Clickable/Internal.hs | 94 ++++++++++++++++++++ src/Clickable/Main.hs | 37 ++++++++ src/Clickable/Property.hs | 2 +- src/Clickable/Types.hs | 71 +++++++++++++++ src/Wasm/Compat/Marshal.hs | 22 ++--- 13 files changed, 293 insertions(+), 205 deletions(-) create mode 100644 src/Clickable/Internal.hs create mode 100644 src/Clickable/Main.hs create mode 100644 src/Clickable/Types.hs diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs index 978d2b3..bdac142 100644 --- a/examples/charts/charts.hs +++ b/examples/charts/charts.hs @@ -6,5 +6,6 @@ main :: IO () main = return () foreign export ccall wasm_main :: IO () -wasm_main = attach do - liftClickM App.new >>= App.html +wasm_main = do + _ <- attach $ liftClickM App.new >>= App.html + return () diff --git a/htmlt.cabal b/htmlt.cabal index e0e5cc5..59874f8 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -94,6 +94,9 @@ library Clickable.DOM Clickable.Element Clickable.Property + Clickable.Main + Clickable.Types + Clickable.Internal Clickable.FFI Wasm.Compat.Prim Wasm.Compat.Marshal diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index dc8d8bd..9c3c9f2 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -100,15 +100,15 @@ freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ($1()), ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4) => {var j = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); if ($1 instanceof Comment) { return eval(j)($1.parentNode, $4); } else { return eval(j)($1, $4); }}, -ZC2ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => {function isOpenBracket(node) {return node instanceof Comment && node.textContent == 'ContentBoundary {{'} function isCloseBracket(node) {return node instanceof Comment && node.textContent == '}}'} var iter = $1; var nestedCounter = 0; for (;;){ if (!iter.previousSibling || (nestedCounter == 0 && isOpenBracket(iter.previousSibling)) ) break; if (isCloseBracket(iter.previousSibling)) nestedCounter++; else if (isOpenBracket(iter.previousSibling)) nestedCounter--; iter.previousSibling.parentNode.removeChild(iter.previousSibling); }}, -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => {var c1 = document.createComment('ContentBoundary {{'); var c2 = document.createComment('}}'); if ($1 instanceof Comment) { $1.parentNode.insertBefore(c1, $1); $1.parentNode.insertBefore(c2, $1); } else { $1.appendChild(c1); $1.appendChild(c2); } return c2;}, -ZC4ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, -ZC6ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC5ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), -ZC9ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: () => (document.body), -ZC12ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); if ($1 instanceof Comment) { $1.parentNode[k] = v; } else { $1[k] = v; }}, -ZC13ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, -ZC14ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, -ZC15ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => {function isOpenBracket(node) {return node instanceof Comment && node.textContent == 'ContentBoundary {{'} function isCloseBracket(node) {return node instanceof Comment && node.textContent == '}}'} var iter = $1; var nestedCounter = 0; for (;;){ if (!iter.previousSibling || (nestedCounter == 0 && isOpenBracket(iter.previousSibling)) ) break; if (isCloseBracket(iter.previousSibling)) nestedCounter++; else if (isOpenBracket(iter.previousSibling)) nestedCounter--; iter.previousSibling.parentNode.removeChild(iter.previousSibling); }}, +ZC4ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => {var c1 = document.createComment('ContentBoundary {{'); var c2 = document.createComment('}}'); if ($1 instanceof Comment) { $1.parentNode.insertBefore(c1, $1); $1.parentNode.insertBefore(c2, $1); } else { $1.appendChild(c1); $1.appendChild(c2); } return c2;}, +ZC5ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, +ZC7ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC6ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), +ZC10ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: () => (document.body), +ZC13ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); if ($1 instanceof Comment) { $1.parentNode[k] = v; } else { $1[k] = v; }}, +ZC14ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, +ZC15ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, +ZC16ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, diff --git a/src/Clickable.hs b/src/Clickable.hs index 1e2b050..06325d1 100644 --- a/src/Clickable.hs +++ b/src/Clickable.hs @@ -3,6 +3,8 @@ module Clickable (module Exports) where import Clickable.DOM as Exports import Clickable.Core as Exports import Clickable.Element as Exports +import Clickable.Main as Exports import Clickable.Property as Exports +import Clickable.Types as Exports import Wasm.Compat.Marshal as Exports import Wasm.Compat.Prim as Exports diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 2aa62ce..c4ca2e4 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -3,7 +3,6 @@ module Clickable.Core where import Control.Monad import Control.Monad.Reader import Control.Monad.State -import Data.Function ((&)) import Data.IORef import Data.List qualified as List import Data.Text (Text) @@ -15,64 +14,17 @@ import GHC.Exts hiding (build) import Unsafe.Coerce import Clickable.FFI +import Clickable.Types +import Clickable.Internal (reactive, reactive_) +import Clickable.Internal qualified as Internal import Wasm.Compat.Prim -data DynVar a where - DynVar :: RefId -> IORef a -> DynVar a -type RefId = Int +launchHtmlM :: JSVal -> InternalEnv -> HtmlM a -> IO a +launchHtmlM root env = flip runReaderT env . unClickM . trampoline . flip runReaderT root . unHtmlM -data DynVal a where - TipVal :: DynVar a -> DynVal a - TupleVal :: DynVal a -> DynVal b -> RefId -> DynVal (a, b) - MapVal :: DynVal a -> (a -> b) -> DynVal b - -------------------------------- --- REATIVE STUFF RESURRECTED -- -------------------------------- - -newtype HtmlM a = HtmlM { unHtmlM :: ReaderT JSVal ClickM a } - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader JSVal) - -newtype ClickM a = ClickM {unClickM :: ReaderT InternalEnv IO a } - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) - -instance MonadState InternalState ClickM where - state f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ swap . f - -data InternalEnv = InternalEnv - { scope :: ScopeId - , internal_state_ref :: IORef InternalState - } deriving (Generic) - -data InternalState = InternalState - { subscriptions :: [Subscription] - , finalizers :: [Finalizer] - , transaction_queue :: Map RefId (ClickM ()) - , next_id :: Int - } deriving (Generic) - -type Subscription = (ScopeId, RefId, Any -> ClickM ()) - -type Finalizer = (ScopeId, FinalizerVal) - -type EventId = Int - -type ScopeId = Int - -data FinalizerVal - = CustomFinalizer (ClickM ()) - | ScopeFinalizer ScopeId - -emptyInternalState :: InternalState -emptyInternalState = InternalState [] [] Map.empty 0 - -newInternalEnv :: IO InternalEnv -newInternalEnv = do - let scope = emptyInternalState.next_id - internal_state_ref <- newIORef emptyInternalState - {next_id = emptyInternalState.next_id + 1} - return InternalEnv {internal_state_ref, scope} +launchClickM :: InternalEnv -> ClickM a -> IO a +launchClickM env = flip runReaderT env . unClickM . trampoline liftClickM :: ClickM a -> HtmlM a liftClickM = HtmlM . lift @@ -82,7 +34,7 @@ liftClickM = HtmlM . lift --------------------------------------- mapVar :: DynVar a -> (a -> b) -> DynVal b -mapVar var = MapVal (TipVal var) +mapVar var = MapVal (FromVar var) newVar :: a -> ClickM (DynVar a) newVar a = do @@ -90,9 +42,10 @@ newVar a = do state \s -> (DynVar s.next_id ref, s {next_id = s.next_id + 1}) readVal :: DynVal a -> ClickM a -readVal (TipVal (DynVar _ ref)) = liftIO $ readIORef ref -readVal (TupleVal a b _) = liftA2 (,) (readVal a) (readVal b) +readVal (ConstVal a) = pure a +readVal (FromVar (DynVar _ ref)) = liftIO $ readIORef ref readVal (MapVal val f) = fmap f $ readVal val +readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) readVar :: DynVar a -> ClickM a readVar (DynVar _ ref) = liftIO $ readIORef ref @@ -100,103 +53,42 @@ readVar (DynVar _ ref) = liftIO $ readIORef ref atomicModifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a atomicModifyVar var@(DynVar varId ref) f = do (newVal, a) <- liftIO $ atomicModifyIORef' ref g - modify $ varModifiedFn var newVal + modify $ Internal.unsafeTrigger varId newVal return a where g old = let (new, a) = f old in (new, (new, a)) -varModifiedFn :: - DynVar a -> - a -> - InternalState -> InternalState -varModifiedFn (DynVar varId _) vals = go0 where - go0 = defer varId $ gets (.subscriptions) >>= go1 - go1 [] = return () - go1 ((_, sVar, cb) : xs) - | sVar == varId = cb (unsafeCoerce vals) >> go1 xs - | otherwise = go1 xs - -varModifiedFn1 :: RefId -> a -> InternalState -> InternalState -varModifiedFn1 varId vals = go0 where - go0 = defer varId $ gets (.subscriptions) >>= go1 - go1 [] = return () - go1 ((_, sVar, cb) : xs) - | sVar == varId = cb (unsafeCoerce vals) >> go1 xs - | otherwise = go1 xs - modifyVar :: DynVar s -> (s -> s) -> ClickM () modifyVar var f = atomicModifyVar var ((,()) . f) ---------------------------------------------- --- RESOURCE MANAGEMENT AND DYNAMIC UPDATES -- ---------------------------------------------- +writeVar :: DynVar s -> s -> ClickM () +writeVar var s = modifyVar var $ const s -newScopeFn :: ScopeId -> InternalState -> (InternalState, ScopeId) -newScopeFn p s = - let - scopeId = s.next_id - finalizers = (p, ScopeFinalizer scopeId) : s.finalizers - next_id = s.next_id + 1 - in - (s {finalizers, next_id}, scopeId) +subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () +subscribe val k = reactive_ $ Internal.subscribe val k -newScope :: ClickM ScopeId -newScope = ClickM $ ReaderT $ \e -> - atomicModifyIORef' e.internal_state_ref $ newScopeFn e.scope +------------------------- +-- RESOURCE MANAGEMENT -- +------------------------- -freeScopeFn :: Bool -> ScopeId -> InternalState -> (InternalState, [Finalizer]) -freeScopeFn unlink rscope s = - let - chkSub (s, _, _) = s /= rscope - chkFin True (s1, ScopeFinalizer s2) = s1 /= rscope && s2 /= rscope - chkFin True (s, _) = s /= rscope - chkFin False (s, _) = s /= rscope - (scopeFns, finalizers) = List.partition (chkFin unlink) s.finalizers - subscriptions = List.filter chkSub s.subscriptions - in - (s {subscriptions, finalizers}, scopeFns) +newScope :: ClickM ScopeId +newScope = reactive Internal.newScope freeScope :: Bool -> ScopeId -> ClickM () freeScope unlink s = f where - f = state (swap . freeScopeFn unlink s) >>= g + f = reactive (const (Internal.freeScope unlink s)) >>= g g [] = return () g ((_, ScopeFinalizer s'):xs) = freeScope True s' >> g xs g ((_, CustomFinalizer x):xs) = x >> g xs -installFinalizerFn :: ScopeId -> ClickM () -> InternalState -> InternalState -installFinalizerFn scope k s = s {finalizers = (scope, CustomFinalizer k) : s.finalizers } - installFinalizer :: ClickM () -> ClickM () -installFinalizer k = ask >>= \e -> modify (installFinalizerFn e.scope k) - -subscribeFn :: - ScopeId -> - DynVal a -> - (a -> ClickM ()) -> - InternalState -> InternalState -subscribeFn scope (TipVal (DynVar varId _)) fn s = s - { subscriptions = sub : s.subscriptions } - where - sub = (scope, varId, fn . unsafeCoerce) -subscribeFn scope (TupleVal a b varid) fn s = - subscribeFn scope b g $ subscribeFn scope a f s - where - f a = do - bval <- readVal b - modify $ varModifiedFn1 varid (a, bval) - g b = do - aval <- readVal a - modify $ varModifiedFn1 varid (aval, b) -subscribeFn scope (MapVal v f) fn s = subscribeFn scope v (fn . f) s - -subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () -subscribe val k = do - e :: InternalEnv <- ask - liftIO $ modifyIORef' e.internal_state_ref $ subscribeFn e.scope val k +installFinalizer k = reactive_ $ Internal.installFinalizer k --- | Loop until transaction queue is empty. TODO: Is this even +-- | Loop until transaction queue is empty. +-- +-- This makes possible to implement @Applicative DynVal@ without triggering callbacks TODO: Is this even -- worth-while to have? What if just let multiple DOM changes when it --- depends on several sources? +-- depends on multiple sources? trampoline :: ClickM a -> ClickM a trampoline act = loop0 act where loop0 :: ClickM a -> ClickM a @@ -216,9 +108,6 @@ trampoline act = loop0 act where Nothing -> (Nothing, s) Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) -defer :: RefId -> ClickM () -> InternalState -> InternalState -defer k act s = s { transaction_queue = Map.insert k act s.transaction_queue } - ------------------ -- BUILDING DOM -- ------------------ @@ -297,16 +186,3 @@ dyn val = do freeScope False scope exec $ update newVal return () - --------------------------- --- START AN APPLICATION -- --------------------------- - -attach :: HtmlM a -> IO a -attach html = do - body <- documentBody - env <- newInternalEnv - html.unHtmlM - & flip runReaderT body - & unClickM - & flip runReaderT env diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index e192511..57201fa 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -1,29 +1,13 @@ module Clickable.DOM where -import Control.Monad -import Data.Bifunctor -import Control.Monad.Identity import Control.Monad.Reader -import Control.Monad.Trans -import Control.Monad.State -import Data.Foldable -import Data.Function ((&)) -import Data.IORef -import Data.List qualified as List import Data.Text (Text) -import Data.Tuple -import Data.Typeable -import Data.Map (Map) -import Data.Set (Set) import Data.Kind -import Data.Map qualified as Map import GHC.Generics -import GHC.Exts hiding (build) -import GHC.TypeLits -import Unsafe.Coerce import Clickable.FFI qualified as FFI import Clickable.Core +import Clickable.Types import Wasm.Compat.Prim import Wasm.Compat.Marshal @@ -45,16 +29,16 @@ addEventListener args k = do liftClickM $ connectResource rootElement args k data ConnectResourceArgs callback = ConnectResourceArgs - { js_wrapper :: RawJavaScript + { js_wrapper :: UnsafeJavaScript , mk_callback :: callback -> JSVal -> ClickM () } connectResource :: JSVal -> ConnectResourceArgs callback -> callback -> ClickM () connectResource target args k = do - env <- ask - let hsCallback' = (`runReaderT` env) . unClickM . args.mk_callback k + e :: InternalEnv <- ask + let hsCallback' = (`runReaderT` e) . unClickM . trampoline . args.mk_callback k hsCallback'' <- liftIO $ FFI.js_dynExport hsCallback' - cancel <- liftIO $ FFI.aquireResource target args.js_wrapper.unRawJavaScript hsCallback'' + cancel <- liftIO $ FFI.aquireResource target args.js_wrapper.unUnsafeJavaScript hsCallback'' installFinalizer do liftIO $ FFI.apply0 cancel liftIO $ freeJSVal hsCallback'' @@ -147,8 +131,8 @@ inputConnectArgs eventName = ConnectResourceArgs \ function listener(target){\n\ \ haskellCb(event.target.value);\n\ \ }\n\ - \ window.addEventListener('" <> RawJavaScript eventName <> "', listener);\n\ - \ return () => window.removeEventListener('" <> RawJavaScript eventName <> "', listener);\n\ + \ window.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => window.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \})" , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k } @@ -162,8 +146,8 @@ keyboardConnectArgs eventName = ConnectResourceArgs \ function listener(target){\n\ \ haskellCb(event.target.value);\n\ \ }\n\ - \ window.addEventListener('" <> RawJavaScript eventName <> "', listener);\n\ - \ return () => window.removeEventListener('" <> RawJavaScript eventName <> "', listener);\n\ + \ window.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => window.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \})" , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k } @@ -206,16 +190,16 @@ selectChangeConnectArgs = ConnectResourceArgs , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k } -normalEventWrapper :: Text -> EventListenerOptions -> RawJavaScript +normalEventWrapper :: Text -> EventListenerOptions -> UnsafeJavaScript normalEventWrapper eventName opt = "(function(target, haskellCb){\n\ \ function listener(event){\n\ - \ " <> preventDefaultStmt <> ";\n\ - \ " <> stopPropagationStmt <> ";\n\ + \ " <> preventDefaultStmt <> "\n\ + \ " <> stopPropagationStmt <> "\n\ \ haskellCb(event);\n\ \ }\n\ - \ target.addEventListener('" <> RawJavaScript eventName <> "', listener);\n\ - \ return () => target.removeEventListener(" <> RawJavaScript eventName <> ", listener);\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \})" where preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" diff --git a/src/Clickable/Element.hs b/src/Clickable/Element.hs index 0753290..de84a7d 100644 --- a/src/Clickable/Element.hs +++ b/src/Clickable/Element.hs @@ -4,7 +4,7 @@ Shortcuts for most common HTML5 elements module Clickable.Element where import Clickable.Core -import Wasm.Compat.Prim +import Clickable.Types import Data.Text -- | This typeclass allows for tag constructors to have variable diff --git a/src/Clickable/FFI.hs b/src/Clickable/FFI.hs index 09f67c8..37a15ba 100644 --- a/src/Clickable/FFI.hs +++ b/src/Clickable/FFI.hs @@ -114,6 +114,9 @@ js_insertBrackets = undefined js_clearBrackets :: JSVal -> IO () js_clearBrackets = undefined +js_removeBrackets :: JSVal -> IO () +js_removeBrackets = undefined + js_aquireResource :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO JSVal js_aquireResource = undefined @@ -217,6 +220,23 @@ foreign import javascript unsafe iter.previousSibling.parentNode.removeChild(iter.previousSibling);\ }" js_clearBrackets :: JSVal -> IO () +foreign import javascript unsafe + "function isOpenBracket(node) {return node instanceof Comment && node.textContent == 'ContentBoundary {{'}\ + function isCloseBracket(node) {return node instanceof Comment && node.textContent == '}}'}\ + var iter = $1;\ + var nestedCounter = 0;\ + for (;;){\ + if (!iter.previousSibling ||\ + (nestedCounter == 0 && isOpenBracket(iter.previousSibling))\ + ) break;\ + if (isCloseBracket(iter.previousSibling)) nestedCounter++;\ + else if (isOpenBracket(iter.previousSibling)) nestedCounter--;\ + iter.previousSibling.parentNode.removeChild(iter.previousSibling);\ + }\ + $1.parentNode($1);\ + if ($1 != iter) iter.parentNode.removeChild(iter);\ + " + js_removeBrackets :: JSVal -> IO () foreign import javascript unsafe "var j = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ if ($1 instanceof Comment) {\ diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs new file mode 100644 index 0000000..ffb94f7 --- /dev/null +++ b/src/Clickable/Internal.hs @@ -0,0 +1,94 @@ +module Clickable.Internal where + +import Clickable.Types +import Control.Monad.Reader +import Control.Monad.State +import Data.IORef +import Data.List qualified as List +import Data.Map qualified as Map +import Unsafe.Coerce + + +emptyInternalState :: InternalState +emptyInternalState = InternalState [] [] Map.empty 0 + +newInternalEnv :: IO InternalEnv +newInternalEnv = do + let scope = emptyInternalState.next_id + internal_state_ref <- newIORef emptyInternalState + {next_id = emptyInternalState.next_id + 1} + return InternalEnv {internal_state_ref, scope} + +unsafeTrigger :: RefId -> a -> InternalState -> InternalState +unsafeTrigger varId vals = go0 where + go0 = defer varId $ gets (.subscriptions) >>= go1 + go1 [] = return () + go1 ((_, sVar, cb) : xs) + | sVar == varId = cb (unsafeCoerce vals) >> go1 xs + | otherwise = go1 xs + +newScope :: ScopeId -> InternalState -> (InternalState, ScopeId) +newScope p s = + let + scopeId = s.next_id + finalizers = (p, ScopeFinalizer scopeId) : s.finalizers + next_id = s.next_id + 1 + in + (s {finalizers, next_id}, scopeId) + +freeScope :: Bool -> ScopeId -> InternalState -> (InternalState, [Finalizer]) +freeScope unlink rscope s = + let + chkSub (s, _, _) = s /= rscope + chkFin True (s1, ScopeFinalizer s2) = s1 /= rscope && s2 /= rscope + chkFin True (s, _) = s /= rscope + chkFin False (s, _) = s /= rscope + (finalizers, scopeFns) = List.partition (chkFin unlink) s.finalizers + subscriptions = List.filter chkSub s.subscriptions + in + (s {subscriptions, finalizers}, scopeFns) + +installFinalizer :: ClickM () -> ScopeId -> InternalState -> InternalState +installFinalizer k scope s = s + {finalizers = (scope, CustomFinalizer k) : s.finalizers} + +subscribe :: + DynVal a -> + (a -> ClickM ()) -> + ScopeId -> + InternalState -> InternalState +subscribe (FromVar (DynVar varId _)) fn scope s = s {subscriptions} + where + subscriptions = newSub : s.subscriptions + newSub = (scope, varId, fn . unsafeCoerce) +subscribe (SplatVal fv av) fn scope s = + subscribe av g scope $ subscribe fv f scope $ attachCb s + where + f fv' = do + av' <- readVal av + modify $ unsafeTrigger varid $ fv' av' + g av' = do + fv' <- readVal fv + modify $ unsafeTrigger varid $ fv' av' + attachCb s = s + { subscriptions = (scope, varid, fn . unsafeCoerce) : s.subscriptions + , next_id = s.next_id + 1 + } + varid = s.next_id +subscribe (MapVal v f) fn scope s = subscribe v (fn . f) scope s +subscribe (ConstVal _) _ _ s = s + +defer :: RefId -> ClickM () -> InternalState -> InternalState +defer k act s = s { transaction_queue = Map.insert k act s.transaction_queue } + +readVal :: DynVal a -> ClickM a +readVal (ConstVal a) = pure a +readVal (FromVar (DynVar _ ref)) = liftIO $ readIORef ref +readVal (MapVal val f) = fmap f $ readVal val +readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) + +reactive :: (ScopeId -> InternalState -> (InternalState, a)) -> ClickM a +reactive f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ f e.scope + +reactive_ :: (ScopeId -> InternalState -> InternalState) -> ClickM () +reactive_ f = reactive \scope s -> (f scope s, ()) diff --git a/src/Clickable/Main.hs b/src/Clickable/Main.hs new file mode 100644 index 0000000..4fc2816 --- /dev/null +++ b/src/Clickable/Main.hs @@ -0,0 +1,37 @@ +module Clickable.Main where + +import GHC.Generics +import Clickable.FFI +import Clickable.Core +import Clickable.Types +import Clickable.Internal (newInternalEnv) +import Wasm.Compat.Prim + +data AttachOptions = AttachOptions + { internal_env :: InternalEnv + , dom_builder :: JSVal + } deriving Generic + +-- | Needed to manually finalize and detach the application +data RunningApp = RunningApp + { internal_env :: InternalEnv + , dom_bracket :: JSVal + } deriving Generic + +attachWithOptions :: AttachOptions -> HtmlM a -> IO (a, RunningApp) +attachWithOptions opt app = do + domBracket <- js_insertBrackets opt.dom_builder + result <- launchHtmlM domBracket opt.internal_env app + let runApp = RunningApp opt.internal_env domBracket + return (result, runApp) + +attach :: HtmlM a -> IO (a, RunningApp) +attach html = do + body <- documentBody + internalEnv <- newInternalEnv + attachWithOptions (AttachOptions internalEnv body) html + +detach :: RunningApp -> IO () +detach app = do + launchClickM app.internal_env $ freeScope True app.internal_env.scope + js_removeBrackets app.dom_bracket diff --git a/src/Clickable/Property.hs b/src/Clickable/Property.hs index d807a0d..1e20ccf 100644 --- a/src/Clickable/Property.hs +++ b/src/Clickable/Property.hs @@ -4,8 +4,8 @@ Shortcuts for common HTML5 attributes and properties module Clickable.Property where import Clickable.Core +import Clickable.Types import Data.Text -import Wasm.Compat.Prim -- TODO: Real-world usage has demonstrated that 'dynStyles' not diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs new file mode 100644 index 0000000..d1ec0f0 --- /dev/null +++ b/src/Clickable/Types.hs @@ -0,0 +1,71 @@ +module Clickable.Types where + +import Control.Monad +import Control.Monad.Reader +import Control.Monad.State +import Data.IORef +import Data.List qualified as List +import Data.Text (Text) +import Data.Tuple +import Data.Map (Map) +import Data.Map qualified as Map +import GHC.Generics +import GHC.Exts hiding (build) +import Unsafe.Coerce + +import Clickable.FFI +import Wasm.Compat.Prim + +data DynVar a where + DynVar :: RefId -> IORef a -> DynVar a + +type RefId = Int + +data DynVal a where + ConstVal :: a -> DynVal a + FromVar :: DynVar a -> DynVal a + MapVal :: DynVal a -> (a -> b) -> DynVal b + SplatVal :: DynVal (a -> b) -> DynVal a -> DynVal b + +instance Functor DynVal where fmap = flip MapVal + +instance Applicative DynVal where pure = ConstVal; (<*>) = SplatVal + +fromVar :: DynVar a -> DynVal a +fromVar = FromVar + +------------------------------- +-- REATIVE STUFF RESURRECTED -- +------------------------------- + +newtype HtmlM a = HtmlM { unHtmlM :: ReaderT JSVal ClickM a } + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader JSVal) + +newtype ClickM a = ClickM {unClickM :: ReaderT InternalEnv IO a } + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) + +instance MonadState InternalState ClickM where + state f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ swap . f + + +data InternalEnv = InternalEnv + { scope :: ScopeId + , internal_state_ref :: IORef InternalState + } deriving (Generic) + +data InternalState = InternalState + { subscriptions :: [Subscription] + , finalizers :: [Finalizer] + , transaction_queue :: Map RefId (ClickM ()) + , next_id :: Int + } deriving (Generic) + +type Subscription = (ScopeId, RefId, Any -> ClickM ()) + +type Finalizer = (ScopeId, FinalizerVal) + +type ScopeId = Int + +data FinalizerVal + = CustomFinalizer (ClickM ()) + | ScopeFinalizer ScopeId diff --git a/src/Wasm/Compat/Marshal.hs b/src/Wasm/Compat/Marshal.hs index d09f3aa..9edb9b5 100644 --- a/src/Wasm/Compat/Marshal.hs +++ b/src/Wasm/Compat/Marshal.hs @@ -250,46 +250,46 @@ textFromJSString j = IO \s0 -> (# s4, arr #) = unsafeFreezeByteArray# marr s3 in (# s4, (Text (ByteArray arr) 0 tlen) #) -newtype RawJavaScript = RawJavaScript {unRawJavaScript :: Text} +newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} deriving newtype (IsString, Semigroup, Monoid) -evalJavaScript :: RawJavaScript -> IO JSVal +evalJavaScript :: UnsafeJavaScript -> IO JSVal evalJavaScript rjs = do - let Text (ByteArray arr) off len = rjs.unRawJavaScript + let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript addr = byteArrayContents# arr js_evalJavaScript (Ptr addr `plusPtr` off) len -evalJavaScript1 :: ToJSVal arg0 => arg0 -> RawJavaScript -> IO JSVal +evalJavaScript1 :: ToJSVal arg0 => arg0 -> UnsafeJavaScript -> IO JSVal evalJavaScript1 arg0 rjs = do a0 <- toJSVal arg0 - let Text (ByteArray arr) off len = rjs.unRawJavaScript + let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript addr = byteArrayContents# arr js_evalJavaScript1 a0 (Ptr addr `plusPtr` off) len -evalJavaScript2 :: (ToJSVal arg0, ToJSVal arg1) => arg0 -> arg1 -> RawJavaScript -> IO JSVal +evalJavaScript2 :: (ToJSVal arg0, ToJSVal arg1) => arg0 -> arg1 -> UnsafeJavaScript -> IO JSVal evalJavaScript2 arg0 arg1 rjs = do a0 <- toJSVal arg0 a1 <- toJSVal arg1 - let Text (ByteArray arr) off len = rjs.unRawJavaScript + let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript addr = byteArrayContents# arr js_evalJavaScript2 a0 a1 (Ptr addr `plusPtr` off) len -evalJavaScript3 :: (ToJSVal arg0, ToJSVal arg1, ToJSVal arg2) => arg0 -> arg1 -> arg2 -> RawJavaScript -> IO JSVal +evalJavaScript3 :: (ToJSVal arg0, ToJSVal arg1, ToJSVal arg2) => arg0 -> arg1 -> arg2 -> UnsafeJavaScript -> IO JSVal evalJavaScript3 arg0 arg1 arg2 rjs = do a0 <- toJSVal arg0 a1 <- toJSVal arg1 a2 <- toJSVal arg2 - let Text (ByteArray arr) off len = rjs.unRawJavaScript + let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript addr = byteArrayContents# arr js_evalJavaScript3 a0 a1 a2 (Ptr addr `plusPtr` off) len -evalJavaScript4 :: (ToJSVal arg0, ToJSVal arg1, ToJSVal arg2, ToJSVal arg3) => arg0 -> arg1 -> arg2 -> arg3 -> RawJavaScript -> IO JSVal +evalJavaScript4 :: (ToJSVal arg0, ToJSVal arg1, ToJSVal arg2, ToJSVal arg3) => arg0 -> arg1 -> arg2 -> arg3 -> UnsafeJavaScript -> IO JSVal evalJavaScript4 arg0 arg1 arg2 arg3 rjs = do a0 <- toJSVal arg0 a1 <- toJSVal arg1 a2 <- toJSVal arg2 a3 <- toJSVal arg3 - let Text (ByteArray arr) off len = rjs.unRawJavaScript + let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript addr = byteArrayContents# arr js_evalJavaScript4 a0 a1 a2 a3 (Ptr addr `plusPtr` off) len From 6f257367c2e2eefaa8eda852561caeacf2854581 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 26 Mar 2024 16:28:54 +0400 Subject: [PATCH 14/64] Cleanup --- htmlt.cabal | 2 ++ src/Clickable/Core.hs | 28 ++++++++++++--------------- src/Clickable/Internal.hs | 40 ++++++++++++++++++++------------------- src/Clickable/Types.hs | 29 +++++++++++----------------- 4 files changed, 46 insertions(+), 53 deletions(-) diff --git a/htmlt.cabal b/htmlt.cabal index 59874f8..7eafc05 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -104,6 +104,8 @@ library other-modules: Paths_htmlt build-depends: base, + binary, + bytestring, containers, exceptions, mtl, diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index c4ca2e4..a4c0257 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -4,24 +4,19 @@ import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.IORef -import Data.List qualified as List -import Data.Text (Text) -import Data.Tuple -import Data.Map (Map) import Data.Map qualified as Map -import GHC.Generics -import GHC.Exts hiding (build) -import Unsafe.Coerce +import Data.Text (Text) import Clickable.FFI -import Clickable.Types import Clickable.Internal (reactive, reactive_) import Clickable.Internal qualified as Internal +import Clickable.Types import Wasm.Compat.Prim launchHtmlM :: JSVal -> InternalEnv -> HtmlM a -> IO a -launchHtmlM root env = flip runReaderT env . unClickM . trampoline . flip runReaderT root . unHtmlM +launchHtmlM root env = + flip runReaderT env . unClickM . trampoline . flip runReaderT root . unHtmlM launchClickM :: InternalEnv -> ClickM a -> IO a launchClickM env = flip runReaderT env . unClickM . trampoline @@ -39,7 +34,7 @@ mapVar var = MapVal (FromVar var) newVar :: a -> ClickM (DynVar a) newVar a = do ref <- liftIO $ newIORef a - state \s -> (DynVar s.next_id ref, s {next_id = s.next_id + 1}) + state \s -> (DynVar (SourceId s.next_id) ref, s {next_id = s.next_id + 1}) readVal :: DynVal a -> ClickM a readVal (ConstVal a) = pure a @@ -71,10 +66,10 @@ subscribe val k = reactive_ $ Internal.subscribe val k -- RESOURCE MANAGEMENT -- ------------------------- -newScope :: ClickM ScopeId +newScope :: ClickM ResourceScope newScope = reactive Internal.newScope -freeScope :: Bool -> ScopeId -> ClickM () +freeScope :: Bool -> ResourceScope -> ClickM () freeScope unlink s = f where f = reactive (const (Internal.freeScope unlink s)) >>= g g [] = return () @@ -84,11 +79,12 @@ freeScope unlink s = f where installFinalizer :: ClickM () -> ClickM () installFinalizer k = reactive_ $ Internal.installFinalizer k --- | Loop until transaction queue is empty. +-- | Loop until transaction_queue is empty. -- --- This makes possible to implement @Applicative DynVal@ without triggering callbacks TODO: Is this even --- worth-while to have? What if just let multiple DOM changes when it --- depends on multiple sources? +-- This makes possible to implement @Applicative DynVal@ without +-- redundantly firing callback for the final result. TODO: Is this +-- even worth-while to have? What if just let multiple DOM changes +-- when it depends on multiple sources? trampoline :: ClickM a -> ClickM a trampoline act = loop0 act where loop0 :: ClickM a -> ClickM a diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index ffb94f7..37f463f 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -14,12 +14,12 @@ emptyInternalState = InternalState [] [] Map.empty 0 newInternalEnv :: IO InternalEnv newInternalEnv = do - let scope = emptyInternalState.next_id + let scope = ResourceScope emptyInternalState.next_id internal_state_ref <- newIORef emptyInternalState {next_id = emptyInternalState.next_id + 1} return InternalEnv {internal_state_ref, scope} -unsafeTrigger :: RefId -> a -> InternalState -> InternalState +unsafeTrigger :: SourceId -> a -> InternalState -> InternalState unsafeTrigger varId vals = go0 where go0 = defer varId $ gets (.subscriptions) >>= go1 go1 [] = return () @@ -27,16 +27,19 @@ unsafeTrigger varId vals = go0 where | sVar == varId = cb (unsafeCoerce vals) >> go1 xs | otherwise = go1 xs -newScope :: ScopeId -> InternalState -> (InternalState, ScopeId) +newScope :: ResourceScope -> InternalState -> (InternalState, ResourceScope) newScope p s = let - scopeId = s.next_id + scopeId = ResourceScope s.next_id finalizers = (p, ScopeFinalizer scopeId) : s.finalizers next_id = s.next_id + 1 in (s {finalizers, next_id}, scopeId) -freeScope :: Bool -> ScopeId -> InternalState -> (InternalState, [Finalizer]) +freeScope :: + Bool -> + ResourceScope -> + InternalState -> (InternalState, [(ResourceScope, FinalizerVal)]) freeScope unlink rscope s = let chkSub (s, _, _) = s /= rscope @@ -48,19 +51,21 @@ freeScope unlink rscope s = in (s {subscriptions, finalizers}, scopeFns) -installFinalizer :: ClickM () -> ScopeId -> InternalState -> InternalState +installFinalizer :: ClickM () -> ResourceScope -> InternalState -> InternalState installFinalizer k scope s = s {finalizers = (scope, CustomFinalizer k) : s.finalizers} subscribe :: DynVal a -> (a -> ClickM ()) -> - ScopeId -> + ResourceScope -> InternalState -> InternalState +subscribe (ConstVal _) _ _ s = s subscribe (FromVar (DynVar varId _)) fn scope s = s {subscriptions} where subscriptions = newSub : s.subscriptions newSub = (scope, varId, fn . unsafeCoerce) +subscribe (MapVal v f) fn scope s = subscribe v (fn . f) scope s subscribe (SplatVal fv av) fn scope s = subscribe av g scope $ subscribe fv f scope $ attachCb s where @@ -74,21 +79,18 @@ subscribe (SplatVal fv av) fn scope s = { subscriptions = (scope, varid, fn . unsafeCoerce) : s.subscriptions , next_id = s.next_id + 1 } - varid = s.next_id -subscribe (MapVal v f) fn scope s = subscribe v (fn . f) scope s -subscribe (ConstVal _) _ _ s = s + varid = SourceId s.next_id + readVal :: DynVal a -> ClickM a + readVal (ConstVal a) = pure a + readVal (FromVar (DynVar _ ref)) = liftIO $ readIORef ref + readVal (MapVal val f) = fmap f $ readVal val + readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) -defer :: RefId -> ClickM () -> InternalState -> InternalState +defer :: SourceId -> ClickM () -> InternalState -> InternalState defer k act s = s { transaction_queue = Map.insert k act s.transaction_queue } -readVal :: DynVal a -> ClickM a -readVal (ConstVal a) = pure a -readVal (FromVar (DynVar _ ref)) = liftIO $ readIORef ref -readVal (MapVal val f) = fmap f $ readVal val -readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) - -reactive :: (ScopeId -> InternalState -> (InternalState, a)) -> ClickM a +reactive :: (ResourceScope -> InternalState -> (InternalState, a)) -> ClickM a reactive f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ f e.scope -reactive_ :: (ScopeId -> InternalState -> InternalState) -> ClickM () +reactive_ :: (ResourceScope -> InternalState -> InternalState) -> ClickM () reactive_ f = reactive \scope s -> (f scope s, ()) diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index d1ec0f0..91897a5 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -17,9 +17,7 @@ import Clickable.FFI import Wasm.Compat.Prim data DynVar a where - DynVar :: RefId -> IORef a -> DynVar a - -type RefId = Int + DynVar :: SourceId -> IORef a -> DynVar a data DynVal a where ConstVal :: a -> DynVal a @@ -34,9 +32,11 @@ instance Applicative DynVal where pure = ConstVal; (<*>) = SplatVal fromVar :: DynVar a -> DynVal a fromVar = FromVar -------------------------------- --- REATIVE STUFF RESURRECTED -- -------------------------------- +newtype ResourceScope = ResourceScope {unResourceScope :: Int} + deriving newtype (Eq, Ord, Show) + +newtype SourceId = SourceId {unSourceId :: Int} + deriving newtype (Eq, Ord, Show) newtype HtmlM a = HtmlM { unHtmlM :: ReaderT JSVal ClickM a } deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader JSVal) @@ -47,25 +47,18 @@ newtype ClickM a = ClickM {unClickM :: ReaderT InternalEnv IO a } instance MonadState InternalState ClickM where state f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ swap . f - data InternalEnv = InternalEnv - { scope :: ScopeId + { scope :: ResourceScope , internal_state_ref :: IORef InternalState } deriving (Generic) data InternalState = InternalState - { subscriptions :: [Subscription] - , finalizers :: [Finalizer] - , transaction_queue :: Map RefId (ClickM ()) + { subscriptions :: [(ResourceScope, SourceId, Any -> ClickM ())] + , finalizers :: [(ResourceScope, FinalizerVal)] + , transaction_queue :: Map SourceId (ClickM ()) , next_id :: Int } deriving (Generic) -type Subscription = (ScopeId, RefId, Any -> ClickM ()) - -type Finalizer = (ScopeId, FinalizerVal) - -type ScopeId = Int - data FinalizerVal = CustomFinalizer (ClickM ()) - | ScopeFinalizer ScopeId + | ScopeFinalizer ResourceScope From 7b37849372d7e46c6b339a9931fd2d740edded66 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 27 Mar 2024 16:27:06 +0400 Subject: [PATCH 15/64] Clickable.Protocol --- htmlt.cabal | 4 +- jsbits/binary.ts | 403 ++++++++++++++++++++ jsbits/ffi.ts | 64 ++++ jsbits/jsffi.js | 2 + jsbits/lib.ts | 100 +++++ jsbits/post-link.mjs | 100 +++++ jsbits/prelude.js | 93 +++++ jsbits/protocol.ts | 653 ++++++++++++++++++++++++++++++++ src/Clickable/Core.hs | 11 + src/Clickable/FFI.hs | 6 + src/Clickable/Internal.hs | 41 +- src/Clickable/Protocol.hs | 198 ++++++++++ src/Clickable/Protocol/Value.hs | 158 ++++++++ src/Clickable/Types.hs | 16 +- tsconfig.json | 15 + webpack.config.js | 9 + 16 files changed, 1860 insertions(+), 13 deletions(-) create mode 100644 jsbits/binary.ts create mode 100644 jsbits/ffi.ts create mode 100644 jsbits/lib.ts create mode 100755 jsbits/post-link.mjs create mode 100644 jsbits/prelude.js create mode 100644 jsbits/protocol.ts create mode 100644 src/Clickable/Protocol.hs create mode 100644 src/Clickable/Protocol/Value.hs create mode 100644 tsconfig.json diff --git a/htmlt.cabal b/htmlt.cabal index 7eafc05..24193df 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -97,6 +97,8 @@ library Clickable.Main Clickable.Types Clickable.Internal + Clickable.Protocol + Clickable.Protocol.Value Clickable.FFI Wasm.Compat.Prim Wasm.Compat.Marshal @@ -156,7 +158,7 @@ executable htmlt-charts hs-source-dirs: ./examples/charts ghc-options: -no-hs-main -optl-mexec-model=reactor - -optl-Wl,--export=hs_init,--export=wasm_main + -optl-Wl,--export=hs_init,--export=wasm_main,--export=malloc build-depends: base, htmlt, diff --git a/jsbits/binary.ts b/jsbits/binary.ts new file mode 100644 index 0000000..3f355ac --- /dev/null +++ b/jsbits/binary.ts @@ -0,0 +1,403 @@ +/** + * Data.Binary serialization library implemented in typescript + */ +import { absurd } from './lib'; + +type HaskellPointer = number; + +export class DecoderBase { + // @ts-ignore + readonly _A: A; + + encode(value: A): Uint8Array { + const decoder = this as Decoder; + const size = computeSize(decoder, value); + const u8array = new Uint8Array(size); + runEncoder(decoder, u8array, 0, value); + return u8array; + } + + decode(mem: Uint8Array): A { + const decoder = this as Decoder; + const [resultVal, _ptr] = runDecoder(decoder, mem, 0); + return resultVal; + } +} + +export type Decoder = + | Int8Decoder + | Int64Decoder + | Float64Decoder + | Uint8ArrayDecoder + | StringDecoder + | ArrayDecoder + | RecordDecoder + | OneOfDecoder + | RecursiveDecoder + | TupleDecoder +; + +export class Int8Decoder extends DecoderBase { +} +export class Int64Decoder extends DecoderBase { +} +export class Float64Decoder extends DecoderBase { +} +export class Uint8ArrayDecoder extends DecoderBase { +} +export class StringDecoder extends DecoderBase { +} +export class ArrayDecoder extends DecoderBase { + constructor( + readonly _element: Decoder, + ) { super(); } +} +export class RecordDecoder extends DecoderBase { + constructor( + readonly _description: Record>, + ) { super(); } +} +export class OneOfDecoder extends DecoderBase { + constructor( + readonly _alternatives: Record>, + ) { super(); } +} +export class RecursiveDecoder extends DecoderBase { + constructor( + public _self: Decoder, + ) { super(); } +} +export class TupleDecoder extends DecoderBase { + constructor( + readonly _tuple: Decoder[], + ) { super(); } +} +export function computeSize( + decoder: Decoder, + value: A +): number { + if (decoder instanceof Int8Decoder) { + return 1; + } + if (decoder instanceof Int64Decoder) { + return 8; + } + if (decoder instanceof Float64Decoder) { + return 8; + } + if (decoder instanceof StringDecoder) { + const str = value as any as string; + const lengthSize = 8; // How many bytes to encode array length + const u8array = new TextEncoder().encode(str); + return lengthSize + u8array.length; + } + if (decoder instanceof Uint8ArrayDecoder) { + const u8array = value as any as Uint8Array; + const lengthSize = 8; // How many bytes to encode array length + return lengthSize + u8array.length; + } + if (decoder instanceof ArrayDecoder) { + const array = value as any as any[]; + const lengthSize = 8; // How many bytes to encode array length + return array.reduce((acc, v) => acc + computeSize(decoder._element, v), lengthSize); + } + if (decoder instanceof RecordDecoder) { + const obj = value as any as Record; + return Object.keys(decoder._description).reduce(((acc, k) => + acc + computeSize(decoder._description[k], obj[k]) + ), 0 + ); + } + if (decoder instanceof OneOfDecoder) { + const obj = value as any as { tag: number }; + const dscrSize = discriminatorSize(Object.keys(decoder._alternatives).length); + return dscrSize + computeSize(decoder._alternatives[obj.tag], obj); + } + if (decoder instanceof RecursiveDecoder) { + return computeSize(decoder._self, value); + } + if (decoder instanceof TupleDecoder) { + const tupleVal = value as any as any[]; + return decoder._tuple.reduce((acc, v, i) => acc + computeSize(v, tupleVal[i]), 0); + } + return absurd(decoder); +} + +export function runDecoder( + decoder: Decoder, + mem: Uint8Array, + ptr: HaskellPointer, +): [A, HaskellPointer] { + if (decoder instanceof Int8Decoder) { + const result = mem[ptr] as any as A; + return [result, ptr + 1]; + } + if (decoder instanceof Int64Decoder) { + // Data.Binary encodes the integers with Big Endian encoding, what + // the heck? + const val = mem[ptr + 7] + + (mem[ptr + 6] << 8) + + (mem[ptr + 5] << 16) + + (mem[ptr + 4] << 24) + + (mem[ptr + 3] << 32) + + (mem[ptr + 2] << 40) + + (mem[ptr + 1] << 48) + + (mem[ptr] << 56); + return [val as any as A, ptr + 8]; + } + if (decoder instanceof Float64Decoder) { + // FFS: Data.Binary represents a Double as a tuple (Integer, Int) + // which is 25 bytes long! + + // const buffer = new ArrayBuffer(8); + // const uint8View = new Uint8Array(buffer); + // uint8View[0] = mem[ptr]; + // uint8View[1] = mem[ptr + 1]; + // uint8View[2] = mem[ptr + 2]; + // uint8View[3] = mem[ptr + 3]; + // uint8View[4] = mem[ptr + 4]; + // uint8View[5] = mem[ptr + 5]; + // uint8View[6] = mem[ptr + 6]; + // uint8View[7] = mem[ptr + 7]; + // const float64View = new Float64Array(buffer); + // const val = float64View[0]; + // return [val as any as A, ptr + 8]; + throw new Error("Unimplemented"); + } + if (decoder instanceof StringDecoder) { + const len = mem[ptr + 7] + + (mem[ptr + 6] << 8) + + (mem[ptr + 5] << 16) + + (mem[ptr + 4] << 24) + + (mem[ptr + 3] << 32) + + (mem[ptr + 2] << 40) + + (mem[ptr + 1] << 48) + + (mem[ptr] << 56); + const strView = mem.subarray(ptr + 8, ptr + 8 + len); + const resultStr = new TextDecoder("utf8").decode(strView) as any as A; + return [resultStr, ptr + 8 + len]; + } + if (decoder instanceof Uint8ArrayDecoder) { + const len = mem[ptr + 7] + + (mem[ptr + 6] << 8) + + (mem[ptr + 5] << 16) + + (mem[ptr + 4] << 24) + + (mem[ptr + 3] << 32) + + (mem[ptr + 2] << 40) + + (mem[ptr + 1] << 48) + + (mem[ptr] << 56); + const resultU8Arr = mem.subarray(ptr + 8, ptr + 8 + len) as any as A; + return [resultU8Arr, ptr + 8 + len]; + } + if (decoder instanceof ArrayDecoder) { + const len = mem[ptr + 7] + + (mem[ptr + 6] << 8) + + (mem[ptr + 5] << 16) + + (mem[ptr + 4] << 24) + + (mem[ptr + 3] << 32) + + (mem[ptr + 2] << 40) + + (mem[ptr + 1] << 48) + + (mem[ptr] << 56); + const resultArr = []; + let jx = ptr + 8; + for (let i = 0; i < len; i++) { + const [val, newIx] = runDecoder(decoder._element, mem, jx); + resultArr.push(val); + jx = newIx; + } + return [resultArr as any as A, jx]; + } + if (decoder instanceof RecordDecoder) { + let jx = ptr; + const resultRec = Object.fromEntries( + Object.entries(decoder._description).map(([k, dec]) => { + const [val, newIx] = runDecoder(dec, mem, jx); + jx = newIx; + return [k, val]; + }) + ); + return [resultRec as any as A, jx]; + } + if (decoder instanceof OneOfDecoder) { + const dscrSize = discriminatorSize(Object.keys(decoder._alternatives).length); + const [tag, ix1] = readDiscriminator(dscrSize, mem, ptr); + const [oneValue, ix2] = runDecoder(decoder._alternatives[tag], mem, ix1); + oneValue['tag'] = tag; + return [oneValue, ix2]; + } + if (decoder instanceof RecursiveDecoder) { + return runDecoder(decoder._self, mem, ptr); + } + if (decoder instanceof TupleDecoder) { + let jx = ptr; + const resultTup = decoder._tuple.map(dec => { + const [val, newIx] = runDecoder(dec, mem, jx); + jx = newIx; + return val; + }); + return [resultTup as any as A, jx]; + } + return absurd(decoder); +} + +export function runEncoder( + decoder: Decoder, + mem: Uint8Array, + ptr: HaskellPointer, + value: A, +): HaskellPointer { + if (decoder instanceof Int8Decoder) { + mem[ptr] = value as any as number; + return ptr + 1; + } + if (decoder instanceof Int64Decoder) { + const val = value as any as number; + mem[ptr + 7] = val & 0xFF; + mem[ptr + 6] = (val >> 8) & 0xFF; + mem[ptr + 5] = (val >> 16) & 0xFF; + mem[ptr + 4] = (val >> 24) & 0xFF; + // mem[ptr + 3] = (val >> 32) & 0xFF; + // mem[ptr + 2] = (val >> 40) & 0xFF; + // mem[ptr + 1] = (val >> 48) & 0xFF; + // mem[ptr] = (val >> 56) & 0xFF; + return ptr + 8; + } + if (decoder instanceof Float64Decoder) { + throw new Error("Unimplemented"); + } + if (decoder instanceof StringDecoder) { + const str = value as any as string; + const encoder = new TextEncoder(); + const strView = encoder.encode(str); + const len = strView.length; + mem[ptr + 7] = len & 0xFF; + mem[ptr + 6] = (len >> 8) & 0xFF; + mem[ptr + 5] = (len >> 16) & 0xFF; + mem[ptr + 4] = (len >> 24) & 0xFF; + // mem[ptr + 3] = (len >> 32) & 0xFF; + // mem[ptr + 2] = (len >> 40) & 0xFF; + // mem[ptr + 1] = (len >> 48) & 0xFF; + // mem[ptr] = (len >> 56) & 0xFF; + mem.set(strView, ptr + 8); + return ptr + 8 + len; + } + if (decoder instanceof Uint8ArrayDecoder) { + const u8Array = value as any as Uint8Array; + const len = u8Array.length; + mem[ptr + 7] = len & 0xFF; + mem[ptr + 6] = (len >> 8) & 0xFF; + mem[ptr + 5] = (len >> 16) & 0xFF; + mem[ptr + 4] = (len >> 24) & 0xFF; + // mem[ptr + 3] = (len >> 32) & 0xFF; + // mem[ptr + 2] = (len >> 40) & 0xFF; + // mem[ptr + 1] = (len >> 48) & 0xFF; + // mem[ptr] = (len >> 56) & 0xFF; + mem.set(u8Array, ptr + 8); + return ptr + 8 + len; + } + if (decoder instanceof ArrayDecoder) { + const array = value as any as any[]; + const len = array.length; + mem[ptr + 7] = len & 0xFF; + mem[ptr + 6] = (len >> 8) & 0xFF; + mem[ptr + 5] = (len >> 16) & 0xFF; + mem[ptr + 4] = (len >> 24) & 0xFF; + // mem[ptr + 3] = (len >> 32) & 0xFF; + // mem[ptr + 2] = (len >> 40) & 0xFF; + // mem[ptr + 1] = (len >> 48) & 0xFF; + // mem[ptr] = (len >> 56) & 0xFF; + let jx = ptr + 8; + for (let i = 0; i < len; i++) { + jx = runEncoder(decoder._element, mem, jx, array[i]); + } + return jx; + } + if (decoder instanceof RecordDecoder) { + const obj = value as Record; + let jx = ptr; + for (const k in decoder._description) { + if (Object.prototype.hasOwnProperty.call(decoder._description, k)) { + jx = runEncoder(decoder._description[k], mem, jx, obj[k]); + } + } + return jx; + } + if (decoder instanceof OneOfDecoder) { + const tag = (value as any)['tag']; + const dscrSize = discriminatorSize(Object.keys(decoder._alternatives).length); + mem[ptr] = tag; + return runEncoder(decoder._alternatives[tag], mem, ptr + dscrSize, value); + } + if (decoder instanceof RecursiveDecoder) { + return runEncoder(decoder._self, mem, ptr, value); + } + if (decoder instanceof TupleDecoder) { + const tupleVal = value as any[]; + let jx = ptr; + decoder._tuple.forEach((dec, i) => { + jx = runEncoder(dec, mem, jx, tupleVal[i]); + }); + return jx; + } + return absurd(decoder); +} + +function discriminatorSize(numAlernatives: number): number { + return Math.ceil(Math.log2(numAlernatives) / 8); +} + +function readDiscriminator(dscrSize: number, mem: Uint8Array, ix: HaskellPointer): [number, HaskellPointer] { + // TODO: complete implementation for dscrSize > 1 + if (dscrSize != 1) throw new Error('Unimplemented'); + return [mem[ix], ix + 1]; +} + +export const int8 = new Int8Decoder(); + +export const int64 = new Int64Decoder(); + +export const float64 = new Float64Decoder(); + +export const string = new StringDecoder(); + +export const u8array = new Uint8ArrayDecoder(); + +export function array(d: Decoder): ArrayDecoder { + return new ArrayDecoder(d); +} + +export function record }>(fields: fields): RecordDecoder<{[k in keyof fields]: fields[k]['_A'] }> { + return new RecordDecoder(fields); +} + +export type NarrowDownByTag< + Alternatives extends Record> + > = OneOfDecoder<{ [K in keyof Alternatives]: { tag: K } & Alternatives[K]['_A']}[keyof Alternatives]>; + +export function discriminate>>(alts: Alternatives): NarrowDownByTag { + return new OneOfDecoder(alts); +} + +export function tuple[]>(...args: Args): TupleDecoder<{[k in keyof Args]: Args[k]['_A'] }> { + return new TupleDecoder(args); +} + +export function recursive(f: (self: Decoder) => Decoder): Decoder { + const self = new RecursiveDecoder(undefined as any); + const result = f(self); + self._self = result; + return result; +} + +export type Maybe + = { tag: MaybeTag.Nothing } + | { tag: MaybeTag.Just, 0: A }; + +export enum MaybeTag { Nothing, Just }; + +export function maybe(decoder: Decoder): Decoder> { + return discriminate({ + [MaybeTag.Nothing]: record({}), + [MaybeTag.Just]: record({ 0: decoder }) + }); +} diff --git a/jsbits/ffi.ts b/jsbits/ffi.ts new file mode 100644 index 0000000..49bfb1a --- /dev/null +++ b/jsbits/ffi.ts @@ -0,0 +1,64 @@ +import * as p from './protocol'; +import { JavaScriptMessage, HaskellMessageTag, List, JavaScriptMessageTag } from './protocol'; + +export type HaskellPointer = number; + +export type HaskellExports = { + hs_init: () => void; + malloc: (size: number) => HaskellPointer; + memory: WebAssembly.Memory; +}; + +export function loadBuffer(exports: HaskellExports, ptr: HaskellPointer): Uint8Array { + const b = new Uint8Array(exports.memory.buffer, ptr); + const len = b[0] + + (b[1] << 8) + + (b[2] << 16) + + (b[3] << 24) + + (b[4] << 32) + + (b[5] << 40) + + (b[6] << 48) + + (b[7] << 56); + const buf = (new Uint8Array(exports.memory.buffer, ptr + 8, len)).slice().buffer; + return new Uint8Array(buf); +} + +export function storeBuffer(exports: HaskellExports, u8array: Uint8Array): HaskellPointer { + const len = u8array.byteLength; + const ptr = exports.malloc(u8array.length + 8); + // Write the length of the buffer as 8 bytes before the buffer + const view = new DataView(exports.memory.buffer); + view.setUint32(ptr, len, true); + + // Copy the buffer into WebAssembly memory + const dest = new Uint8Array(exports.memory.buffer, ptr + 8, len); + dest.set(u8array); + return ptr; +} + +export function evalMessageFFI(exports: HaskellExports, ptr: HaskellPointer): HaskellPointer { + const inbuf = loadBuffer(exports, ptr); + const haskMsg = p.haskellMessage.decode(inbuf); + const jsCallback = (_jsMsg: JavaScriptMessage, _argScope: List) => { + // TODO + }; + switch (haskMsg.tag) { + case HaskellMessageTag.EvalExpr: { + const result = p.evalExpr(jsCallback, null, null, haskMsg.expr); + const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, 0: p.unknownToValue(result) }; + const outbuf = p.javascriptMessage.encode(jsmsg); + return storeBuffer(exports, outbuf); + } + case HaskellMessageTag.HotReload: { + window.location.reload(); + const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, 0: p.unknownToValue(null) }; + const outbuf = p.javascriptMessage.encode(jsmsg); + return storeBuffer(exports, outbuf); + } + case HaskellMessageTag.Halt: { + const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, 0: p.unknownToValue(null) }; + const outbuf = p.javascriptMessage.encode(jsmsg); + return storeBuffer(exports, outbuf); + } + } +} diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index 9c3c9f2..f5b5c8d 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -1,3 +1,5 @@ +import { evalMessageFFI } from './ffi'; + // This file implements the JavaScript runtime logic for Haskell // modules that use JSFFI. It is not an ESM module, but the template // of one; the post-linker script will copy all contents into a new diff --git a/jsbits/lib.ts b/jsbits/lib.ts new file mode 100644 index 0000000..710a5f1 --- /dev/null +++ b/jsbits/lib.ts @@ -0,0 +1,100 @@ + +/** Helper for totality checking */ +export function absurd(_x: never): any { + throw new Error('absurd: unreachable code'); +} + +export class IntMap { + public counter: number; + public map: Map; + + constructor() { + this.counter = 0; + this.map = new Map(); + } + + /** + * Generates a new key using the internal counter and maps it to the provided value. + * @param value The value to be mapped to the new key. + * @returns The generated key. + */ + push(value: T): number { + const key = this.counter++; + this.map.set(key, value); + return key; + } + + /** + * Sets the provided key to the specified value. + * @param key The key to set. + * @param value The value to be associated with the key. + */ + set(key: number, value: T): void { + this.map.set(key, value); + } + + /** + * Gets the value associated with the provided key. + * @param key The key to retrieve. + * @returns The value associated with the key, or undefined if the key is not found. + */ + get(key: number): T | undefined { + return this.map.get(key); + } + + /** + * Deletes the key and its associated value from the map. + * @param key The key to delete. + * @returns True if the key was found and deleted, false otherwise. + */ + delete(key: number): boolean { + return this.map.delete(key); + } + + /** + * Checks if the map contains the specified key. + * @param key The key to check. + * @returns True if the key is present in the map, false otherwise. + */ + has(key: number): boolean { + return this.map.has(key); + } + + /** + * Clears all keys and values from the map. + */ + clear(): void { + this.map.clear(); + } + + /** + * Returns an array of all keys in the map. + * @returns An array containing all keys in the map. + */ + keys(): IterableIterator { + return this.map.keys(); + } + + /** + * Returns an array of all values in the map. + * @returns An array containing all values in the map. + */ + values(): IterableIterator { + return this.map.values(); + } + + /** + * Returns an array of key-value pairs in the map. + * @returns An array containing key-value pairs in the map. + */ + entries(): IterableIterator<[number, T]> { + return this.map.entries(); + } + + /** + * Executes a provided function once per each key/value pair in the Map, in insertion order. + */ + forEach(callbackfn: (value: T, key: number, map: Map) => void, thisArg?: any): void { + this.map.forEach(callbackfn, thisArg); + } +} diff --git a/jsbits/post-link.mjs b/jsbits/post-link.mjs new file mode 100755 index 0000000..9981c7e --- /dev/null +++ b/jsbits/post-link.mjs @@ -0,0 +1,100 @@ +#!/nix/store/x1xcjw5628crkk1pwr12y7nwbzkc3969-coreutils-9.4/bin/env -S node + +// This is the post-linker program that processes a wasm module with +// ghc_wasm_jsffi custom section and outputs an ESM module that +// exports a function to generate the ghc_wasm_jsffi wasm imports. It +// has a simple CLI interface: "./post-link.mjs -i foo.wasm -o +// foo.js", as well as an exported postLink function that takes a +// WebAssembly.Module object and returns the ESM module content. + +import fs from "node:fs/promises"; +import path from "node:path"; +import util from "node:util"; + +// Each record in the ghc_wasm_jsffi custom section are 3 +// NUL-terminated strings: name, binder, body. We try to parse the +// body as an expression and fallback to statements, and return the +// completely parsed arrow function source. +function parseRecord([name, binder, body]) { + for (const src of [`${binder} => (${body})`, `${binder} => {${body}}`]) { + try { + new Function(`return ${src};`); + return src; + } catch (_) {} + } + throw new Error(`parseRecord ${name} ${binder} ${body}`); +} + +// Parse ghc_wasm_jsffi custom sections in a WebAssembly.Module object +// and return an array of records. +function parseSections(mod) { + const recs = []; + const dec = new TextDecoder("utf-8", { fatal: true }); + const importNames = new Set( + WebAssembly.Module.imports(mod) + .filter((i) => i.module === "ghc_wasm_jsffi") + .map((i) => i.name), + ); + for (const buf of WebAssembly.Module.customSections(mod, "ghc_wasm_jsffi")) { + const ba = new Uint8Array(buf); + let strs = []; + for (let l = 0, r; l < ba.length; l = r + 1) { + r = ba.indexOf(0, l); + strs.push(dec.decode(ba.subarray(l, r))); + if (strs.length === 3) { + if (importNames.has(strs[0])) { + recs.push(strs); + } + strs = []; + } + } + } + return recs; +} + + +export async function postLink(mod) { + let src = await fs.readFile(path.join(import.meta.dirname, "prelude.js"), { + encoding: "utf-8", + }); + src = `${src}\nexport default (__exports) => {`; + src = `${src}\nconst __ghc_wasm_jsffi_jsval_manager = new JSValManager();`; + src = `${src}\nconst __ghc_wasm_jsffi_finalization_registry = new FinalizationRegistry(sp => __exports.rts_freeStablePtr(sp));`; + src = `${src}\nreturn {`; + src = `${src}\nnewJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v),`; + src = `${src}\ngetJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k),`; + src = `${src}\nfreeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k),`; + src = `${src}\nscheduleWork: () => setImmediate(__exports.rts_schedulerLoop),`; + for (const rec of parseSections(mod)) { + src = `${src}\n${rec[0]}: ${parseRecord(rec)},`; + } + return `${src}\n};\n};\n`; +} + +function isMain() { + return import.meta.filename === process.argv[1]; +} + +async function main() { + const { input, output } = util.parseArgs({ + options: { + input: { + type: "string", + short: "i", + }, + output: { + type: "string", + short: "o", + }, + }, + }).values; + + await fs.writeFile( + output, + await postLink(await WebAssembly.compile(await fs.readFile(input))) + ); +} + +if (isMain()) { + await main(); +} diff --git a/jsbits/prelude.js b/jsbits/prelude.js new file mode 100644 index 0000000..dc9d257 --- /dev/null +++ b/jsbits/prelude.js @@ -0,0 +1,93 @@ +import { evalMessageFFI } from './ffi'; + +// This file implements the JavaScript runtime logic for Haskell +// modules that use JSFFI. It is not an ESM module, but the template +// of one; the post-linker script will copy all contents into a new +// ESM module. + +// Manage a mapping from unique 32-bit ids to actual JavaScript +// values. +class JSValManager { + #lastk = 0; + #kv = new Map(); + + constructor() {} + + // Maybe just bump this.#lastk? For 64-bit ids that's sufficient, + // but better safe than sorry in the 32-bit case. + #allocKey() { + let k = this.#lastk; + while (true) { + if (!this.#kv.has(k)) { + this.#lastk = k; + return k; + } + k = (k + 1) | 0; + } + } + + newJSVal(v) { + const k = this.#allocKey(); + this.#kv.set(k, v); + return k; + } + + // A separate has() call to ensure we can store undefined as a value + // too. Also, unconditionally check this since the check is cheap + // anyway, if the check fails then there's a use-after-free to be + // fixed. + getJSVal(k) { + if (!this.#kv.has(k)) { + throw new WebAssembly.RuntimeError(`getJSVal(${k})`); + } + return this.#kv.get(k); + } + + // Check for double free as well. + freeJSVal(k) { + if (!this.#kv.delete(k)) { + throw new WebAssembly.RuntimeError(`freeJSVal(${k})`); + } + } +} + +// A simple & fast setImmediate() implementation for browsers. It's +// not a drop-in replacement for node.js setImmediate() because: +// 1. There's no clearImmediate(), and setImmediate() doesn't return +// anything +// 2. There's no guarantee that callbacks scheduled by setImmediate() +// are executed in the same order (in fact it's the opposite lol), +// but you are never supposed to rely on this assumption anyway +class SetImmediate { + #fs = []; + #mc = new MessageChannel(); + + constructor() { + this.#mc.port1.addEventListener("message", () => { + this.#fs.pop()(); + }); + this.#mc.port1.start(); + } + + setImmediate(cb, ...args) { + this.#fs.push(() => cb(...args)); + this.#mc.port2.postMessage(undefined); + } +} + +// The actual setImmediate() to be used. This is a ESM module top +// level binding and doesn't pollute the globalThis namespace. +let setImmediate; +if (globalThis.setImmediate) { + // node.js, bun + setImmediate = globalThis.setImmediate; +} else { + /* try { + * // deno + * setImmediate = (await import("node:timers")).setImmediate; + * } catch { */ + // browsers + const sm = new SetImmediate(); + setImmediate = (cb, ...args) => sm.setImmediate(cb, ...args); + /* } */ +} diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts new file mode 100644 index 0000000..db8437a --- /dev/null +++ b/jsbits/protocol.ts @@ -0,0 +1,653 @@ +import * as b from './binary'; +import { Maybe, MaybeTag } from './binary'; +import { absurd, IntMap } from './lib'; + +export type JSFunctionName = string; + +export type Ident = string; + +export type Bindings = Record; + +export type List = null | Cons; + +export type Cons = { 0: T, 1: List }; + +export function Cons(x: T, xs: List): List { + return [x, xs]; +} + +export function car(pair: Cons): T { + return pair[0]; +} + +export function cdr(pair: Cons): List { + return pair[1]; +} + +export type HaskellCallback = (jsMsg: JavaScriptMessage, argScope: List) => void; + +export function evalExpr(hscb: HaskellCallback, idenScope: List, argScope: List, exp: Expr): unknown { + switch(exp.tag) { + case ExprTag.Null: { + return null; + } + case ExprTag.Boolean: { + return exp[0] != 0; + } + case ExprTag.I64: { + return exp[0]; + } + case ExprTag.F64: { + return exp[0]; + } + case ExprTag.String: { + return exp[0]; + } + case ExprTag.Array: { + return exp[0].map(evalExpr.bind(undefined, hscb, idenScope, argScope)); + } + case ExprTag.Object: { + return Object.fromEntries(exp[0].map(([k, e]) => [k, evalExpr(hscb, idenScope, argScope, e)])); + } + case ExprTag.Uint8Array: { + return exp[0]; + } + case ExprTag.Dot: { + const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as any; + return lhs[exp[1]]; + } + case ExprTag.SetProp: { + const rhs = evalExpr(hscb, idenScope, argScope, exp[2]); + const obj = evalExpr(hscb, idenScope, argScope, exp[0]) as any; + obj[exp[1]] = rhs; + return rhs; + } + case ExprTag.Ix: { + const rhs: any = evalExpr(hscb, idenScope, argScope, exp.exp); + return rhs[exp.ix]; + } + case ExprTag.Add: { + const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as number; + const rhs = evalExpr(hscb, idenScope, argScope, exp[1]) as number; + return lhs + rhs; + } + case ExprTag.Subtract: { + const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as number; + const rhs = evalExpr(hscb, idenScope, argScope, exp[1]) as number; + return lhs - rhs; + } + case ExprTag.Multiply: { + const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as number; + const rhs = evalExpr(hscb, idenScope, argScope, exp[1]) as number; + return lhs * rhs; + } + case ExprTag.Divide: { + const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as number; + const rhs = evalExpr(hscb, idenScope, argScope, exp[1]) as number; + return lhs / rhs; + } + case ExprTag.Id: { + const ident = exp[0]; + for (let iter = idenScope; iter; iter = cdr(iter)) { + const bindings = car(iter); + if (ident in bindings) { + // Found bound value + return bindings[ident]; + } + } + throw new Error('Variable not in scope: ' + exp[0]); + } + case ExprTag.Lam: { + return function() { + return evalExpr(hscb, idenScope, Cons(arguments, argScope), exp.body); + }; + } + case ExprTag.Arg: { + let iter = argScope; + let j = 0; + while (iter) { + if (j == exp.scopeIx) { + const iarguments = car(iter); + return iarguments[exp.argIx]; + } + iter = cdr(iter); + j++; + } + throw new Error('Argument scope out of a range: ' + exp.scopeIx); + } + case ExprTag.Apply: { + const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as Function; + return lhs.apply(undefined, exp[1].map(evalExpr.bind(undefined, hscb, idenScope, argScope))); + } + case ExprTag.Call: { + const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as any; + const fn = lhs[exp[1]]; + return fn.apply(lhs, exp[2].map(evalExpr.bind(undefined, hscb, idenScope, argScope))); + } + case ExprTag.AssignVar: { + const rhs = evalExpr(hscb, idenScope, argScope, exp.rhs); + if (varStorage.has(exp.scopeId)) { + const scopeMap = varStorage.get(exp.scopeId)!; + scopeMap.set(exp.varId, rhs); + } else { + const scopeMap = new Map(); + scopeMap.set(exp.varId, rhs); + varStorage.set(exp.scopeId, scopeMap); + } + return rhs; + } + case ExprTag.FreeVar: { + const scopeStorage = varStorage.get(exp.scopeId); + if (!scopeStorage) return; + scopeStorage.delete(exp.varId); + if (scopeStorage.size == 0) { + varStorage.delete(exp.scopeId); + } + return; + } + case ExprTag.Var: { + return varStorage.get(exp.scopeId)?.get(exp.varId); + } + case ExprTag.FreeScope: { + varStorage.delete(exp.scopeId); + const scopeFinalizers = finalizers.get(exp.scopeId); + if (scopeFinalizers) scopeFinalizers.forEach(fn => fn ()); + return null; + } + case ExprTag.InsertNode: { + const parent = evalExpr(hscb, idenScope, argScope, exp.parent) as Element|Comment; + const child = evalExpr(hscb, idenScope, argScope, exp.child) as Node; + domHelpers.insertIntoBuilder(parent, child); + return null; + } + case ExprTag.HtmlBuilder: { + const dest = evalExpr(hscb, idenScope, argScope, exp.dest) as Element|Comment; + const builderFn = evalExpr(hscb, idenScope, argScope, exp.builderFn) as Function; + builderFn(dest); + return dest; + } + case ExprTag.CreateElement: { + return document.createElement(exp.tagName); + } + case ExprTag.CreateElementNS: { + return document.createElementNS(exp.ns, exp.tagName); + } + case ExprTag.CreateText: { + return document.createTextNode(exp.content); + } + case ExprTag.ElementProp: { + const parent = evalExpr(hscb, idenScope, argScope, exp.node) as Element|Comment; + const propValue = evalExpr(hscb, idenScope, argScope, exp.propValue); + domHelpers.assignProperty(parent, exp.propName, propValue); + return null; + } + case ExprTag.ElementAttr: { + const parent = evalExpr(hscb, idenScope, argScope, exp.node) as Element|Comment; + domHelpers.assignAttribute(parent, exp.attrName, exp.attrValue); + return null; + } + case ExprTag.InsertClassList: { + const parent = evalExpr(hscb, idenScope, argScope, exp.node) as Element|Comment; + const element = domHelpers.domBuilderElement(parent); + exp.classList.forEach(className => element.classList.add(className)); + return null; + } + case ExprTag.RemoveClassList: { + const parent = evalExpr(hscb, idenScope, argScope, exp.node) as Element|Comment; + const element = domHelpers.domBuilderElement(parent); + exp.classList.forEach(className => element.classList.remove(className)); + return null; + } + case ExprTag.UpdateTextNode: { + const node = evalExpr(hscb, idenScope, argScope, exp.node) as Text; + node.textContent = exp.content; + return null; + } + case ExprTag.InsertBoundary: { + const parent = evalExpr(hscb, idenScope, argScope, exp.parent) as Element|Comment; + return domHelpers.insertBoundary(parent); + } + case ExprTag.ClearBoundary: { + const boundary = evalExpr(hscb, idenScope, argScope, exp.boundary) as Comment; + return domHelpers.clearBoundary(boundary, Boolean(exp.detach)); + } + case ExprTag.AddEventListener: { + const target = evalExpr(hscb, idenScope, argScope, exp.target) as Element|Comment; + const eventName = evalExpr(hscb, idenScope, argScope, exp.eventName) as string; + const listener = evalExpr(hscb, idenScope, argScope, exp.listener) as EventListener; + domHelpers.addEventListener(target, eventName, listener); + const existingScope = finalizers.get(exp.reactiveScope); + const scopeFinalizers = existingScope ? existingScope : new IntMap(); + if (!existingScope) finalizers.set(exp.reactiveScope, scopeFinalizers); + return scopeFinalizers.push(() => domHelpers.removeEventListener(target, eventName, listener)); + } + case ExprTag.SetTimeout: { + const callback = evalExpr(hscb, idenScope, argScope, exp.callback) as Function; + const existingScope = finalizers.get(exp.reactiveScope); + const scopeFinalizers = existingScope ? existingScope : new IntMap(); + if (!existingScope) finalizers.set(exp.reactiveScope, scopeFinalizers); + let timeoutId: NodeJS.Timeout|null = null; + const finalizerId = scopeFinalizers.push(() => timeoutId && clearTimeout(timeoutId)); + timeoutId = setTimeout(() => { + scopeFinalizers.delete(finalizerId); + timeoutId = null; + callback(); + }, exp.timeout); + return finalizerId; + } + case ExprTag.ApplyFinalizer: { + const existingScope = finalizers.get(exp.reactiveScope); + const finalizerId = evalExpr(hscb, idenScope, argScope, exp.finalizerId) as number; + if (!existingScope) return false; + const cancellerFn = existingScope.get(finalizerId); + if (!cancellerFn) return false; + existingScope.delete(finalizerId); + cancellerFn(); + return true; + } + case ExprTag.RevSeq: { + return exp.exprs.reduceRight((_, e) => evalExpr(hscb, idenScope, argScope, e), null); + } + case ExprTag.Eval: { + return eval(exp.rawJavaScript); + } + case ExprTag.TriggerCallback: { + const arg = evalExpr(hscb, idenScope, argScope, exp.arg); + const jsMsg: JavaScriptMessage = { + tag: JavaScriptMessageTag.TriggerCallback, + arg: unknownToValue(arg), + callbackId: exp.callbackId, + } + return hscb(jsMsg, argScope); + } + case ExprTag.UncaughtException: { + throw new Error(exp.message); + } + } + absurd(exp); +} + +export function unknownToValue(inp: unknown): Value { + if (typeof(inp) === 'boolean') { + return { tag: ValueTag.Boolean, 0: inp ? 1 : 0 }; + } + if (typeof(inp) === 'number') { + if (Number.isInteger(inp)) { + return { tag: ValueTag.I64, 0: inp }; + } else { + return { tag: ValueTag.F64, 0: inp }; + } + } + if (typeof(inp) === 'string') { + return { tag: ValueTag.String, 0: inp }; + } + if (Array.isArray(inp)) { + return { tag: ValueTag.Array, 0: inp.map(unknownToValue) }; + } + if (inp instanceof Uint8Array) { + return { tag: ValueTag.Uint8Array, 0: inp }; + } + if (inp === null || inp === undefined) { + return { tag: ValueTag.Null }; + } + const entries = Object.entries(inp) + .map(([k, v]) => [k, unknownToValue(v)] as KV); + + return { tag: ValueTag.Object, 0: entries } + + type KV = [string, Value]; +} + +export enum ValueTag { + Null, + Boolean, + I64, + F64, + String, + Array, + Object, + Uint8Array, +} + +export type Value = + | { tag: ValueTag.Null } + | { tag: ValueTag.Boolean, 0: number } + | { tag: ValueTag.I64, 0: number } + | { tag: ValueTag.F64, 0: number } + | { tag: ValueTag.String, 0: string } + | { tag: ValueTag.Array, 0: Value[] } + | { tag: ValueTag.Object, 0: [string, Value][] } + | { tag: ValueTag.Uint8Array, 0: Uint8Array } +; + +export const jvalue = b.recursive(self => b.discriminate({ + [ValueTag.Null]: b.record({ }), + [ValueTag.Boolean]: b.record({ 0: b.int8 }), + [ValueTag.I64]: b.record({ 0: b.int64 }), + [ValueTag.F64]: b.record({ 0: b.float64 }), + [ValueTag.String]: b.record({ 0: b.string }), + [ValueTag.Array]: b.record({ 0: b.array(self) }), + [ValueTag.Object]: b.record({ 0: b.array(b.tuple(b.string, self)) }), + [ValueTag.Uint8Array]: b.record({ 0: b.u8array }), +})); + +export type StartLocation = { + protocol: string, + hostname: string, + port: string, + pathname: string, + search: string, + hash: string, +}; + +export const startLocation: b.Decoder = b.record({ + protocol: b.string, + hostname: b.string, + port: b.string, + pathname: b.string, + search: b.string, + hash: b.string, +}); + +export type StartFlags = { + initial_url: StartLocation; + window_inner_size: [number, number]; + devserver_connection_id: Maybe; +}; + +export const startFlags: b.Decoder = b.record({ + initial_url: startLocation, + window_inner_size: b.tuple(b.int64, b.int64), + devserver_connection_id: b.maybe(b.int64), +}); + +export enum ExprTag { + Null, + Boolean, + I64, + F64, + String, + Array, + Object, + Uint8Array, + + Dot, + SetProp, + Ix, + + Add, + Subtract, + Multiply, + Divide, + + Id, + Lam, + Arg, + Apply, + Call, + + AssignVar, + FreeVar, + Var, + FreeScope, + + HtmlBuilder, + InsertNode, + CreateElement, + CreateElementNS, + CreateText, + ElementProp, + ElementAttr, + InsertClassList, + RemoveClassList, + UpdateTextNode, + InsertBoundary, + ClearBoundary, + + AddEventListener, + SetTimeout, + ApplyFinalizer, + + RevSeq, + Eval, + TriggerCallback, + UncaughtException, +} + +export type Expr = + | { tag: ExprTag.Null } + | { tag: ExprTag.Boolean, 0: number } + | { tag: ExprTag.I64, 0: number } + | { tag: ExprTag.F64, 0: number } + | { tag: ExprTag.String, 0: string } + | { tag: ExprTag.Array, 0: Expr[] } + | { tag: ExprTag.Object, 0: [string, Expr][] } + | { tag: ExprTag.Uint8Array, 0: Uint8Array } + + | { tag: ExprTag.Dot, 0: Expr, 1: string } + | { tag: ExprTag.SetProp, 0: Expr, 1: string, 2: Expr } + | { tag: ExprTag.Ix, exp: Expr, ix: number } + + | { tag: ExprTag.Add, 0: Expr, 1: Expr } + | { tag: ExprTag.Subtract, 0: Expr, 1: Expr } + | { tag: ExprTag.Multiply, 0: Expr, 1: Expr } + | { tag: ExprTag.Divide, 0: Expr, 1: Expr } + + | { tag: ExprTag.Id, 0: string } + | { tag: ExprTag.Lam, body: Expr } + | { tag: ExprTag.Arg, scopeIx: number, argIx: number } + | { tag: ExprTag.Apply, 0: Expr, 1: Expr[] } + | { tag: ExprTag.Call, 0: Expr, 1: JSFunctionName, 2: Expr[] } + + | { tag: ExprTag.AssignVar, scopeId: number, varId: number, rhs: Expr } + | { tag: ExprTag.FreeVar, scopeId: number, varId: number } + | { tag: ExprTag.Var, scopeId: number, varId: number } + | { tag: ExprTag.FreeScope, scopeId: number } + + | { tag: ExprTag.InsertNode, parent: Expr, child: Expr } + | { tag: ExprTag.HtmlBuilder, dest: Expr, builderFn: Expr } + | { tag: ExprTag.CreateElement, tagName: string } + | { tag: ExprTag.CreateElementNS, ns: string, tagName: string } + | { tag: ExprTag.CreateText, content: string } + | { tag: ExprTag.ElementProp, node: Expr, propName: string, propValue: Expr } + | { tag: ExprTag.ElementAttr, node: Expr, attrName: string, attrValue: string } + | { tag: ExprTag.InsertClassList, node: Expr, classList: string[] } + | { tag: ExprTag.RemoveClassList, node: Expr, classList: string[] } + | { tag: ExprTag.UpdateTextNode, node: Expr, content: string } + | { tag: ExprTag.InsertBoundary, parent: Expr } + | { tag: ExprTag.ClearBoundary, boundary: Expr, detach: number } + + | { tag: ExprTag.AddEventListener, reactiveScope: number, target: Expr, eventName: Expr, listener: Expr } + | { tag: ExprTag.SetTimeout, reactiveScope: number, callback: Expr, timeout: number } + | { tag: ExprTag.ApplyFinalizer, reactiveScope: number, finalizerId: Expr } + + | { tag: ExprTag.RevSeq, exprs: Expr[] } + | { tag: ExprTag.Eval, rawJavaScript: string } + | { tag: ExprTag.TriggerCallback, callbackId: number, arg: Expr } + | { tag: ExprTag.UncaughtException, message: string } +; + +export const expr = b.recursive(self => b.discriminate({ + [ExprTag.Null]: b.record({}), + [ExprTag.Boolean]: b.record({ 0: b.int8 }), + [ExprTag.I64]: b.record({ 0: b.int64 }), + [ExprTag.F64]: b.record({ 0: b.float64 }), + [ExprTag.String]: b.record({ 0: b.string }), + [ExprTag.Array]: b.record({ 0: b.array(self) }), + [ExprTag.Object]: b.record({ 0: b.array(b.tuple(b.string, self)) }), + + [ExprTag.Dot]: b.record({ 0: self, 1: b.string }), + [ExprTag.SetProp]: b.record({ 0: self, 1: b.string, 2: self }), + [ExprTag.Ix]: b.record({ exp: self, ix: b.int64 }), + + [ExprTag.Add]: b.record({ 0: self, 1: self }), + [ExprTag.Subtract]: b.record({ 0: self, 1: self }), + [ExprTag.Multiply]: b.record({ 0: self, 1: self }), + [ExprTag.Divide]: b.record({ 0: self, 1: self }), + + [ExprTag.Id]: b.record({ 0: b.string }), + [ExprTag.Lam]: b.record({ body: self }), + [ExprTag.Arg]: b.record({ scopeIx: b.int8, argIx: b.int8 }), + [ExprTag.Apply]: b.record({ 0: self, 1: b.array(self) }), + [ExprTag.Call]: b.record({ 0: self, 1: b.string, 2: b.array(self) }), + + [ExprTag.AssignVar]: b.record({ scopeId: b.int64, varId: b.int64, rhs: self }), + [ExprTag.FreeVar]: b.record({ scopeId: b.int64, varId: b.int64 }), + [ExprTag.Var]: b.record({ scopeId: b.int64, varId: b.int64 }), + [ExprTag.FreeScope]: b.record({ scopeId: b.int64 }), + + [ExprTag.InsertNode]: b.record({ parent: self, child: self }), + [ExprTag.HtmlBuilder]: b.record({ dest: self, builderFn: self }), + [ExprTag.CreateElement]: b.record({ tagName: b.string }), + [ExprTag.CreateElementNS]: b.record({ ns: b.string, tagName: b.string }), + [ExprTag.CreateText]: b.record({ content: b.string }), + [ExprTag.ElementProp]: b.record({ node: self, propName: b.string, propValue: self }), + [ExprTag.ElementAttr]: b.record({ node: self, attrName: b.string, attrValue: b.string }), + [ExprTag.InsertClassList]: b.record({ node: self, classList: b.array(b.string) }), + [ExprTag.RemoveClassList]: b.record({ node: self, classList: b.array(b.string) }), + [ExprTag.UpdateTextNode]: b.record({ node: self, content: b.string }), + [ExprTag.InsertBoundary]: b.record({ parent: self }), + [ExprTag.ClearBoundary]: b.record({ boundary: self, detach: b.int8 }), + + [ExprTag.AddEventListener]: b.record({ reactiveScope: b.int64, target: self, eventName: self, listener: self }), + [ExprTag.SetTimeout]: b.record({ reactiveScope: b.int64, callback: self, timeout: b.int64 }), + [ExprTag.ApplyFinalizer]: b.record({ reactiveScope: b.int64, finalizerId: self }), + + [ExprTag.RevSeq]: b.record({ exprs: b.array(self) }), + [ExprTag.Eval]: b.record({ rawJavaScript: b.string }), + [ExprTag.TriggerCallback]: b.record({ callbackId: b.int64, arg: self }), + [ExprTag.UncaughtException]: b.record({ message: b.string }), +})); + +export enum HaskellMessageTag { + EvalExpr, + HotReload, + Halt, +} + +export const haskellMessage = b.discriminate({ + [HaskellMessageTag.EvalExpr]: b.record({ expr: expr }), + [HaskellMessageTag.HotReload]: b.record({ }), + [HaskellMessageTag.Halt]: b.record({ }), +}); + +export enum JavaScriptMessageTag { + Start, + Return, + TriggerCallback, + BeforeUnload, +} + +export const javascriptMessage = b.discriminate({ + [JavaScriptMessageTag.Start]: b.record({ startFlags }), + [JavaScriptMessageTag.Return]: b.record({ 0: jvalue }), + [JavaScriptMessageTag.TriggerCallback]: b.record({ arg: jvalue, callbackId: b.int64 }), + [JavaScriptMessageTag.BeforeUnload]: b.record({}), +}); + +export type HaskellMessage = typeof haskellMessage['_A']; +export type JavaScriptMessage = typeof javascriptMessage['_A']; + +export type ReactiveScope = number; +export type VarId = number; + +export const varStorage = new Map>(); +export const finalizers = new Map>; + +export function mkStartMessage(): JavaScriptMessage { + const initial_url: StartLocation = { + protocol: location.protocol, + hostname: location.hostname, + port: location.port, + pathname: location.pathname, + search: location.search, + hash: location.hash, + }; + return { + tag: JavaScriptMessageTag.Start, + startFlags: { + initial_url, + window_inner_size: [window.innerWidth, window.innerHeight], + devserver_connection_id: { tag: MaybeTag.Nothing }, + } + }; +} + +namespace domHelpers { + export function insertIntoBuilder(builder: Element|Comment, child: Node): void { + if (builder instanceof Comment) { + builder.parentElement!.insertBefore(child, builder); + } else { + builder.appendChild(child); + } + } + + export function assignProperty(parent: Element|Comment, propName: string, propValue: unknown): void { + if (parent instanceof Comment) { + (parent.parentElement as any)[propName] = propValue; + } else { + (parent as any)[propName] = propValue; + } + } + + export function assignAttribute(builder: Element|Comment, attrName: string, attrValue: string): void { + const element = domBuilderElement(builder); + element.setAttribute(attrName, attrValue); + } + + export function addEventListener(builder: Element|Comment, eventName: string, listener: EventListener): void { + const element = domBuilderElement(builder); + element.addEventListener(eventName, listener); + } + + export function removeEventListener(builder: Element|Comment, eventName: string, listener: EventListener): void { + const element = domBuilderElement(builder); + element.removeEventListener(eventName, listener); + } + + export function insertBoundary(builder: Element|Comment): Comment { + const begin = document.createComment('ContentBoundary {{'); + const end = document.createComment('}}'); + insertIntoBuilder(builder, begin); + insertIntoBuilder(builder, end); + return end; + } + + export function clearBoundary(boundary: Comment, detach: boolean): void { + const end = boundary; + let nestedCounter = 0; + for (;;){ + if (!end.previousSibling || + (nestedCounter == 0 && isOpeningBoundary(end.previousSibling)) + ) break; + if (isClosingBoundary(end.previousSibling)) nestedCounter++; + else if (isOpeningBoundary(end.previousSibling)) nestedCounter--; + end.previousSibling!.parentNode!.removeChild(end.previousSibling!); + } + if (detach) { + end.previousSibling!.parentNode!.removeChild(end.previousSibling!); + end.parentNode!.removeChild(end); + } + } + + export function domBuilderElement(builder: Element|Comment): Element { + if (builder instanceof Comment) { + return builder.parentElement!; + } + return builder; + } + + function isOpeningBoundary(node: Node): boolean { + if (node instanceof Comment && node.textContent == 'ContentBoundary {{') { + return true; + } + return false; + } + + function isClosingBoundary(node: Node): boolean { + if (node instanceof Comment && node.textContent == '}}') { + return true; + } + return false; + } +}; diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index a4c0257..ae99227 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -11,6 +11,8 @@ import Clickable.FFI import Clickable.Internal (reactive, reactive_) import Clickable.Internal qualified as Internal import Clickable.Types +import Clickable.Protocol +import Clickable.Protocol.Value import Wasm.Compat.Prim @@ -62,6 +64,15 @@ writeVar var s = modifyVar var $ const s subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () subscribe val k = reactive_ $ Internal.subscribe val k +enqueueExpr :: Expr -> ClickM () +enqueueExpr e = modify \s -> s {evaluation_queue = e : s.evaluation_queue} + +evalExpr :: Expr -> ClickM Value +evalExpr e = do + send_command <- asks (.send_command) + queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) + liftIO $ send_command $ RevSeq $ e : queue + ------------------------- -- RESOURCE MANAGEMENT -- ------------------------- diff --git a/src/Clickable/FFI.hs b/src/Clickable/FFI.hs index 37a15ba..1bb8278 100644 --- a/src/Clickable/FFI.hs +++ b/src/Clickable/FFI.hs @@ -123,6 +123,9 @@ js_aquireResource = undefined js_apply0 :: JSVal -> IO () js_apply0 = undefined +js_evalMessageFFI :: Ptr Word8 -> IO (Ptr Word8) +js_evalMessageFFI = undefined + #else foreign import javascript unsafe "var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ @@ -247,4 +250,7 @@ foreign import javascript unsafe js_aquireResource :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO JSVal foreign import javascript unsafe "$1()" js_apply0 :: JSVal -> IO () +foreign import javascript unsafe + "evalMessageFFI(__exports, $1)" + js_evalMessageFFI :: Ptr Word8 {- HaskellMessage -} -> IO (Ptr Word8 {- JavaScriptMessage -}) #endif diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 37f463f..304dbb7 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -1,23 +1,36 @@ module Clickable.Internal where import Clickable.Types +import Clickable.Protocol +import Clickable.Protocol.Value qualified as Value +import Clickable.FFI qualified as FFI import Control.Monad.Reader import Control.Monad.State import Data.IORef import Data.List qualified as List import Data.Map qualified as Map import Unsafe.Coerce - +import Data.Binary qualified as Binary +import Data.ByteString.Lazy qualified as BSL +import Data.ByteString as BS +import Data.ByteString.Lazy qualified as BSL +import Data.ByteString.Unsafe qualified as BSU +import Data.Word +import Foreign.Marshal.Alloc qualified as Alloc +import Foreign.Marshal.Utils +import Foreign.Ptr +import Foreign.Storable +import System.IO.Unsafe emptyInternalState :: InternalState -emptyInternalState = InternalState [] [] Map.empty 0 +emptyInternalState = InternalState [] [] Map.empty [] 0 newInternalEnv :: IO InternalEnv newInternalEnv = do let scope = ResourceScope emptyInternalState.next_id internal_state_ref <- newIORef emptyInternalState {next_id = emptyInternalState.next_id + 1} - return InternalEnv {internal_state_ref, scope} + return InternalEnv {internal_state_ref, scope, send_command = sendMessage} unsafeTrigger :: SourceId -> a -> InternalState -> InternalState unsafeTrigger varId vals = go0 where @@ -94,3 +107,25 @@ reactive f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ reactive_ :: (ResourceScope -> InternalState -> InternalState) -> ClickM () reactive_ f = reactive \scope s -> (f scope s, ()) + +sendMessage :: HaskellMessage -> IO JavaScriptMessage +sendMessage hmsg = do + hptr <- storeByteString $ BSL.toStrict $ Binary.encode hmsg + jptr <- FFI.js_evalMessageFFI hptr + Alloc.free hptr + Binary.decode . BSL.fromStrict <$> loadByteString jptr + where + storeByteString :: ByteString -> IO (Ptr a) + storeByteString bs = do + let len = BS.length bs + dest <- Alloc.callocBytes (len + 8) + poke @Word64 dest (fromIntegral len) + BSU.unsafeUseAsCStringLen bs $ \(src, _) -> + copyBytes (dest `plusPtr` 8) src len + return (castPtr dest) + + loadByteString :: Ptr a -> IO ByteString + loadByteString ptr = do + len <- peek @Word64 (castPtr ptr) + let contentPtr = ptr `plusPtr` 8 + BSU.unsafePackCStringFinalizer contentPtr (fromIntegral len) (Alloc.free ptr) diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs new file mode 100644 index 0000000..13fde8d --- /dev/null +++ b/src/Clickable/Protocol.hs @@ -0,0 +1,198 @@ +module Clickable.Protocol where + +import Data.Binary (Binary) +import Data.ByteString (ByteString) +import Data.Int +import Data.Text (Text) +import Data.Word +import GHC.Generics + +import "this" Clickable.Protocol.Value qualified as Value + +data HaskellMessage + = EvalExpr Expr + -- ^ Evaluate expression, expect the result to be returned by + -- 'Return' message + | HotReload + -- ^ Used under dev server, won't return anything + | Halt + -- ^ Signal that current process completed, won't return anything + deriving stock (Generic, Show) + deriving anyclass (Binary) + +data JavaScriptMessage + = Start StartFlags + | Return Value.Value + | TriggerCallbackMsg Value.Value CallbackId + | BeforeUnload + -- ^ Fired from addEventListener("beforeunload") listener. Won't + -- work under the DevServer! + deriving stock (Generic, Show) + deriving anyclass (Binary) + +data StartFlags = StartFlags + { initial_url :: Location + , window_inner_size :: (Int64, Int64) + , devserver_connection_id :: Maybe Int64 + } deriving stock (Generic, Show) + deriving anyclass (Binary) + +data Location = Location + { protocol :: Text + -- ^ A string containing the protocol scheme of the URL, including + -- the final ':' + , hostname :: Text + -- ^ A string containing the domain of the URL. + , port :: Text + -- ^ A string containing the port number of the URL. + , pathname :: Text + -- ^ A string containing an initial '/' followed by the path of the + -- URL, not including the query string or fragment. + , search :: Text + -- ^ A string containing a '?' followed by the parameters or + -- "querystring" of the URL + , hash :: Text + -- ^ A string containing a '#' followed by the fragment identifier + -- of the URL. + } deriving stock (Show, Eq, Generic) + deriving anyclass (Binary, Value.FromJSValue, Value.ToJSValue) + +-- | Strict Lambda calculus with arbitrary side-effects, meant to be +-- used as commands executed in the JavaScript side, optimized for +-- non-blocking execution and minimizing round-trips. +data Expr + = Null + -- ^ Represents null or undefined values + | Boolean Bool + -- ^ JavaScript boolean value + | I64 Int64 + -- ^ JavaScript integer number + | F64 Double + -- ^ JavaScript floating point number + | String Text + -- ^ JavaScript string + | Array [Expr] + -- ^ JavaScript array + | Object [(Text, Expr)] + -- ^ JavaScript object + | Uint8Array ByteString + -- ^ Raw byte array + + | Dot Expr Text + -- ^ Read string property of an object. @(Dot (Id "document") + -- "body")@ is equivalent to @document.body@ JavaScript expression + | SetProp Expr Text Expr + -- ^ Assign a value to a string property of an object @(AssignProp + -- (Id "foo") "bar" (Str "baz"))@ is equivalent to @foo['bar'] = + -- baz;@ JavaScript expression. Evaluates into its right-hand side + -- expression. + | Ix Expr Int64 + -- ^ Read value from an integer index of an object. @(Ix (Id + -- "foo") 0)@ is equivalent to @foo[0]@ JavaScript expression + + | Add Expr Expr + -- ^ Binary addition @(Add 256 5647)@ is equivalent to @256 + 5647@ + | Subtract Expr Expr + -- ^ Binary substraction @(Subtract 256 5647)@ is equivalent to @256 - 5647@ + | Multiply Expr Expr + -- ^ Binary multiplication @(Multiply 256 5647)@ is equivalent to @256 * 5647@ + | Divide Expr Expr + -- ^ Binary division @(Divide 256 5647)@ is equivalent to @256 / 5647@ + + | Id Text -- ^ Lookup an identifier in current lexical scope + | Lam Expr + -- ^ Introduce a lambda function. Arguments can be accessed via 'Arg + -- 0 0' + | Arg Word8 Word8 + -- ^ Lookup an argument in the current argument scope. Separate + -- scope for argument from regular lexical scope required for + -- performance reasons. First field is "De Bruijn index" pointing to + -- nth-lambda counting outward from current expression. Second + -- number is positional argument for that lambda (each lambda + -- receives multiple arguments in a vector, see + -- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments) + -- De Bruijn indicies are notoriously hard to write manually, it's + -- one of the reasons this protocol is much less convenient than FFI + -- with JavaScript. One solution I found is that for complex code I + -- write regular JavaScript and run it with 'Eval'. + | Apply Expr [Expr] + -- ^ Apply a function to arbitrary length arguments. @Apply (Id + -- "encodeURIComponent") [Str "#"]@ going to evaluate to @String "%23"@ + | Call Expr Text [Expr] + -- ^ Call a method of an object @Call (Id "console") "log" [Str + -- "Hi!"]@ is equivalent to @console.log('Hi!')@ JavaScript code + + | AssignVar VarId Expr + -- ^ Assign a value to VarId allocated in haskell side. This way + -- haskell can save certain values between WASM reactor invocations + | FreeVar VarId + -- ^ Free a variable allocated with @AssignVar@ + | Var VarId + -- ^ Retrieve the value of the variable + | FreeScope ReactiveScope + -- ^ Free all the resources assosiated with the given ReactiveScope + + | HtmlBuilder Expr Expr + | InsertNode Expr Expr + | CreateElement Text + | CreateElementNS Text Text + | CreateTextNode Text + | ElementProp Expr Text Expr + | ElementAttr Expr Text Text + | InsertClassList Expr [Text] + | RemoveClassList Expr [Text] + | UpdateTextNode Expr Text + | InsertBoundary Expr + | ClearBoundary Expr Bool + + | AddEventListener ReactiveScope Expr Expr Expr + -- ^ @AddEventListener rscope target eventName listener@ is + -- equivalent to @target.addEventListener(eventName, listener)@ it + -- returns @FinalizerId@ integer identifier that can be used in + -- 'RemoveEventListener', but calling 'RemoveEventListener' is not + -- required, it'll be called authomatically when given ReactiveScope + -- will be freed with 'FreeScope' + | SetTimeout ReactiveScope Expr Int64 + -- ^ Returns FinalizerId + | ApplyFinalizer ReactiveScope Expr + -- ^ Actuate given finalizer before the ReactiveScope is freed + + | RevSeq [Expr] + -- ^ Sequence of the expressions in reverse order. It will be + -- evaluated from the end to the beggining of the list. Returns + -- whatever the last expression (from the head of the list) + -- evaluates into. Order is reversed to support fast insertion of + -- new instructions + | Eval Text + -- ^ Evaluate arbitrary JavaScript code @(Eval "setTimeout(() => + -- console.log('Hi!'), 1000)")@ will print a message with one second + -- delay + | TriggerCallback CallbackId Expr + -- ^ As a side-effect emits `TriggerCallbackMsg` message to Haskell + | UncaughtException Text + deriving stock (Generic, Show) + deriving anyclass (Binary) + +valueToExpr :: Value.Value -> Expr +valueToExpr = \case + Value.Null -> Null + Value.Bool a -> Boolean a + Value.I64 a -> I64 a + Value.F64 a -> F64 a + Value.String a -> String a + Value.Array xs -> Array $ fmap valueToExpr xs + Value.Object kv -> Object $ fmap (\(k, v) -> (k, valueToExpr v)) kv + Value.Uint8Array a -> Uint8Array a + +data VarId = VarId ReactiveScope Int64 + deriving stock (Generic, Show, Ord, Eq) + deriving anyclass (Binary) + +newtype CallbackId = CallbackId { unCallbackId :: Int64 } + deriving newtype (Show, Num, Binary, Ord, Eq) + +newtype ReactiveScope = ReactiveScope { unReactiveScope :: Int64 } + deriving newtype (Show, Num, Binary, Ord, Eq) + +newtype FinalizerId = FinalizerId { unFinalizerId :: Int64 } + deriving newtype (Show, Num, Binary, Ord, Eq) diff --git a/src/Clickable/Protocol/Value.hs b/src/Clickable/Protocol/Value.hs new file mode 100644 index 0000000..67fab21 --- /dev/null +++ b/src/Clickable/Protocol/Value.hs @@ -0,0 +1,158 @@ +module Clickable.Protocol.Value where + +import Data.Binary +import Data.ByteString +import Data.Kind +import Data.List qualified as List +import Data.Maybe +import Data.Text (Text) +import Data.Text qualified as Text +import GHC.Generics as G +import GHC.Int + +data Value + = Null + | Bool Bool + | I64 Int64 + | F64 Double + | String Text + | Array [Value] + | Object [(Text, Value)] + | Uint8Array ByteString + deriving stock (Generic, Show) + deriving anyclass (Binary) + +class ToJSValue a where + toJSValue :: a -> Value + default toJSValue :: (Generic a, GToJSValue (Rep a)) => a -> Value + toJSValue = gToJSValue . G.from + +instance ToJSValue Value where toJSValue = Prelude.id + +instance ToJSValue Bool where toJSValue = Bool + +instance ToJSValue Int64 where toJSValue = I64 + +instance ToJSValue Double where toJSValue = F64 + +instance ToJSValue Char where + toJSValue c = String $ Text.cons c Text.empty + +instance ToJSValue Text where toJSValue = String + +instance ToJSValue a => ToJSValue [a] where toJSValue = Array . fmap toJSValue + +instance ToJSValue a => ToJSValue (Maybe a) where toJSValue = maybe Null toJSValue + +instance (ToJSValue a, ToJSValue b) => ToJSValue (a, b) where + toJSValue (a, b) = toJSValue [toJSValue a, toJSValue b] + +instance (ToJSValue a, ToJSValue b, ToJSValue c) => ToJSValue (a, b, c) where + toJSValue (a, b, c) = toJSValue [toJSValue a, toJSValue b, toJSValue c] +-------------------------------------------------------------------------------- + +class FromJSValue a where + fromJSValue :: Value -> Maybe a + default fromJSValue :: (Generic a, GFromJSValue (Rep a)) => Value -> Maybe a + fromJSValue = fmap G.to . gFromJSValue + +instance FromJSValue Value where fromJSValue = pure + +instance FromJSValue Bool where + fromJSValue = \case Bool a -> Just a; _ -> Nothing + +instance FromJSValue Int64 where + fromJSValue = \case + I64 j -> Just j + F64 j -> Just $ floor j + _ -> Nothing + +instance FromJSValue Double where + fromJSValue = \case + I64 j -> Just $ fromIntegral j + F64 j -> Just j + _ -> Nothing + +instance FromJSValue Char where + fromJSValue = \case + String a | Just (c, _) <- Text.uncons a -> Just c + | otherwise -> Nothing + _ -> Nothing + +instance FromJSValue Text where + fromJSValue = \case String a -> Just a; _ -> Nothing + +instance FromJSValue a => FromJSValue [a] where + fromJSValue = \case + Array xs -> Just (mapMaybe fromJSValue xs) + _ -> Nothing + +instance FromJSValue a => FromJSValue (Maybe a) where + fromJSValue = fmap Just . fromJSValue @a + +instance (FromJSValue a, FromJSValue b) => FromJSValue (a, b) where + fromJSValue j = fromJSValue j >>= \case + Just (a:b:_) -> (,) <$> fromJSValue a <*> fromJSValue b + _ -> Nothing + +instance (FromJSValue a, FromJSValue b, FromJSValue c) => FromJSValue (a, b, c) where + fromJSValue j = fromJSValue j >>= \case + Just (a:b:c:_) -> (,,) <$> fromJSValue a <*> fromJSValue b <*> fromJSValue c + _ -> Nothing +-------------------------------------------------------------------------------- + +class GFromJSValue (f :: Type -> Type) where + gFromJSValue :: Value -> Maybe (f a) + +instance GFromJSValue f => GFromJSValue (M1 m c f) where + gFromJSValue = fmap M1 . gFromJSValue @f + +instance GFromJSObject (x :*: y) => GFromJSValue (x :*: y) where + gFromJSValue (Object kvs) = gFromJSObject kvs + gFromJSValue _ = Nothing + +instance {-# OVERLAPPING #-} FromJSValue a => GFromJSValue (S1 s (Rec0 a)) where + gFromJSValue = fmap (M1 . K1) . fromJSValue @a +-------------------------------------------------------------------------------- + +class GToJSValue (f :: Type -> Type) where + gToJSValue :: f x -> Value + +instance GToJSValue f => GToJSValue (M1 m c f) where + gToJSValue (M1 f) = gToJSValue f + +instance GToJSObject (x :*: y) => GToJSValue (x :*: y) where + gToJSValue (x :*: y) = Object $ gToJSObject (x :*: y) + +instance {-# OVERLAPPING #-} (ToJSValue a) => GToJSValue (S1 s (Rec0 a)) where + gToJSValue (M1 (K1 a)) = toJSValue a +-------------------------------------------------------------------------------- + +class GToJSObject (f :: Type -> Type) where + gToJSObject :: f x -> [(Text, Value)] + +instance (GToJSObject x, GToJSObject y) => GToJSObject (x :*: y) where + gToJSObject (x :*: y) = gToJSObject x <> gToJSObject y + +instance (GToJSObject f) => GToJSObject (M1 m c f) where + gToJSObject (M1 a) = gToJSObject a + +instance {-# OVERLAPPING #-} (ToJSValue a, Selector s) => GToJSObject (S1 s (Rec0 a)) where + gToJSObject (M1 (K1 a)) = [(key, toJSValue a)] + where + key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) +-------------------------------------------------------------------------------- + +class GFromJSObject (f :: Type -> Type) where + gFromJSObject :: [(Text, Value)] -> Maybe (f x) + +instance (GFromJSObject x, GFromJSObject y) => GFromJSObject (x :*: y) where + gFromJSObject kvs = liftA2 (:*:) (gFromJSObject kvs) (gFromJSObject kvs) + +instance (GFromJSObject f) => GFromJSObject (M1 m c f) where + gFromJSObject = fmap M1 . gFromJSObject + +instance {-# OVERLAPPING #-} (FromJSValue a, Selector s) => GFromJSObject (S1 s (Rec0 a)) where + gFromJSObject kvs = List.lookup key kvs >>= fmap (M1 . K1) . fromJSValue + where + key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index 91897a5..3c26d70 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -1,19 +1,15 @@ module Clickable.Types where -import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.IORef -import Data.List qualified as List -import Data.Text (Text) import Data.Tuple import Data.Map (Map) -import Data.Map qualified as Map import GHC.Generics -import GHC.Exts hiding (build) -import Unsafe.Coerce +import GHC.Exts -import Clickable.FFI +import Clickable.Protocol +import Clickable.Protocol.Value import Wasm.Compat.Prim data DynVar a where @@ -38,10 +34,10 @@ newtype ResourceScope = ResourceScope {unResourceScope :: Int} newtype SourceId = SourceId {unSourceId :: Int} deriving newtype (Eq, Ord, Show) -newtype HtmlM a = HtmlM { unHtmlM :: ReaderT JSVal ClickM a } +newtype HtmlM a = HtmlM {unHtmlM :: ReaderT JSVal ClickM a} deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader JSVal) -newtype ClickM a = ClickM {unClickM :: ReaderT InternalEnv IO a } +newtype ClickM a = ClickM {unClickM :: ReaderT InternalEnv IO a} deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) instance MonadState InternalState ClickM where @@ -50,12 +46,14 @@ instance MonadState InternalState ClickM where data InternalEnv = InternalEnv { scope :: ResourceScope , internal_state_ref :: IORef InternalState + , send_command :: HaskellMessage -> IO JavaScriptMessage } deriving (Generic) data InternalState = InternalState { subscriptions :: [(ResourceScope, SourceId, Any -> ClickM ())] , finalizers :: [(ResourceScope, FinalizerVal)] , transaction_queue :: Map SourceId (ClickM ()) + , evaluation_queue :: [Expr] , next_id :: Int } deriving (Generic) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..ef6b4b0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "sourceMap": false, + "target": "ES6", + "outDir": "./dist", + "rootDir": ".", + "strict": true, + "importHelpers": true, + "moduleResolution": "bundler", + "module": "ES6" + }, + "include": [ + "jsbits/**/*.ts" + ] +} diff --git a/webpack.config.js b/webpack.config.js index cde7f9c..44f5e9d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -10,4 +10,13 @@ module.exports = { extensions: ['.ts', '.js'], }, devtool: false, + module: { + rules: [ + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/, + }, + ], + }, }; From ccfae9536e352dc591d6e1c0d7d51847a7731fca Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 28 Mar 2024 02:32:47 +0400 Subject: [PATCH 16/64] WIP --- examples/charts/App.hs | 2 +- examples/charts/Charts.hs | 4 +- examples/charts/PairSelector.hs | 3 +- examples/charts/charts.hs | 2 +- jsbits/ffi.ts | 12 +- jsbits/jsffi.js | 14 +-- jsbits/protocol.ts | 10 ++ src/Clickable/Core.hs | 188 ++++++++++++++++++++++---------- src/Clickable/DOM.hs | 111 +++++++++---------- src/Clickable/FFI.hs | 17 ++- src/Clickable/Internal.hs | 92 +++++++++++++--- src/Clickable/Main.hs | 38 +++---- src/Clickable/Protocol.hs | 34 +++--- src/Clickable/Types.hs | 24 ++-- 14 files changed, 344 insertions(+), 207 deletions(-) diff --git a/examples/charts/App.hs b/examples/charts/App.hs index 568a3af..ec57a42 100644 --- a/examples/charts/App.hs +++ b/examples/charts/App.hs @@ -21,7 +21,7 @@ data AppTab new :: ClickM AppInstance new = do charts_instance <- Charts.new - state_var <- newVar $ ChartsTab charts_instance + state_var <- newDynVar $ ChartsTab charts_instance return AppInstance { state_var } diff --git a/examples/charts/Charts.hs b/examples/charts/Charts.hs index 224ea22..3739063 100644 --- a/examples/charts/Charts.hs +++ b/examples/charts/Charts.hs @@ -1,7 +1,5 @@ module Charts where -import Data.Proxy -import Control.Monad.State import Data.Text (Text) import Data.Text qualified as Text import GHC.Generics @@ -28,7 +26,7 @@ data ChartInstance = ChartInstance new :: ClickM ChartInstance new = do pair_selector_instance <- PairSelector.new - state_var <- newVar ChartState + state_var <- newDynVar ChartState { main_transform = Transform2D 0 0 0 0 , mouse_position = Point 0 0 , counter = 0 diff --git a/examples/charts/PairSelector.hs b/examples/charts/PairSelector.hs index d82fee0..35f49f7 100644 --- a/examples/charts/PairSelector.hs +++ b/examples/charts/PairSelector.hs @@ -1,6 +1,5 @@ module PairSelector where -import Data.Proxy import Data.Text (Text) import Data.Text qualified as Text import Data.Function hiding (on) @@ -21,7 +20,7 @@ data PairSelectorState = PairSelectorState new :: ClickM (DynVar PairSelectorState) new = - newVar PairSelectorState + newDynVar PairSelectorState { selected_pair = Nothing , options = [] } diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs index bdac142..f50244a 100644 --- a/examples/charts/charts.hs +++ b/examples/charts/charts.hs @@ -7,5 +7,5 @@ main = return () foreign export ccall wasm_main :: IO () wasm_main = do - _ <- attach $ liftClickM App.new >>= App.html + _ <- runApp $ lift App.new >>= App.html return () diff --git a/jsbits/ffi.ts b/jsbits/ffi.ts index 49bfb1a..b9e1db5 100644 --- a/jsbits/ffi.ts +++ b/jsbits/ffi.ts @@ -36,15 +36,19 @@ export function storeBuffer(exports: HaskellExports, u8array: Uint8Array): Haske return ptr; } -export function evalMessageFFI(exports: HaskellExports, ptr: HaskellPointer): HaskellPointer { +type SendMessageCallback = (jptr: HaskellPointer) => void; + +export function evalMessageFFI(javascriptMessageCallback: SendMessageCallback, exports: HaskellExports, ptr: HaskellPointer): HaskellPointer { const inbuf = loadBuffer(exports, ptr); const haskMsg = p.haskellMessage.decode(inbuf); - const jsCallback = (_jsMsg: JavaScriptMessage, _argScope: List) => { - // TODO + const jsCallback = (jsmsg: JavaScriptMessage, _argScope: List) => { + const outbuf = p.javascriptMessage.encode(jsmsg); + const ptr = storeBuffer(exports, outbuf); + javascriptMessageCallback(ptr); }; switch (haskMsg.tag) { case HaskellMessageTag.EvalExpr: { - const result = p.evalExpr(jsCallback, null, null, haskMsg.expr); + const result = p.evalExpr(jsCallback, [globalThis, null], null, haskMsg.expr); const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, 0: p.unknownToValue(result) }; const outbuf = p.javascriptMessage.encode(jsmsg); return storeBuffer(exports, outbuf); diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index f5b5c8d..489c32c 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -100,17 +100,9 @@ newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v), getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), -ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ($1()), -ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4) => {var j = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); if ($1 instanceof Comment) { return eval(j)($1.parentNode, $4); } else { return eval(j)($1, $4); }}, -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => {function isOpenBracket(node) {return node instanceof Comment && node.textContent == 'ContentBoundary {{'} function isCloseBracket(node) {return node instanceof Comment && node.textContent == '}}'} var iter = $1; var nestedCounter = 0; for (;;){ if (!iter.previousSibling || (nestedCounter == 0 && isOpenBracket(iter.previousSibling)) ) break; if (isCloseBracket(iter.previousSibling)) nestedCounter++; else if (isOpenBracket(iter.previousSibling)) nestedCounter--; iter.previousSibling.parentNode.removeChild(iter.previousSibling); }}, -ZC4ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => {var c1 = document.createComment('ContentBoundary {{'); var c2 = document.createComment('}}'); if ($1 instanceof Comment) { $1.parentNode.insertBefore(c1, $1); $1.parentNode.insertBefore(c2, $1); } else { $1.appendChild(c1); $1.appendChild(c2); } return c2;}, -ZC5ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, -ZC7ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC6ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), -ZC10ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: () => (document.body), -ZC13ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3,$4,$5) => {var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)); if ($1 instanceof Comment) { $1.parentNode[k] = v; } else { $1[k] = v; }}, -ZC14ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));}, -ZC15ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createElement(t); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, -ZC16ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2,$3) => {var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)); var n = document.createTextNode(c); if ($1 instanceof Comment) { $1.parentNode.insertBefore(n, $1); } else { $1.appendChild(n); } return n;}, +ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => (evalMessageFFI($1, __exports, $2)), +ZC9ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index db8437a..6e757cd 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -221,6 +221,13 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc if (!existingScope) finalizers.set(exp.reactiveScope, scopeFinalizers); return scopeFinalizers.push(() => domHelpers.removeEventListener(target, eventName, listener)); } + case ExprTag.ConnectResource: { + const finalizer = evalExpr(hscb, idenScope, argScope, exp.aquire) as Function; + const existingScope = finalizers.get(exp.reactiveScope); + const scopeFinalizers = existingScope ? existingScope : new IntMap(); + if (!existingScope) finalizers.set(exp.reactiveScope, scopeFinalizers); + return scopeFinalizers.push(finalizer); + } case ExprTag.SetTimeout: { const callback = evalExpr(hscb, idenScope, argScope, exp.callback) as Function; const existingScope = finalizers.get(exp.reactiveScope); @@ -405,6 +412,7 @@ export enum ExprTag { ClearBoundary, AddEventListener, + ConnectResource, SetTimeout, ApplyFinalizer, @@ -458,6 +466,7 @@ export type Expr = | { tag: ExprTag.ClearBoundary, boundary: Expr, detach: number } | { tag: ExprTag.AddEventListener, reactiveScope: number, target: Expr, eventName: Expr, listener: Expr } + | { tag: ExprTag.ConnectResource, reactiveScope: number, aquire: Expr } | { tag: ExprTag.SetTimeout, reactiveScope: number, callback: Expr, timeout: number } | { tag: ExprTag.ApplyFinalizer, reactiveScope: number, finalizerId: Expr } @@ -510,6 +519,7 @@ export const expr = b.recursive(self => b.discriminate({ [ExprTag.ClearBoundary]: b.record({ boundary: self, detach: b.int8 }), [ExprTag.AddEventListener]: b.record({ reactiveScope: b.int64, target: self, eventName: self, listener: self }), + [ExprTag.ConnectResource]: b.record({ reactiveScope: b.int64, aquire: self }), [ExprTag.SetTimeout]: b.record({ reactiveScope: b.int64, callback: self, timeout: b.int64 }), [ExprTag.ApplyFinalizer]: b.record({ reactiveScope: b.int64, finalizerId: self }), diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index ae99227..8d160b2 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -4,27 +4,21 @@ import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.IORef +import Data.Function ((&)) import Data.Map qualified as Map +import Data.List qualified as List import Data.Text (Text) -import Clickable.FFI import Clickable.Internal (reactive, reactive_) import Clickable.Internal qualified as Internal import Clickable.Types import Clickable.Protocol -import Clickable.Protocol.Value -import Wasm.Compat.Prim +import Clickable.Protocol.Value (Value) +import Clickable.Protocol.Value qualified as Value -launchHtmlM :: JSVal -> InternalEnv -> HtmlM a -> IO a -launchHtmlM root env = - flip runReaderT env . unClickM . trampoline . flip runReaderT root . unHtmlM - launchClickM :: InternalEnv -> ClickM a -> IO a -launchClickM env = flip runReaderT env . unClickM . trampoline - -liftClickM :: ClickM a -> HtmlM a -liftClickM = HtmlM . lift +launchClickM env = flip runReaderT env . unClickT . trampoline --------------------------------------- -- OPERATIONS OVER DYNAMIC VARIABLES -- @@ -33,8 +27,8 @@ liftClickM = HtmlM . lift mapVar :: DynVar a -> (a -> b) -> DynVal b mapVar var = MapVal (FromVar var) -newVar :: a -> ClickM (DynVar a) -newVar a = do +newDynVar :: a -> ClickM (DynVar a) +newDynVar a = do ref <- liftIO $ newIORef a state \s -> (DynVar (SourceId s.next_id) ref, s {next_id = s.next_id + 1}) @@ -69,9 +63,12 @@ enqueueExpr e = modify \s -> s {evaluation_queue = e : s.evaluation_queue} evalExpr :: Expr -> ClickM Value evalExpr e = do - send_command <- asks (.send_command) + send_message <- asks (.send_message) queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - liftIO $ send_command $ RevSeq $ e : queue + result <- liftIO $ send_message $ EvalExpr $ RevSeq $ e : queue + case result of + Return v -> return v + _ -> return Value.Null ------------------------- -- RESOURCE MANAGEMENT -- @@ -83,13 +80,16 @@ newScope = reactive Internal.newScope freeScope :: Bool -> ResourceScope -> ClickM () freeScope unlink s = f where f = reactive (const (Internal.freeScope unlink s)) >>= g - g [] = return () + g [] = enqueueExpr $ FreeScope s g ((_, ScopeFinalizer s'):xs) = freeScope True s' >> g xs g ((_, CustomFinalizer x):xs) = x >> g xs installFinalizer :: ClickM () -> ClickM () installFinalizer k = reactive_ $ Internal.installFinalizer k +newVar :: ClickM VarId +newVar = reactive Internal.newVar + -- | Loop until transaction_queue is empty. -- -- This makes possible to implement @Applicative DynVal@ without @@ -120,54 +120,60 @@ trampoline act = loop0 act where ------------------ el :: Text -> HtmlM a -> HtmlM a -el t ch = do - r <- ask - el <- liftIO $ insertElement r t - local (const el) ch +el t ch = lift $ htmlBuilder (CreateElement t) $ evalStateT ch.unHtmlT Nothing property :: Text -> Text -> HtmlM () -property k v = do - root <- ask - liftIO $ setProperty root k v +property k v = lift $ modify f where + f s = s {evaluation_queue = expr : s.evaluation_queue } + expr = ElementProp (Arg 0 0) k (String v) boolProperty :: Text -> Bool -> HtmlM () -boolProperty k v = do - root <- ask - liftIO $ setBoolProperty root k v +boolProperty k v = lift $ modify f where + f s = s {evaluation_queue = expr : s.evaluation_queue } + expr = ElementProp (Arg 0 0) k (Boolean v) attribute :: Text -> Text -> HtmlM () -attribute k v = do - root <- ask - liftIO $ setAttribute root k v +attribute k v = lift $ modify f where + f s = s {evaluation_queue = expr : s.evaluation_queue } + expr = ElementAttr (Arg 0 0) k v text :: Text -> HtmlM () -text t = do - r <- ask - void $ liftIO $ insertText r t +text t = lift $ modify f where + f s = s {evaluation_queue = expr : s.evaluation_queue } + expr = InsertNode (Arg 0 0) $ CreateTextNode t dynText :: DynVal Text -> HtmlM () dynText val = do - r <- ask - t <- liftClickM $ readVal val - textNode <- liftIO $ insertText r t - liftClickM $ subscribe val $ \new -> - liftIO $ updateTextContent textNode new + scope <- lift $ asks (.scope) + t <- lift $ readVal val + v <- lift $ newVar + lift $ modify $ f v t + lift $ subscribe val $ enqueueIfAlive scope . UpdateTextNode (Var v) + where + f v t s = s {evaluation_queue = expr v t : s.evaluation_queue } + expr v t = InsertNode (Arg 0 0) $ AssignVar v $ CreateTextNode t dynProp :: Text -> DynVal Text -> HtmlM () dynProp k val = do - root <- ask - v <- liftClickM $ readVal val - liftIO $ setProperty root k v - liftClickM $ subscribe val $ \new -> - liftIO $ setProperty root k new + scope <- lift $ asks (.scope) + t <- lift $ readVal val + v <- saveCurrentNode + lift $ modify $ f t + lift $ subscribe val $ enqueueIfAlive scope . ElementProp (Var v) k . String + where + f v s = s {evaluation_queue = expr v : s.evaluation_queue } + expr v = ElementProp (Arg 0 0) k (String v) dynBoolProp :: Text -> DynVal Bool -> HtmlM () dynBoolProp k val = do - root <- ask - v <- liftClickM $ readVal val - liftIO $ setBoolProperty root k v - liftClickM $ subscribe val $ \new -> - liftIO $ setBoolProperty root k new + scope <- lift $ asks (.scope) + t <- lift $ readVal val + v <- saveCurrentNode + lift $ modify $ f t + lift $ subscribe val $ enqueueIfAlive scope . ElementProp (Var v) k . Boolean + where + f v s = s {evaluation_queue = expr v : s.evaluation_queue } + expr v = ElementProp (Arg 0 0) k (Boolean v) blank :: Applicative m => m () blank = pure () @@ -178,18 +184,88 @@ blank = pure () dyn :: DynVal (HtmlM ()) -> HtmlM () dyn val = do - root <- ask - scope <- liftClickM newScope - closeBracket <- liftIO $ js_insertBrackets root - initialVal <- liftClickM $ readVal val + boundary <- lift insertBoundary + scope <- lift newScope + initialVal <- lift $ readVal val let update html = do - liftIO $ js_clearBrackets closeBracket + lift $ clearBoundary boundary html - exec = local (\s -> s {scope}) . - flip runReaderT closeBracket . unHtmlM - liftClickM $ exec $ update initialVal - liftClickM $ subscribe val \newVal -> do + exec h = evalStateT h.unHtmlT Nothing + & htmlBuilder1 (Var boundary) + & local (\s -> s {scope}) + lift $ exec $ update initialVal + lift $ subscribe val $ \newVal -> do freeScope False scope exec $ update newVal + +htmlBuilder :: Expr -> ClickM a -> ClickM a +htmlBuilder builder content = do + prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) + result <- content + let mkExpr revSeq = InsertNode (Arg 0 0) (HtmlBuilder builder (Lam (RevSeq revSeq))) + modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} + return result + +htmlBuilder1 :: Expr -> ClickM a -> ClickM a +htmlBuilder1 builder content = do + prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) + result <- content + let mkExpr revSeq = HtmlBuilder builder (Lam (RevSeq revSeq)) + modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} + return result + +enqueueIfAlive :: ResourceScope -> Expr -> ClickM () +enqueueIfAlive scope e = modify \s -> + let + evaluation_queue = + -- if Map.member scope s.finalizers + if True + then e : s.evaluation_queue else s.evaluation_queue + in + s {evaluation_queue} + +saveCurrentNode :: HtmlM VarId +saveCurrentNode = do + alreadySaved <- HtmlT get + case alreadySaved of + Nothing -> do + varId <- lift newVar + HtmlT $ put $ Just varId + lift $ enqueueExpr $ AssignVar varId (Arg 0 0) + return varId + Just saved -> return saved + +insertBoundary :: ClickM VarId +insertBoundary = do + boundary <- newVar + modify \s -> s {evaluation_queue = AssignVar boundary (InsertBoundary (Arg 0 0)) : s.evaluation_queue} + return boundary + +clearBoundary :: VarId -> ClickM () +clearBoundary boundary = enqueueExpr (ClearBoundary (Var boundary) False) + +destroyBoundary :: VarId -> ClickM () +destroyBoundary boundary = enqueueExpr (ClearBoundary (Var boundary) True) + +attachHtml :: Expr -> HtmlM a -> ClickM a +attachHtml builder contents = do + saveQueue <- state \s -> + (s.evaluation_queue, s {evaluation_queue = []}) + result <- evalStateT contents.unHtmlT Nothing + modify \s -> + let + attachExpr = HtmlBuilder builder (Lam (RevSeq s.evaluation_queue)) + in + s {evaluation_queue = attachExpr : saveQueue} + return result + +attachToBody :: HtmlM a -> ClickM a +attachToBody = attachHtml (Id "document" `Dot` "body") + +syncPoint :: ClickM () +syncPoint = do + send_message <- asks (.send_message) + queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) + liftIO $ send_message $ EvalExpr $ RevSeq queue return () diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index 57201fa..40b4f34 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -2,14 +2,16 @@ module Clickable.DOM where import Control.Monad.Reader import Data.Text (Text) +import Data.Foldable import Data.Kind +import Data.Int import GHC.Generics +import Unsafe.Coerce -import Clickable.FFI qualified as FFI -import Clickable.Core import Clickable.Types -import Wasm.Compat.Prim -import Wasm.Compat.Marshal +import Clickable.Protocol +import Clickable.Protocol.Value (Value, FromJSValue(..)) +import Clickable.Internal data EventListenerOptions = EventListenerOptions @@ -24,24 +26,26 @@ defaultEventListenerOptions = EventListenerOptions } addEventListener :: ConnectResourceArgs callback -> callback -> HtmlM () -addEventListener args k = do - rootElement <- ask - liftClickM $ connectResource rootElement args k +addEventListener args k = lift $ connectResource args k data ConnectResourceArgs callback = ConnectResourceArgs - { js_wrapper :: UnsafeJavaScript - , mk_callback :: callback -> JSVal -> ClickM () + { aquire_fn :: ResourceScope -> SourceId -> Expr + , mk_callback :: callback -> Value -> ClickM () } -connectResource :: JSVal -> ConnectResourceArgs callback -> callback -> ClickM () -connectResource target args k = do - e :: InternalEnv <- ask - let hsCallback' = (`runReaderT` e) . unClickM . trampoline . args.mk_callback k - hsCallback'' <- liftIO $ FFI.js_dynExport hsCallback' - cancel <- liftIO $ FFI.aquireResource target args.js_wrapper.unUnsafeJavaScript hsCallback'' - installFinalizer do - liftIO $ FFI.apply0 cancel - liftIO $ freeJSVal hsCallback'' +connectResource :: ConnectResourceArgs callback -> callback -> ClickM () +connectResource args k = reactive_ \scope s -> + let + callback :: Value -> ClickM () + callback = local (\e -> e {scope}) . args.mk_callback k + sourceId = SourceId s.next_id + newSub = (scope, sourceId, callback . unsafeCoerce) + connectExpr = ConnectResource scope $ args.aquire_fn scope sourceId + in + s { evaluation_queue = connectExpr : s.evaluation_queue + , subscriptions = newSub : s.subscriptions + , next_id = s.next_id + 1 + } on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HtmlM () on k = addEventListener (addEventListenerArgs @eventName) k @@ -75,11 +79,11 @@ instance IsEventName "input" where addEventListenerArgs = inputConnectArgs "input" instance IsEventName "keydown" where - type EventListenerCb "keydown" = Int -> ClickM () + type EventListenerCb "keydown" = Int64 -> ClickM () addEventListenerArgs = keyboardConnectArgs "keydown" instance IsEventName "keyup" where - type EventListenerCb "keyup" = Int -> ClickM () + type EventListenerCb "keyup" = Int64 -> ClickM () addEventListenerArgs = keyboardConnectArgs "keyup" instance IsEventName "focus" where @@ -109,47 +113,50 @@ instance IsEventName "select/change" where -- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event pointerConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) pointerConnectArgs eventName = ConnectResourceArgs - { js_wrapper = normalEventWrapper eventName defaultEventListenerOptions + { aquire_fn = \scope sourceId -> + Eval (normalEventWrapper eventName defaultEventListenerOptions) + `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k _ -> k } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event submitConnectArgs :: ConnectResourceArgs (ClickM ()) submitConnectArgs = ConnectResourceArgs - { js_wrapper = normalEventWrapper "submit" EventListenerOptions + { aquire_fn = \scope sourceId -> + Eval (normalEventWrapper "submit" EventListenerOptions { prevent_default = True , stop_propagation = True - } + }) `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k _ -> k } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event inputConnectArgs :: Text -> ConnectResourceArgs (Text -> ClickM ()) inputConnectArgs eventName = ConnectResourceArgs - { js_wrapper = - "(function(target, haskellCb){\n\ + { aquire_fn = \scope sourceId -> Eval + ("(function(target, haskellCb){\n\ \ function listener(target){\n\ \ haskellCb(event.target.value);\n\ \ }\n\ \ window.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => window.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})" - , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + \})") `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + , mk_callback = \k event -> forM_ (fromJSValue event) k } -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardConnectArgs :: Text -> ConnectResourceArgs (Int -> ClickM ()) +keyboardConnectArgs :: Text -> ConnectResourceArgs (Int64 -> ClickM ()) keyboardConnectArgs eventName = ConnectResourceArgs - { js_wrapper = + { aquire_fn = \scope sourceId -> Eval ( "(function(target, haskellCb){\n\ \ function listener(target){\n\ \ haskellCb(event.target.value);\n\ \ }\n\ \ window.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => window.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})" - , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + \})") `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + , mk_callback = \k event -> forM_ (fromJSValue event) k } -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event @@ -158,36 +165,38 @@ keyboardConnectArgs eventName = ConnectResourceArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event focusConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) focusConnectArgs eventName = ConnectResourceArgs - { js_wrapper = normalEventWrapper eventName defaultEventListenerOptions + { aquire_fn = \scope sourceId -> + Eval (normalEventWrapper eventName defaultEventListenerOptions) + `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k _ -> k } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event checkboxChangeConnectArgs :: ConnectResourceArgs (Bool -> ClickM ()) checkboxChangeConnectArgs = ConnectResourceArgs - { js_wrapper = + { aquire_fn = \scope sourceId -> Eval "(function(target, haskellCb){\n\ \ function listener(target){\n\ \ haskellCb(event.target.checked);\n\ \ }\n\ \ window.addEventListener('change', listener);\n\ \ return () => window.removeEventListener('change', listener);\n\ - \})" - , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + , mk_callback = \k event -> forM_ (fromJSValue event) k } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event selectChangeConnectArgs :: ConnectResourceArgs (Text -> ClickM ()) selectChangeConnectArgs = ConnectResourceArgs - { js_wrapper = + { aquire_fn = \scope sourceId -> Eval "(function(target, haskellCb){\n\ \ function listener(target){\n\ \ haskellCb(event.target.value);\n\ \ }\n\ \ window.addEventListener('change', listener);\n\ \ return () => window.removeEventListener('change', listener);\n\ - \})" - , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + , mk_callback = \k event -> forM_ (fromJSValue event) k } normalEventWrapper :: Text -> EventListenerOptions -> UnsafeJavaScript @@ -205,36 +214,16 @@ normalEventWrapper eventName opt = preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" -data Location = Location - { protocol :: Text - -- ^ A string containing the protocol scheme of the URL, including - -- the final ':' - , hostname :: Text - -- ^ A string containing the domain of the URL. - , port :: Text - -- ^ A string containing the port number of the URL. - , pathname :: Text - -- ^ A string containing an initial '/' followed by the path of the - -- URL, not including the query string or fragment. - , search :: Text - -- ^ A string containing a '?' followed by the parameters or - -- "querystring" of the URL - , hash :: Text - -- ^ A string containing a '#' followed by the fragment identifier - -- of the URL. - } deriving stock (Show, Eq, Generic) - deriving anyclass (FromJSVal, ToJSVal) - -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event popstateConnectArgs :: ConnectResourceArgs (Location -> ClickM ()) popstateConnectArgs = ConnectResourceArgs - { js_wrapper = + { aquire_fn = \scope sourceId -> Eval "(function(target, haskellCb){\n\ \ function listener(){\n\ \ haskellCb(location);\n\ \ }\n\ \ target.addEventListener('popstate', listener);\n\ \ return () => target.removeEventListener('popstate', listener);\n\ - \})" - , mk_callback = \k event -> liftIO (fromJSVal event) >>= mapM_ k + \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + , mk_callback = \k event -> forM_ (fromJSValue event) k } diff --git a/src/Clickable/FFI.hs b/src/Clickable/FFI.hs index 1bb8278..cd8879b 100644 --- a/src/Clickable/FFI.hs +++ b/src/Clickable/FFI.hs @@ -123,9 +123,15 @@ js_aquireResource = undefined js_apply0 :: JSVal -> IO () js_apply0 = undefined -js_evalMessageFFI :: Ptr Word8 -> IO (Ptr Word8) +js_evalMessageFFI :: JSVal -> Ptr Word8 -> IO (Ptr Word8) js_evalMessageFFI = undefined +js_exportCallback :: (Ptr Word8 {- JavaScriptMessage -} -> IO ()) -> IO JSVal +js_exportCallback = undefined + +js_installCallback :: JSVal -> IO () +js_installCallback = undefined + #else foreign import javascript unsafe "var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ @@ -251,6 +257,11 @@ foreign import javascript unsafe foreign import javascript unsafe "$1()" js_apply0 :: JSVal -> IO () foreign import javascript unsafe - "evalMessageFFI(__exports, $1)" - js_evalMessageFFI :: Ptr Word8 {- HaskellMessage -} -> IO (Ptr Word8 {- JavaScriptMessage -}) + "evalMessageFFI($1, __exports, $2)" + js_evalMessageFFI :: JSVal -> Ptr Word8 {- HaskellMessage -} -> IO (Ptr Word8 {- JavaScriptMessage -}) +foreign import javascript unsafe + "window._javascriptMessageCallback = $1;" + js_installCallback :: JSVal -> IO () +foreign import javascript "wrapper" + js_exportCallback :: (Ptr Word8 {- JavaScriptMessage -} -> IO ()) -> IO JSVal #endif diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 304dbb7..0b5c00a 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -1,36 +1,38 @@ module Clickable.Internal where -import Clickable.Types -import Clickable.Protocol -import Clickable.Protocol.Value qualified as Value import Clickable.FFI qualified as FFI +import Clickable.Protocol +import Clickable.Types import Control.Monad.Reader import Control.Monad.State -import Data.IORef -import Data.List qualified as List -import Data.Map qualified as Map -import Unsafe.Coerce import Data.Binary qualified as Binary -import Data.ByteString.Lazy qualified as BSL +import Data.Foldable import Data.ByteString as BS import Data.ByteString.Lazy qualified as BSL import Data.ByteString.Unsafe qualified as BSU +import Data.IORef +import Data.List qualified as List +import Data.Map qualified as Map import Data.Word import Foreign.Marshal.Alloc qualified as Alloc import Foreign.Marshal.Utils import Foreign.Ptr import Foreign.Storable -import System.IO.Unsafe +import Unsafe.Coerce +import Wasm.Compat.Prim + emptyInternalState :: InternalState emptyInternalState = InternalState [] [] Map.empty [] 0 newInternalEnv :: IO InternalEnv -newInternalEnv = do +newInternalEnv = mdo let scope = ResourceScope emptyInternalState.next_id internal_state_ref <- newIORef emptyInternalState {next_id = emptyInternalState.next_id + 1} - return InternalEnv {internal_state_ref, scope, send_command = sendMessage} + receiveCb <- FFI.js_exportCallback $ receiveMessage env + let env = InternalEnv {internal_state_ref, scope, send_message = sendMessage receiveCb} + return env unsafeTrigger :: SourceId -> a -> InternalState -> InternalState unsafeTrigger varId vals = go0 where @@ -45,9 +47,13 @@ newScope p s = let scopeId = ResourceScope s.next_id finalizers = (p, ScopeFinalizer scopeId) : s.finalizers - next_id = s.next_id + 1 + s' = s {finalizers, next_id = s.next_id + 1} in - (s {finalizers, next_id}, scopeId) + (s', scopeId) + +newVar :: ResourceScope -> InternalState -> (InternalState, VarId) +newVar e s = + (s {next_id = s.next_id + 1}, VarId e s.next_id) freeScope :: Bool -> @@ -103,15 +109,15 @@ defer :: SourceId -> ClickM () -> InternalState -> InternalState defer k act s = s { transaction_queue = Map.insert k act s.transaction_queue } reactive :: (ResourceScope -> InternalState -> (InternalState, a)) -> ClickM a -reactive f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ f e.scope +reactive f = ClickT $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ f e.scope reactive_ :: (ResourceScope -> InternalState -> InternalState) -> ClickM () reactive_ f = reactive \scope s -> (f scope s, ()) -sendMessage :: HaskellMessage -> IO JavaScriptMessage -sendMessage hmsg = do +sendMessage :: JSVal -> HaskellMessage -> IO JavaScriptMessage +sendMessage receiveCb hmsg = do hptr <- storeByteString $ BSL.toStrict $ Binary.encode hmsg - jptr <- FFI.js_evalMessageFFI hptr + jptr <- FFI.js_evalMessageFFI receiveCb hptr Alloc.free hptr Binary.decode . BSL.fromStrict <$> loadByteString jptr where @@ -129,3 +135,55 @@ sendMessage hmsg = do len <- peek @Word64 (castPtr ptr) let contentPtr = ptr `plusPtr` 8 BSU.unsafePackCStringFinalizer contentPtr (fromIntegral len) (Alloc.free ptr) + +receiveMessage :: InternalEnv -> Ptr Word8 -> IO () +receiveMessage e jptr = do + jbytes <- loadByteString jptr + let jmsg = Binary.decode $ BSL.fromStrict jbytes + case jmsg of + Start _startFlags -> return () + Return _value -> return () + TriggerCallbackMsg arg sourceId -> + launchClickM e $ modify (unsafeTrigger sourceId arg) + BeforeUnload -> return () + where + loadByteString :: Ptr a -> IO ByteString + loadByteString ptr = do + len <- peek @Word64 (castPtr ptr) + let contentPtr = ptr `plusPtr` 8 + BSU.unsafePackCStringFinalizer contentPtr (fromIntegral len) (Alloc.free ptr) + +launchClickM :: InternalEnv -> ClickM a -> IO a +launchClickM env = flip runReaderT env . unClickT . (<* syncPoint) . trampoline + +-- | Loop until transaction_queue is empty. +-- +-- This makes possible to implement @Applicative DynVal@ without +-- redundantly firing callback for the final result. TODO: Is this +-- even worth-while to have? What if just let multiple DOM changes +-- when it depends on multiple sources? +trampoline :: ClickM a -> ClickM a +trampoline act = loop0 act where + loop0 :: ClickM a -> ClickM a + loop0 before = do + r <- before + mcont <- popQueue + forM_ mcont loop1 + return r + loop1 :: ClickM () -> ClickM () + loop1 before = do + before + mcont <- popQueue + forM_ mcont loop1 + popQueue :: ClickM (Maybe (ClickM ())) + popQueue = state \s -> + case Map.minViewWithKey s.transaction_queue of + Nothing -> (Nothing, s) + Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) + +syncPoint :: ClickM () +syncPoint = do + send_message <- asks (.send_message) + queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) + liftIO $ send_message $ EvalExpr $ RevSeq queue + return () diff --git a/src/Clickable/Main.hs b/src/Clickable/Main.hs index 4fc2816..0207976 100644 --- a/src/Clickable/Main.hs +++ b/src/Clickable/Main.hs @@ -1,16 +1,15 @@ module Clickable.Main where import GHC.Generics -import Clickable.FFI import Clickable.Core import Clickable.Types import Clickable.Internal (newInternalEnv) import Wasm.Compat.Prim -data AttachOptions = AttachOptions - { internal_env :: InternalEnv - , dom_builder :: JSVal - } deriving Generic +-- data AttachOptions = AttachOptions +-- { internal_env :: InternalEnv +-- , dom_builder :: JSVal +-- } deriving Generic -- | Needed to manually finalize and detach the application data RunningApp = RunningApp @@ -18,20 +17,19 @@ data RunningApp = RunningApp , dom_bracket :: JSVal } deriving Generic -attachWithOptions :: AttachOptions -> HtmlM a -> IO (a, RunningApp) -attachWithOptions opt app = do - domBracket <- js_insertBrackets opt.dom_builder - result <- launchHtmlM domBracket opt.internal_env app - let runApp = RunningApp opt.internal_env domBracket - return (result, runApp) +-- attachWithOptions :: AttachOptions -> HtmlM a -> IO (a, RunningApp) +-- attachWithOptions opt app = do +-- domBracket <- js_insertBrackets opt.dom_builder +-- result <- launchHtmlM domBracket opt.internal_env app +-- let runApp = RunningApp opt.internal_env domBracket +-- return (result, runApp) -attach :: HtmlM a -> IO (a, RunningApp) -attach html = do - body <- documentBody - internalEnv <- newInternalEnv - attachWithOptions (AttachOptions internalEnv body) html +runApp :: HtmlM a -> IO a +runApp app = do + env <- newInternalEnv + launchClickM env $ attachToBody app <* syncPoint -detach :: RunningApp -> IO () -detach app = do - launchClickM app.internal_env $ freeScope True app.internal_env.scope - js_removeBrackets app.dom_bracket +-- detach :: RunningApp -> IO () +-- detach app = do +-- launchClickM app.internal_env $ freeScope True app.internal_env.scope +-- js_removeBrackets app.dom_bracket diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index 13fde8d..1d25d42 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -4,6 +4,7 @@ import Data.Binary (Binary) import Data.ByteString (ByteString) import Data.Int import Data.Text (Text) +import Data.String import Data.Word import GHC.Generics @@ -23,7 +24,7 @@ data HaskellMessage data JavaScriptMessage = Start StartFlags | Return Value.Value - | TriggerCallbackMsg Value.Value CallbackId + | TriggerCallbackMsg Value.Value SourceId | BeforeUnload -- ^ Fired from addEventListener("beforeunload") listener. Won't -- work under the DevServer! @@ -129,8 +130,8 @@ data Expr -- ^ Free a variable allocated with @AssignVar@ | Var VarId -- ^ Retrieve the value of the variable - | FreeScope ReactiveScope - -- ^ Free all the resources assosiated with the given ReactiveScope + | FreeScope ResourceScope + -- ^ Free all the resources assosiated with the given ResourceScope | HtmlBuilder Expr Expr | InsertNode Expr Expr @@ -145,17 +146,19 @@ data Expr | InsertBoundary Expr | ClearBoundary Expr Bool - | AddEventListener ReactiveScope Expr Expr Expr + | AddEventListener ResourceScope Expr Expr Expr -- ^ @AddEventListener rscope target eventName listener@ is -- equivalent to @target.addEventListener(eventName, listener)@ it -- returns @FinalizerId@ integer identifier that can be used in -- 'RemoveEventListener', but calling 'RemoveEventListener' is not - -- required, it'll be called authomatically when given ReactiveScope + -- required, it'll be called authomatically when given ResourceScope -- will be freed with 'FreeScope' - | SetTimeout ReactiveScope Expr Int64 + | ConnectResource ResourceScope Expr -- ^ Returns FinalizerId - | ApplyFinalizer ReactiveScope Expr - -- ^ Actuate given finalizer before the ReactiveScope is freed + | SetTimeout ResourceScope Expr Int64 + -- ^ Returns FinalizerId + | ApplyFinalizer ResourceScope Expr + -- ^ Actuate given finalizer before the ResourceScope is freed | RevSeq [Expr] -- ^ Sequence of the expressions in reverse order. It will be @@ -163,11 +166,11 @@ data Expr -- whatever the last expression (from the head of the list) -- evaluates into. Order is reversed to support fast insertion of -- new instructions - | Eval Text + | Eval UnsafeJavaScript -- ^ Evaluate arbitrary JavaScript code @(Eval "setTimeout(() => -- console.log('Hi!'), 1000)")@ will print a message with one second -- delay - | TriggerCallback CallbackId Expr + | TriggerCallback SourceId Expr -- ^ As a side-effect emits `TriggerCallbackMsg` message to Haskell | UncaughtException Text deriving stock (Generic, Show) @@ -184,15 +187,18 @@ valueToExpr = \case Value.Object kv -> Object $ fmap (\(k, v) -> (k, valueToExpr v)) kv Value.Uint8Array a -> Uint8Array a -data VarId = VarId ReactiveScope Int64 +data VarId = VarId ResourceScope Int64 deriving stock (Generic, Show, Ord, Eq) deriving anyclass (Binary) -newtype CallbackId = CallbackId { unCallbackId :: Int64 } +newtype FinalizerId = FinalizerId { unFinalizerId :: Int64 } deriving newtype (Show, Num, Binary, Ord, Eq) -newtype ReactiveScope = ReactiveScope { unReactiveScope :: Int64 } +newtype ResourceScope = ResourceScope {unResourceScope :: Int64} deriving newtype (Show, Num, Binary, Ord, Eq) -newtype FinalizerId = FinalizerId { unFinalizerId :: Int64 } +newtype SourceId = SourceId {unSourceId :: Int64} deriving newtype (Show, Num, Binary, Ord, Eq) + +newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} + deriving newtype (IsString, Show, Semigroup, Monoid, Binary) diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index 3c26d70..513a379 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -3,14 +3,13 @@ module Clickable.Types where import Control.Monad.Reader import Control.Monad.State import Data.IORef +import Data.Int import Data.Tuple import Data.Map (Map) import GHC.Generics import GHC.Exts import Clickable.Protocol -import Clickable.Protocol.Value -import Wasm.Compat.Prim data DynVar a where DynVar :: SourceId -> IORef a -> DynVar a @@ -28,25 +27,22 @@ instance Applicative DynVal where pure = ConstVal; (<*>) = SplatVal fromVar :: DynVar a -> DynVal a fromVar = FromVar -newtype ResourceScope = ResourceScope {unResourceScope :: Int} - deriving newtype (Eq, Ord, Show) +newtype HtmlT m a = HtmlT {unHtmlT :: StateT (Maybe VarId) m a} + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadTrans) -newtype SourceId = SourceId {unSourceId :: Int} - deriving newtype (Eq, Ord, Show) +newtype ClickT m a = ClickT {unClickT :: ReaderT InternalEnv m a} + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv, MonadTrans) -newtype HtmlM a = HtmlM {unHtmlM :: ReaderT JSVal ClickM a} - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader JSVal) - -newtype ClickM a = ClickM {unClickM :: ReaderT InternalEnv IO a} - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) +type HtmlM = HtmlT ClickM +type ClickM = ClickT IO instance MonadState InternalState ClickM where - state f = ClickM $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ swap . f + state f = ClickT $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ swap . f data InternalEnv = InternalEnv { scope :: ResourceScope , internal_state_ref :: IORef InternalState - , send_command :: HaskellMessage -> IO JavaScriptMessage + , send_message :: HaskellMessage -> IO JavaScriptMessage } deriving (Generic) data InternalState = InternalState @@ -54,7 +50,7 @@ data InternalState = InternalState , finalizers :: [(ResourceScope, FinalizerVal)] , transaction_queue :: Map SourceId (ClickM ()) , evaluation_queue :: [Expr] - , next_id :: Int + , next_id :: Int64 } deriving (Generic) data FinalizerVal From 5c23cf84f97dc6026746375f918e17a41ad2cf20 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 28 Mar 2024 23:07:04 +0400 Subject: [PATCH 17/64] Save progress --- examples/charts/App.hs | 13 ++++++ jsbits/protocol.ts | 9 ---- src/Clickable/Core.hs | 91 +++++++++++++-------------------------- src/Clickable/Internal.hs | 37 ++++++++-------- src/Clickable/Protocol.hs | 1 - 5 files changed, 63 insertions(+), 88 deletions(-) diff --git a/examples/charts/App.hs b/examples/charts/App.hs index ec57a42..5eefba5 100644 --- a/examples/charts/App.hs +++ b/examples/charts/App.hs @@ -2,6 +2,7 @@ module App where import Charts qualified as Charts import Control.Monad.State +import Control.Concurrent import Data.Proxy import Data.Text (Text) import Data.Text qualified as Text @@ -38,6 +39,18 @@ html self = do button_ do text "Open Help" on @"click" $ modifyVar self.state_var $ const HelpTab + button_ do + text "Open Modal" + on @"click" do + mvar <- liftIO newEmptyMVar + attachToBody do + p_ $ text "Content of the modal" + button_ do + text "Close" + on @"click" $ liftIO $ putMVar mvar "dljfhdlsfjh" + syncPoint + answer <- liftIO $ takeMVar mvar + consoleLog answer dyn $ self.state_var `mapVar` \case ChartsTab inst -> Charts.html inst HelpTab -> p_ $ text diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index 6e757cd..628f933 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -160,12 +160,6 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc domHelpers.insertIntoBuilder(parent, child); return null; } - case ExprTag.HtmlBuilder: { - const dest = evalExpr(hscb, idenScope, argScope, exp.dest) as Element|Comment; - const builderFn = evalExpr(hscb, idenScope, argScope, exp.builderFn) as Function; - builderFn(dest); - return dest; - } case ExprTag.CreateElement: { return document.createElement(exp.tagName); } @@ -398,7 +392,6 @@ export enum ExprTag { Var, FreeScope, - HtmlBuilder, InsertNode, CreateElement, CreateElementNS, @@ -453,7 +446,6 @@ export type Expr = | { tag: ExprTag.FreeScope, scopeId: number } | { tag: ExprTag.InsertNode, parent: Expr, child: Expr } - | { tag: ExprTag.HtmlBuilder, dest: Expr, builderFn: Expr } | { tag: ExprTag.CreateElement, tagName: string } | { tag: ExprTag.CreateElementNS, ns: string, tagName: string } | { tag: ExprTag.CreateText, content: string } @@ -506,7 +498,6 @@ export const expr = b.recursive(self => b.discriminate({ [ExprTag.FreeScope]: b.record({ scopeId: b.int64 }), [ExprTag.InsertNode]: b.record({ parent: self, child: self }), - [ExprTag.HtmlBuilder]: b.record({ dest: self, builderFn: self }), [ExprTag.CreateElement]: b.record({ tagName: b.string }), [ExprTag.CreateElementNS]: b.record({ ns: b.string, tagName: b.string }), [ExprTag.CreateText]: b.record({ content: b.string }), diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 8d160b2..938b35a 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -1,12 +1,14 @@ -module Clickable.Core where +module Clickable.Core + ( module Clickable.Core + , Internal.trampoline + , Internal.syncPoint + , Internal.launchClickM + ) where -import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.IORef import Data.Function ((&)) -import Data.Map qualified as Map -import Data.List qualified as List import Data.Text (Text) import Clickable.Internal (reactive, reactive_) @@ -16,10 +18,6 @@ import Clickable.Protocol import Clickable.Protocol.Value (Value) import Clickable.Protocol.Value qualified as Value - -launchClickM :: InternalEnv -> ClickM a -> IO a -launchClickM env = flip runReaderT env . unClickT . trampoline - --------------------------------------- -- OPERATIONS OVER DYNAMIC VARIABLES -- --------------------------------------- @@ -58,11 +56,15 @@ writeVar var s = modifyVar var $ const s subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () subscribe val k = reactive_ $ Internal.subscribe val k +-------------------------------------- +-- OPERATIONS OVER evaluation_queue -- +-------------------------------------- + enqueueExpr :: Expr -> ClickM () enqueueExpr e = modify \s -> s {evaluation_queue = e : s.evaluation_queue} -evalExpr :: Expr -> ClickM Value -evalExpr e = do +evalSync :: Expr -> ClickM Value +evalSync e = do send_message <- asks (.send_message) queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) result <- liftIO $ send_message $ EvalExpr $ RevSeq $ e : queue @@ -78,11 +80,12 @@ newScope :: ClickM ResourceScope newScope = reactive Internal.newScope freeScope :: Bool -> ResourceScope -> ClickM () -freeScope unlink s = f where - f = reactive (const (Internal.freeScope unlink s)) >>= g - g [] = enqueueExpr $ FreeScope s - g ((_, ScopeFinalizer s'):xs) = freeScope True s' >> g xs - g ((_, CustomFinalizer x):xs) = x >> g xs +freeScope unlink s = + reactive (const (Internal.freeScope unlink s)) >>= applyFin + where + applyFin [] = enqueueExpr $ FreeScope s + applyFin ((_, ScopeFinalizer s'):xs) = freeScope True s' >> applyFin xs + applyFin ((_, CustomFinalizer x):xs) = x >> applyFin xs installFinalizer :: ClickM () -> ClickM () installFinalizer k = reactive_ $ Internal.installFinalizer k @@ -90,31 +93,6 @@ installFinalizer k = reactive_ $ Internal.installFinalizer k newVar :: ClickM VarId newVar = reactive Internal.newVar --- | Loop until transaction_queue is empty. --- --- This makes possible to implement @Applicative DynVal@ without --- redundantly firing callback for the final result. TODO: Is this --- even worth-while to have? What if just let multiple DOM changes --- when it depends on multiple sources? -trampoline :: ClickM a -> ClickM a -trampoline act = loop0 act where - loop0 :: ClickM a -> ClickM a - loop0 before = do - r <- before - mcont <- popQueue - forM_ mcont loop1 - return r - loop1 :: ClickM () -> ClickM () - loop1 before = do - before - mcont <- popQueue - forM_ mcont loop1 - popQueue :: ClickM (Maybe (ClickM ())) - popQueue = state \s -> - case Map.minViewWithKey s.transaction_queue of - Nothing -> (Nothing, s) - Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) - ------------------ -- BUILDING DOM -- ------------------ @@ -203,7 +181,7 @@ htmlBuilder :: Expr -> ClickM a -> ClickM a htmlBuilder builder content = do prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) result <- content - let mkExpr revSeq = InsertNode (Arg 0 0) (HtmlBuilder builder (Lam (RevSeq revSeq))) + let mkExpr revSeq = InsertNode (Arg 0 0) (Lam (RevSeq (Arg 0 0 : revSeq)) `Apply` [builder]) modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} return result @@ -211,7 +189,7 @@ htmlBuilder1 :: Expr -> ClickM a -> ClickM a htmlBuilder1 builder content = do prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) result <- content - let mkExpr revSeq = HtmlBuilder builder (Lam (RevSeq revSeq)) + let mkExpr revSeq = Apply (Lam (RevSeq (Arg 0 0 : revSeq))) [builder] modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} return result @@ -239,7 +217,7 @@ saveCurrentNode = do insertBoundary :: ClickM VarId insertBoundary = do boundary <- newVar - modify \s -> s {evaluation_queue = AssignVar boundary (InsertBoundary (Arg 0 0)) : s.evaluation_queue} + enqueueExpr $ AssignVar boundary (InsertBoundary (Arg 0 0)) return boundary clearBoundary :: VarId -> ClickM () @@ -249,23 +227,16 @@ destroyBoundary :: VarId -> ClickM () destroyBoundary boundary = enqueueExpr (ClearBoundary (Var boundary) True) attachHtml :: Expr -> HtmlM a -> ClickM a -attachHtml builder contents = do - saveQueue <- state \s -> - (s.evaluation_queue, s {evaluation_queue = []}) - result <- evalStateT contents.unHtmlT Nothing - modify \s -> - let - attachExpr = HtmlBuilder builder (Lam (RevSeq s.evaluation_queue)) - in - s {evaluation_queue = attachExpr : saveQueue} - return result +attachHtml rootElm contents = do + savedQueue <- state saveQueue + evalStateT contents.unHtmlT Nothing + <* modify (enqueueHtml savedQueue) + where + enqueueHtml savedQueue s = s {evaluation_queue = e : savedQueue} + where + e = Lam (RevSeq (Arg 0 0 : s.evaluation_queue)) `Apply` [rootElm] + saveQueue s = + (s.evaluation_queue, s {evaluation_queue = []}) attachToBody :: HtmlM a -> ClickM a attachToBody = attachHtml (Id "document" `Dot` "body") - -syncPoint :: ClickM () -syncPoint = do - send_message <- asks (.send_message) - queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - liftIO $ send_message $ EvalExpr $ RevSeq queue - return () diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 0b5c00a..7e7387d 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -1,8 +1,5 @@ module Clickable.Internal where -import Clickable.FFI qualified as FFI -import Clickable.Protocol -import Clickable.Types import Control.Monad.Reader import Control.Monad.State import Data.Binary qualified as Binary @@ -21,6 +18,9 @@ import Foreign.Storable import Unsafe.Coerce import Wasm.Compat.Prim +import Clickable.FFI qualified as FFI +import Clickable.Protocol +import Clickable.Types emptyInternalState :: InternalState emptyInternalState = InternalState [] [] Map.empty [] 0 @@ -34,13 +34,17 @@ newInternalEnv = mdo let env = InternalEnv {internal_state_ref, scope, send_message = sendMessage receiveCb} return env +-- | Unsafe because there is no gurantee that @a@ matches @a@ in +-- correspoding @DynVar a@ where SourceId comes from unsafeTrigger :: SourceId -> a -> InternalState -> InternalState -unsafeTrigger varId vals = go0 where - go0 = defer varId $ gets (.subscriptions) >>= go1 - go1 [] = return () - go1 ((_, sVar, cb) : xs) - | sVar == varId = cb (unsafeCoerce vals) >> go1 xs - | otherwise = go1 xs +unsafeTrigger sourceId vals = + defer sourceId $ gets (.subscriptions) >>= notify + where + notify [] = return () + notify ((_, s, cb) : xs) + | s == sourceId = cb (unsafeCoerce vals) >> notify xs + | otherwise = notify xs + defer k act s = s {transaction_queue = Map.insert k act s.transaction_queue} newScope :: ResourceScope -> InternalState -> (InternalState, ResourceScope) newScope p s = @@ -105,15 +109,6 @@ subscribe (SplatVal fv av) fn scope s = readVal (MapVal val f) = fmap f $ readVal val readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) -defer :: SourceId -> ClickM () -> InternalState -> InternalState -defer k act s = s { transaction_queue = Map.insert k act s.transaction_queue } - -reactive :: (ResourceScope -> InternalState -> (InternalState, a)) -> ClickM a -reactive f = ClickT $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ f e.scope - -reactive_ :: (ResourceScope -> InternalState -> InternalState) -> ClickM () -reactive_ f = reactive \scope s -> (f scope s, ()) - sendMessage :: JSVal -> HaskellMessage -> IO JavaScriptMessage sendMessage receiveCb hmsg = do hptr <- storeByteString $ BSL.toStrict $ Binary.encode hmsg @@ -187,3 +182,9 @@ syncPoint = do queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) liftIO $ send_message $ EvalExpr $ RevSeq queue return () + +reactive :: (ResourceScope -> InternalState -> (InternalState, a)) -> ClickM a +reactive f = ClickT $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ f e.scope + +reactive_ :: (ResourceScope -> InternalState -> InternalState) -> ClickM () +reactive_ f = reactive \scope s -> (f scope s, ()) diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index 1d25d42..0e74087 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -133,7 +133,6 @@ data Expr | FreeScope ResourceScope -- ^ Free all the resources assosiated with the given ResourceScope - | HtmlBuilder Expr Expr | InsertNode Expr Expr | CreateElement Text | CreateElementNS Text Text From 7840a8cacf2f6a0232b3d3ef2bbdcf62db8c0687 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sat, 30 Mar 2024 03:17:07 +0400 Subject: [PATCH 18/64] Hot reloading --- default.nix | 26 ++- htmlt.cabal | 25 +- src/Clickable.hs | 1 - src/Clickable/Core.hs | 10 +- src/Clickable/FFI.hs | 239 ------------------- src/Clickable/Internal.hs | 21 ++ src/Clickable/Main/DevServer.hs | 333 ++++++++++++++++++++++++++ src/Wasm/Compat/Marshal.hs | 398 -------------------------------- 8 files changed, 386 insertions(+), 667 deletions(-) create mode 100644 src/Clickable/Main/DevServer.hs delete mode 100644 src/Wasm/Compat/Marshal.hs diff --git a/default.nix b/default.nix index f4859f6..1bfdae4 100644 --- a/default.nix +++ b/default.nix @@ -20,22 +20,24 @@ let htmlt = self.callCabal2nix "htmlt" ./. {}; - # th-compat = self.callCabal2nix "th-compat" ./packages/th-compat {}; + th-compat = self.callCabal2nix "th-compat" ../fullstack-app/packages/th-compat {}; + aeson = doJailbreak (self.callCabal2nix "aeson" ../fullstack-app/packages/aeson {}); + bifunctors = doJailbreak super.bifunctors; + free = doJailbreak super.free; + generic-deriving = doJailbreak super.generic-deriving; + invariant = doJailbreak super.invariant; + lens = doJailbreak super.lens; + semigroupoids = doJailbreak super.semigroupoids; tagged = self.callCabal2nix "tagged" ../fullstack-app/packages/tagged {}; + text-short = self.callCabal2nix "text-short" ../fullstack-app/packages/text-short {}; th-abstraction = self.callCabal2nix "th-abstraction" ../fullstack-app/packages/th-abstraction {}; + th-expand-syns = doJailbreak super.th-expand-syns; + th-lift = doJailbreak super.th-lift; + unordered-containers = self.callCabal2nix "unordered-containers" ../fullstack-app/packages/unordered-containers {}; vector = self.callCabal2nix "vector" ../fullstack-app/packages/vector/vector {}; vector-stream = self.callCabal2nix "vector-stream" ../fullstack-app/packages/vector/vector-stream {}; - unordered-containers = self.callCabal2nix "unordered-containers" ../fullstack-app/packages/unordered-containers {}; - # text-short = self.callCabal2nix "text-short" ./packages/text-short {}; - generic-deriving = doJailbreak super.generic-deriving; - bifunctors = doJailbreak super.bifunctors; - semigroupoids = doJailbreak super.semigroupoids; - th-lift = doJailbreak super.th-lift; - th-expand-syns = doJailbreak super.th-expand-syns; - invariant = doJailbreak super.invariant; - free = doJailbreak super.free; - th-compat = doJailbreak super.th-compat; - lens = doJailbreak super.lens; + websockets = doJailbreak super.websockets; + wuss = doJailbreak super.wuss; }; }; diff --git a/htmlt.cabal b/htmlt.cabal index 24193df..daaa4a9 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -80,15 +80,6 @@ library import: htmlt-common hs-source-dirs: src ./examples/charts exposed-modules: - -- HtmlT - -- HtmlT.Base - -- HtmlT.DOM - -- HtmlT.Element - -- HtmlT.Event - -- HtmlT.Internal - -- HtmlT.Main - -- HtmlT.Property - -- HtmlT.Types Clickable Clickable.Core Clickable.DOM @@ -101,7 +92,6 @@ library Clickable.Protocol.Value Clickable.FFI Wasm.Compat.Prim - Wasm.Compat.Marshal other-modules: Paths_htmlt build-depends: @@ -115,8 +105,19 @@ library transformers, ghc-experimental, ghc-prim, - -- generic-lens, - + if !arch(wasm32) + exposed-modules: + Clickable.Main.DevServer + build-depends: + async, + foreign-store, + http-types, + wai, + wai-app-static, + wai-websockets, + warp, + websockets, + -- executable htmlt-counter -- import: htmlt-common -- main-is: counter.hs diff --git a/src/Clickable.hs b/src/Clickable.hs index 06325d1..431b77e 100644 --- a/src/Clickable.hs +++ b/src/Clickable.hs @@ -6,5 +6,4 @@ import Clickable.Element as Exports import Clickable.Main as Exports import Clickable.Property as Exports import Clickable.Types as Exports -import Wasm.Compat.Marshal as Exports import Wasm.Compat.Prim as Exports diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 938b35a..87299e5 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -39,19 +39,19 @@ readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) readVar :: DynVar a -> ClickM a readVar (DynVar _ ref) = liftIO $ readIORef ref -atomicModifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a -atomicModifyVar var@(DynVar varId ref) f = do +modifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a +modifyVar var@(DynVar varId ref) f = do (newVal, a) <- liftIO $ atomicModifyIORef' ref g modify $ Internal.unsafeTrigger varId newVal return a where g old = let (new, a) = f old in (new, (new, a)) -modifyVar :: DynVar s -> (s -> s) -> ClickM () -modifyVar var f = atomicModifyVar var ((,()) . f) +modifyVar_ :: DynVar s -> (s -> s) -> ClickM () +modifyVar_ var f = modifyVar var ((,()) . f) writeVar :: DynVar s -> s -> ClickM () -writeVar var s = modifyVar var $ const s +writeVar var s = modifyVar_ var $ const s subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () subscribe val k = reactive_ $ Internal.subscribe val k diff --git a/src/Clickable/FFI.hs b/src/Clickable/FFI.hs index cd8879b..b5dfa12 100644 --- a/src/Clickable/FFI.hs +++ b/src/Clickable/FFI.hs @@ -8,260 +8,21 @@ #endif module Clickable.FFI where -import Control.Monad.IO.Class import Wasm.Compat.Prim import GHC.Ptr import Data.Word -import GHC.Prim -import Data.Text.Internal -import Data.Array.Byte - - -newtype DomBuilder = DomBuilder {unDomBuilder :: JSVal} - -insertText :: JSVal -> Text -> IO JSVal -insertText root (Text (ByteArray arr) off len) = do - let addr = byteArrayContents# arr - js_insertText root (Ptr addr `plusPtr` off) len - -insertElement :: JSVal -> Text -> IO JSVal -insertElement root (Text (ByteArray arr) off len) = do - let addr = byteArrayContents# arr - js_insertElement root (Ptr addr `plusPtr` off) len - -updateTextContent :: JSVal -> Text -> IO () -updateTextContent root (Text (ByteArray arr) off len) = do - let addr = byteArrayContents# arr - js_updateTextContent root (Ptr addr `plusPtr` off) len - -setProperty :: JSVal -> Text -> Text -> IO () -setProperty root (Text (ByteArray arr0) off0 len0) (Text (ByteArray arr1) off1 len1) = do - let addr0 = byteArrayContents# arr0 - let addr1 = byteArrayContents# arr1 - js_setProperty root (Ptr addr0 `plusPtr` off0) len0 (Ptr addr1 `plusPtr` off1) len1 - -setBoolProperty :: JSVal -> Text -> Bool -> IO () -setBoolProperty root (Text (ByteArray arr0) off0 len0) val = do - let addr0 = byteArrayContents# arr0 - js_setBoolProperty root (Ptr addr0 `plusPtr` off0) len0 (if val then 1 else 0) - -setAttribute :: JSVal -> Text -> Text -> IO () -setAttribute root (Text (ByteArray arr0) off0 len0) (Text (ByteArray arr1) off1 len1) = do - let addr0 = byteArrayContents# arr0 - let addr1 = byteArrayContents# arr1 - js_setAttribute root (Ptr addr0 `plusPtr` off0) len0 (Ptr addr1 `plusPtr` off1) len1 - -addEventListener :: JSVal -> Text -> JSVal -> IO () -addEventListener root (Text (ByteArray arr) off len) lisnr = do - let addr = byteArrayContents# arr - js_addEventListener root (Ptr addr `plusPtr` off) len lisnr - -removeEventListener :: JSVal -> Text -> JSVal -> IO () -removeEventListener root (Text (ByteArray arr) off len) lisnr = do - let addr = byteArrayContents# arr - js_removeEventListener root (Ptr addr `plusPtr` off) len lisnr - -consoleLog :: MonadIO m => Text -> m () -consoleLog (Text (ByteArray arr) off len) = liftIO do - let addr = byteArrayContents# arr - js_consoleLog (Ptr addr `plusPtr` off) len - -aquireResource :: JSVal -> Text -> JSVal -> IO JSVal -aquireResource root (Text (ByteArray arr) off len) lisnr = do - let addr = byteArrayContents# arr - js_aquireResource root (Ptr addr `plusPtr` off) len lisnr - -apply0 :: JSVal -> IO () -apply0 = js_apply0 #if !defined(wasm32_HOST_ARCH) -js_insertText :: JSVal -> Ptr Word8 -> Int -> IO JSVal -js_insertText = undefined - -js_insertElement :: JSVal -> Ptr Word8 -> Int -> IO JSVal -js_insertElement = undefined - -js_updateTextContent :: JSVal -> Ptr Word8 -> Int -> IO () -js_updateTextContent = undefined - -js_setProperty :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () -js_setProperty = undefined - -js_setBoolProperty :: JSVal -> Ptr Word8 -> Int -> Int -> IO () -js_setBoolProperty = undefined - -js_setAttribute :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () -js_setAttribute = undefined - -js_addEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () -js_addEventListener = undefined - -js_removeEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () -js_removeEventListener = undefined - -js_dynExport :: (JSVal -> IO ()) -> IO JSVal -js_dynExport = undefined - -documentBody :: IO JSVal -documentBody = undefined - -js_consoleLog :: Ptr Word8 -> Int -> IO () -js_consoleLog = undefined - -js_insertBrackets :: JSVal -> IO JSVal -js_insertBrackets = undefined - -js_clearBrackets :: JSVal -> IO () -js_clearBrackets = undefined - -js_removeBrackets :: JSVal -> IO () -js_removeBrackets = undefined - -js_aquireResource :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO JSVal -js_aquireResource = undefined - -js_apply0 :: JSVal -> IO () -js_apply0 = undefined - js_evalMessageFFI :: JSVal -> Ptr Word8 -> IO (Ptr Word8) js_evalMessageFFI = undefined js_exportCallback :: (Ptr Word8 {- JavaScriptMessage -} -> IO ()) -> IO JSVal js_exportCallback = undefined -js_installCallback :: JSVal -> IO () -js_installCallback = undefined - #else -foreign import javascript unsafe - "var c = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ - var n = document.createTextNode(c);\ - if ($1 instanceof Comment) {\ - $1.parentNode.insertBefore(n, $1);\ - } else {\ - $1.appendChild(n);\ - }\ - return n;" - js_insertText :: JSVal -> Ptr Word8 -> Int -> IO JSVal -foreign import javascript unsafe - "var t = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ - var n = document.createElement(t);\ - if ($1 instanceof Comment) {\ - $1.parentNode.insertBefore(n, $1);\ - } else {\ - $1.appendChild(n);\ - }\ - return n;" - js_insertElement :: JSVal -> Ptr Word8 -> Int -> IO JSVal -foreign import javascript unsafe - "$1.nodeValue = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));" - js_updateTextContent :: JSVal -> Ptr Word8 -> Int -> IO () -foreign import javascript unsafe - "var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ - var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5));\ - if ($1 instanceof Comment) {\ - $1.parentNode[k] = v;\ - } else {\ - $1[k] = v;\ - }" - js_setProperty :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () -foreign import javascript unsafe - "var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ - if ($1 instanceof Comment) {\ - $1.parentNode[k] = $4 == 0 ? false : true;\ - } else {\ - $1[k] = $4 == 0 ? false : true;\ - }" - js_setBoolProperty :: JSVal -> Ptr Word8 -> Int -> Int -> IO () -foreign import javascript unsafe - "var k = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ - var v = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5));\ - if ($1 instanceof Comment) {\ - $1.parentNode.setAttribute(k, v);\ - } else {\ - $1.setAttribute(k, v);\ - }" - js_setAttribute :: JSVal -> Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO () -foreign import javascript unsafe "document.body" documentBody :: IO JSVal -foreign import javascript unsafe - "var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ - if ($1 instanceof Comment) {\ - $1.parentNode.addEventListener(e, $4);\ - } else {\ - $1.addEventListener(e, $4);\ - }" - js_addEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () -foreign import javascript unsafe - "var e = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ - if ($1 instanceof Comment) {\ - $1.parentNode.addEventListener(e, $4);\ - } else {\ - $1.removeEventListener(e, $4);\ - }" - js_removeEventListener :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () -foreign import javascript "wrapper" js_dynExport :: (JSVal -> IO ()) -> IO JSVal -foreign import javascript unsafe - "console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));" - js_consoleLog :: Ptr Word8 -> Int -> IO () -foreign import javascript unsafe - "var c1 = document.createComment('ContentBoundary {{');\ - var c2 = document.createComment('}}');\ - if ($1 instanceof Comment) {\ - $1.parentNode.insertBefore(c1, $1);\ - $1.parentNode.insertBefore(c2, $1);\ - } else {\ - $1.appendChild(c1);\ - $1.appendChild(c2);\ - }\ - return c2;" - js_insertBrackets :: JSVal -> IO JSVal -foreign import javascript unsafe - "function isOpenBracket(node) {return node instanceof Comment && node.textContent == 'ContentBoundary {{'}\ - function isCloseBracket(node) {return node instanceof Comment && node.textContent == '}}'}\ - var iter = $1;\ - var nestedCounter = 0;\ - for (;;){\ - if (!iter.previousSibling ||\ - (nestedCounter == 0 && isOpenBracket(iter.previousSibling))\ - ) break;\ - if (isCloseBracket(iter.previousSibling)) nestedCounter++;\ - else if (isOpenBracket(iter.previousSibling)) nestedCounter--;\ - iter.previousSibling.parentNode.removeChild(iter.previousSibling);\ - }" - js_clearBrackets :: JSVal -> IO () -foreign import javascript unsafe - "function isOpenBracket(node) {return node instanceof Comment && node.textContent == 'ContentBoundary {{'}\ - function isCloseBracket(node) {return node instanceof Comment && node.textContent == '}}'}\ - var iter = $1;\ - var nestedCounter = 0;\ - for (;;){\ - if (!iter.previousSibling ||\ - (nestedCounter == 0 && isOpenBracket(iter.previousSibling))\ - ) break;\ - if (isCloseBracket(iter.previousSibling)) nestedCounter++;\ - else if (isOpenBracket(iter.previousSibling)) nestedCounter--;\ - iter.previousSibling.parentNode.removeChild(iter.previousSibling);\ - }\ - $1.parentNode($1);\ - if ($1 != iter) iter.parentNode.removeChild(iter);\ - " - js_removeBrackets :: JSVal -> IO () -foreign import javascript unsafe - "var j = new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3));\ - if ($1 instanceof Comment) {\ - return eval(j)($1.parentNode, $4);\ - } else {\ - return eval(j)($1, $4);\ - }" - js_aquireResource :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO JSVal -foreign import javascript unsafe - "$1()" js_apply0 :: JSVal -> IO () foreign import javascript unsafe "evalMessageFFI($1, __exports, $2)" js_evalMessageFFI :: JSVal -> Ptr Word8 {- HaskellMessage -} -> IO (Ptr Word8 {- JavaScriptMessage -}) -foreign import javascript unsafe - "window._javascriptMessageCallback = $1;" - js_installCallback :: JSVal -> IO () foreign import javascript "wrapper" js_exportCallback :: (Ptr Word8 {- JavaScriptMessage -} -> IO ()) -> IO JSVal #endif diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 7e7387d..b1fb75a 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -188,3 +188,24 @@ reactive f = ClickT $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ reactive_ :: (ResourceScope -> InternalState -> InternalState) -> ClickM () reactive_ f = reactive \scope s -> (f scope s, ()) + +data ClientMessage + = BrowserMessage JavaScriptMessage + -- ^ Regular command received from JavaScript environment + | DevServerMessage (ClickM ()) + -- ^ Bypass protocol and inject a command directly into the + -- DevServer instance (useful for delivering notifications under + -- devserver) + +handleMessage :: InternalEnv -> (StartFlags -> ClickM ()) -> ClientMessage -> IO HaskellMessage +handleMessage e jsMain = \case + BrowserMessage (Start startFlags) -> do + launchClickM e $ jsMain startFlags + return Halt + BrowserMessage (Return _val) -> return Halt + BrowserMessage (TriggerCallbackMsg arg sourceId) -> do + launchClickM e $ modify (unsafeTrigger sourceId arg) + return Halt + BrowserMessage BeforeUnload -> + return Halt + DevServerMessage a -> Halt <$ launchClickM e a diff --git a/src/Clickable/Main/DevServer.hs b/src/Clickable/Main/DevServer.hs new file mode 100644 index 0000000..163cfca --- /dev/null +++ b/src/Clickable/Main/DevServer.hs @@ -0,0 +1,333 @@ +module Clickable.DevServer where + +import Control.Concurrent +import Control.Concurrent.Async +import Control.Exception +import Control.Monad +import Control.Monad.State +import Data.Binary qualified as Binary +import Data.ByteString as BS +import Data.ByteString.Lazy qualified as BSL +import Data.Function +import Data.IORef +import Data.List qualified as List +import Data.Map (Map) +import Data.Map qualified as Map +import Data.Typeable +import Foreign.Store +import GHC.Generics +import GHC.IO.Exception +import Network.HTTP.Types as H +import Network.Wai as WAI +import Network.Wai.Application.Static +import Network.Wai.Handler.Warp as Warp +import Network.Wai.Handler.WebSockets +import Network.WebSockets +import System.Environment +import System.IO + +import "this" Clickable.Types +import "this" Clickable.Protocol +import "this" Clickable.Protocol.Value (Value(..)) +import "this" Clickable.Internal (ClientMessage(..)) +import "this" Clickable.Internal qualified as Internal + + +data DevServerConfig a = DevServerConfig + { aquire_resource :: IO a + -- ^ Usualy runs once just after ghci session is loaded, + -- e.g. establish connection to database etc + , release_resource :: a -> IO () + -- ^ Runs before the ghci session is unloaded + , reload_app :: a -> IO ApplicationSpec + -- ^ Given resource of type 'a', initialize instances of client and + -- server applications. Runs each time ghci session reloads + , html_template :: BSL.ByteString -> BSL.ByteString + -- ^ Template for index.html, receives the current URL origin + -- (protocol + host) + , docroots :: [FilePath] + -- ^ List of directories to use with wai-static middleware, could be + -- empty, usually be used like docroots = ["./public"] + } deriving Generic + +data ApplicationSpec = ApplicationSpec + { client_app :: ConnectionInfo -> StartFlags -> ClickM () + , server_app :: Application + , connection_lost :: ConnectionInfo -> IO () + -- ^ Will be executed after a connection closes + } deriving Generic + +defaultDevServerConfig :: (ConnectionInfo -> StartFlags -> ClickM ()) -> DevServerConfig () +defaultDevServerConfig clientApp = DevServerConfig + { aquire_resource = pure () + , release_resource = const (pure ()) + , reload_app = \_ -> pure $ ApplicationSpec clientApp defaultFallbackApp (const (pure ())) + , html_template = defaultHtmlTemplate + , docroots = [] + } + +runDebug :: Typeable resource => Warp.Settings -> DevServerConfig resource -> IO () +runDebug settings cfg = do + -- Using a random constant as the key for Foreign.Store + let storeId = 183 + hSetBuffering stderr LineBuffering + lookupStore storeId >>= \case + Nothing -> do + devInst <- newInstance cfg + writeStore (Store storeId) devInst + let + useCurrentApp req resp = do + RunningApp{devserver_config, server_app} <- readIORef devInst.app_state_ref + withStaticApp devserver_config.docroots server_app req resp + forkIfRepl $ tryPort settings $ + devserverMiddleware devInst useCurrentApp + Just store -> do + oldInst <- readStore store + updateInstance cfg oldInst + conns <- readIORef oldInst.conn_state_ref + forM_ conns \conn -> + sendDataMessage conn.connection . Binary $ Binary.encode HotReload + where + tryPort :: Warp.Settings -> Application -> IO () + tryPort settings application = do + hPutStrLn stderr $ "Running a Dev Server at http://localhost:" <> + show (getPort settings) <> "/" + result <- try $ runSettings settings application + case result of + Right () -> return () + Left (e::IOException) + | ioe_type e == ResourceBusy -> do + hPutStrLn stderr $ "Already in use, trying next port…" + tryPort (setPort (getPort settings + 1) settings) application + | otherwise -> throwIO e + withStaticApp :: [FilePath] -> Middleware + withStaticApp [] next = next + withStaticApp (docroot:docroots) next = + staticApp (defaultFileServerSettings docroot) + {ss404Handler = Just (withStaticApp docroots next)} + forkIfRepl action = do + isRepl <- (== "") <$> getProgName + if isRepl then void (forkIO action) else action + +runDebugPort :: Typeable resource => Warp.Port -> DevServerConfig resource -> IO () +runDebugPort port cfg = + runDebug (Warp.setPort port Warp.defaultSettings) cfg + +runDebugDefault :: Warp.Port -> (ConnectionInfo -> StartFlags -> ClickM ()) -> IO () +runDebugDefault port clientApp = runDebug + (Warp.setPort port Warp.defaultSettings) + (defaultDevServerConfig clientApp) + +devserverMiddleware :: DevServerInstance -> Middleware +devserverMiddleware opts next req resp = + case pathInfo req of + [] -> indexHtmlApp req resp + ["index.html"] -> indexHtmlApp req resp + ["dev-server.sock"] -> devserverApp req resp + _ -> next req resp + where + devserverApp = + websocketsOr defaultConnectionOptions (devserverWebsocket opts) + defaultFallbackApp + indexHtmlApp req resp = do + let devSocket = devServerSocketUrl req + RunningApp{devserver_config} <- readIORef opts.app_state_ref + resp $ responseLBS status200 + [(hContentType, "text/html; charset=utf-8")] $ + devserver_config.html_template devSocket + +devServerSocketUrl :: WAI.Request -> BSL.ByteString +devServerSocketUrl req = + WAI.requestHeaders req + & List.lookup "Host" + & maybe "localhost" BSL.fromStrict + & ((if WAI.isSecure req then "wss://" else "ws://") <>) + & (<> "/dev-server.sock") + +defaultHtmlTemplate :: BSL.ByteString -> BSL.ByteString +defaultHtmlTemplate devSocket = + "\n\ + \ \n\ + \ \n\ + \ \n\ + \\n\ + \" + +defaultFallbackApp :: Application +defaultFallbackApp _ resp = + resp $ responseLBS status404 + [(hContentType, "text/html; charset=utf-8")] + "\n\ + \ \n\ + \

Not Found

\n\ + \ \n\ + \\n\ + \" + +devserverWebsocket :: DevServerInstance -> ServerApp +devserverWebsocket opt p = + let + acceptConn = mdo + conn <- acceptRequest p + newConn conn + dropConn connInfo = do + modifyIORef' opt.conn_state_ref $ Map.delete connInfo.connection_id + runningApp <- readIORef opt.app_state_ref + runningApp.connection_lost connInfo + receive c = + try @ConnectionException (receiveData c) + loop connInfo = do + runningApp <- readIORef opt.app_state_ref + raceResult <- race (receive connInfo.connection) (readChan connInfo.command_chan) + case raceResult of + Left (Right (incomingBytes::ByteString)) -> do + let jsMessage = Binary.decode . BSL.fromStrict $ incomingBytes + reader connInfo $ BrowserMessage jsMessage + loop connInfo + Left (Left (_::ConnectionException)) -> + return () + Right jsAction -> do + reader connInfo $ DevServerMessage jsAction + loop connInfo + + reader :: ConnectionInfo -> ClientMessage -> IO () + reader conn = \case + BrowserMessage (Return val) -> putMVar conn.return_mvar val + BrowserMessage (TriggerCallbackMsg arg sourceId) -> do + modifyIORef' conn.queue_ref (modify (Internal.unsafeTrigger sourceId arg):) + putMVar conn.signal_mvar () + BrowserMessage BeforeUnload -> + return () + DevServerMessage a -> do + modifyIORef' conn.queue_ref (a:) + putMVar conn.signal_mvar () + + worker :: ConnectionInfo -> IO () + worker conn = do + takeMVar conn.signal_mvar + queue <- atomicModifyIORef' conn.queue_ref ([],) + forM_ queue $ Internal.launchClickM conn.internal_env + worker conn + + newConn connection = mdo + command_chan <- newChan + return_mvar <- newEmptyMVar + signal_mvar <- newEmptyMVar + queue_ref <- newIORef [] + internal_env <- newInternalEnv connection return_mvar + connInfo <- atomicModifyIORef' opt.conn_state_ref \m -> + let + connection_id = Map.lookupMax m & maybe 0 (succ . fst) + connInfo = ConnectionInfo + { internal_env + , connection + , command_chan + , connection_id + , return_mvar + , signal_mvar + , worker_thread + , queue_ref } + in + (Map.insert connection_id connInfo m, connInfo) + worker_thread <- forkIO $ worker connInfo + return connInfo + newInternalEnv :: Connection -> MVar Value -> IO InternalEnv + newInternalEnv conn resultMvar = do + let scope = ResourceScope Internal.emptyInternalState.next_id + internal_state_ref <- newIORef Internal.emptyInternalState + {next_id = Internal.emptyInternalState.next_id + 1} + let + sendMessage haskMessage = do + sendDataMessage conn . Binary $ Binary.encode haskMessage + Return <$> takeMVar resultMvar + return InternalEnv {internal_state_ref, scope, send_message = sendMessage} + in + bracket acceptConn dropConn \connInfo -> + withPingThread connInfo.connection 30 (pure ()) $ loop connInfo + +newInstance :: Typeable resource => DevServerConfig resource -> IO DevServerInstance +newInstance cfg = do + resource <- cfg.aquire_resource + appSpec <- cfg.reload_app resource + app_state_ref <- newIORef RunningApp + { resource + , devserver_config = cfg + , client_app = appSpec.client_app + , server_app = appSpec.server_app + , connection_lost = appSpec.connection_lost + } + conn_state_ref <- newIORef Map.empty + return DevServerInstance {conn_state_ref, app_state_ref} + +updateInstance + :: Typeable resource + => DevServerConfig resource + -> DevServerInstance + -> IO () +updateInstance cfg devInst = do + let + tryOldResource :: forall a. Typeable a => DevServerConfig a -> + RunningApp -> Either (IO ()) a + tryOldResource _ RunningApp {resource, devserver_config} + | Just Refl <- eqResource @a resource = Right resource + | otherwise = Left (devserver_config.release_resource resource) + eqResource :: forall a b. (Typeable a, Typeable b) => b -> Maybe (a :~: b) + eqResource _ = eqT @a @b + oldApp <- readIORef devInst.app_state_ref + case tryOldResource cfg oldApp of + Right oldResource -> do + appSpec <- cfg.reload_app oldResource + writeIORef devInst.app_state_ref RunningApp + { resource = oldResource + , devserver_config = cfg + , client_app = appSpec.client_app + , server_app = appSpec.server_app + , connection_lost = appSpec.connection_lost + } + Left releaseOld -> do + releaseOld + newResource <- cfg.aquire_resource + appSpec <- cfg.reload_app newResource + writeIORef devInst.app_state_ref RunningApp + { resource = newResource + , devserver_config = cfg + , client_app = appSpec.client_app + , server_app = appSpec.server_app + , connection_lost = appSpec.connection_lost + } + +data DevServerInstance = DevServerInstance + { conn_state_ref :: IORef (Map ConnectionId ConnectionInfo) + , app_state_ref :: IORef RunningApp + } deriving Generic + +data ConnectionInfo = ConnectionInfo + { connection :: Connection + , return_mvar :: MVar Value + , signal_mvar :: MVar () + , queue_ref :: IORef [ClickM ()] + , internal_env :: InternalEnv + , command_chan :: Chan (ClickM ()) + , worker_thread :: ~ThreadId + -- ^ Writing to the Chan sends a command to the browser to execute + , connection_id :: ConnectionId + } deriving Generic + +data RunningApp = forall a. Typeable a => RunningApp + { resource :: a + , devserver_config :: DevServerConfig a + , client_app :: ConnectionInfo -> StartFlags -> ClickM () + , server_app :: Application + , connection_lost :: ConnectionInfo -> IO () + } + +newtype ConnectionId = ConnectionId {unConnectionId :: Int} + deriving newtype (Ord, Show, Eq, Num, Enum) + +-- | Run @yarn run webpack --mode production@ and copy contents here +-- from @./dist-newstyle/index.bundle.js@ +indexBundleJs :: ByteString +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={268:(e,t,r)=>{r.d(t,{BE:()=>m,IM:()=>D,IX:()=>h,Z_:()=>y,a0:()=>T,a2:()=>x,bc:()=>O,cS:()=>M});var n=r(849);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return g(this,r,0,e),r}decode(e){const[t,r]=f(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class l extends _{constructor(e){super(),this._element=e}}class c extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class p extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof o){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof i)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof c){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return b(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof p)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.R)(e)}function f(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof i){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=f(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=b(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=f(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof p)return f(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=f(e,t,n);return n=_,r})),n]}return(0,n.R)(e)}function g(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof o){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof i){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=g(e,t,a,n[r])})),a}return(0,n.R)(e)}function b(e){return Math.ceil(Math.log2(e)/8)}const M=new a,x=new s,y=new o;function h(e){return new l(e)}function D(e){return new c(e)}function T(e){return new u(e)}function O(...e){return new d(e)}function m(e){const t=new p(void 0),r=e(t);return t._self=r,r}new i},849:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{R:()=>n})},741:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Ub:()=>HaskellMessageTag,Xq:()=>unknownToJValue,bK:()=>JavaScriptMessageTag,f:()=>mkStartMessage,iI:()=>haskellMessage,r:()=>javascriptMessage,sN:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(268),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(849),JValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(idenScope,argScope,hscb,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.Num:return Number(exp.decimal);case ExprTag.Str:return exp[0];case ExprTag.Arr:return exp[0].map(evalExpr.bind(void 0,idenScope,argScope,hscb));case ExprTag.Obj:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(idenScope,argScope,hscb,t)])));case ExprTag.Dot:{const e=evalExpr(idenScope,argScope,hscb,exp[0]);return e[exp[1]]}case ExprTag.AssignProp:{const e=evalExpr(idenScope,argScope,hscb,exp[2]),t=evalExpr(idenScope,argScope,hscb,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(idenScope,argScope,hscb,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=evalExpr(idenScope,argScope,hscb,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=evalExpr(idenScope,argScope,hscb,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=evalExpr(idenScope,argScope,hscb,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=evalExpr(idenScope,argScope,hscb,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(idenScope,Cons(arguments,argScope),hscb,exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(idenScope,argScope,hscb,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,idenScope,argScope,hscb)))}case ExprTag.Call:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,idenScope,argScope,hscb)))}case ExprTag.AssignVar:{const e=evalExpr(idenScope,argScope,hscb,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:return;case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:return varStorage.delete(exp.scopeId);case ExprTag.InsertNode:{const e=evalExpr(idenScope,argScope,hscb,exp.parent),t=evalExpr(idenScope,argScope,hscb,exp.child);return domBuilder.insertIntoBuilder(e,t),null}case ExprTag.WithDomBuilder:{const e=evalExpr(idenScope,argScope,hscb,exp.builder),t=evalExpr(idenScope,argScope,hscb,exp.builderContent);return t(e),e}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(idenScope,argScope,hscb,exp.node),t=evalExpr(idenScope,argScope,hscb,exp.propValue);return domBuilder.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(idenScope,argScope,hscb,exp.node);return domBuilder.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.AddEventListener:{const e=evalExpr(idenScope,argScope,hscb,exp.node),t=evalExpr(idenScope,argScope,hscb,exp.listener);return domBuilder.addEventListener(e,exp.eventName,t),null}case ExprTag.ToggleClass:{const e=evalExpr(idenScope,argScope,hscb,exp.node);return domBuilder.toggleClass(e,exp.className,Boolean(exp.enable)),null}case ExprTag.AssignText:{const e=evalExpr(idenScope,argScope,hscb,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(idenScope,argScope,hscb,exp.parent);return domBuilder.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(idenScope,argScope,hscb,exp.boundary);return domBuilder.clearBoundary(e,Boolean(exp.detach))}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(idenScope,argScope,hscb,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerEvent:{const e=evalExpr(idenScope,argScope,hscb,exp.arg),t={tag:JavaScriptMessageTag.TriggerEvent,arg:unknownToJValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.AsyncCallback:{const e=evalExpr(idenScope,argScope,hscb,exp.arg),t={tag:JavaScriptMessageTag.AsyncCallback,arg:unknownToJValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.R)(exp)}function unknownToJValue(e){if(\"boolean\"==typeof e)return{tag:JValueTag.JBool,0:e?1:0};if(\"number\"==typeof e){const t=e.toString();return{tag:JValueTag.JNum,decimal:t}}if(\"string\"==typeof e)return{tag:JValueTag.JStr,0:e};if(Array.isArray(e))return{tag:JValueTag.JArr,0:e.map(unknownToJValue)};if(null==e)return{tag:JValueTag.JNull};const t=Object.entries(e).map((([e,t])=>[e,unknownToJValue(t)]));return{tag:JValueTag.JObj,0:t}}!function(e){e[e.JObj=0]=\"JObj\",e[e.JArr=1]=\"JArr\",e[e.JStr=2]=\"JStr\",e[e.JNum=3]=\"JNum\",e[e.JBool=4]=\"JBool\",e[e.JNull=5]=\"JNull\"}(JValueTag||(JValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.BE((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.a0({[JValueTag.JObj]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(_binary__WEBPACK_IMPORTED_MODULE_0__.bc(_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,e))}),[JValueTag.JArr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[JValueTag.JStr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[JValueTag.JNum]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({decimal:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[JValueTag.JBool]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[JValueTag.JNull]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({})}))),startLocation=_binary__WEBPACK_IMPORTED_MODULE_0__.IM({protocol:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,hostname:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,port:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,pathname:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,search:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,hash:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),startFlags=_binary__WEBPACK_IMPORTED_MODULE_0__.IM({initial_url:startLocation,window_inner_size:_binary__WEBPACK_IMPORTED_MODULE_0__.bc(_binary__WEBPACK_IMPORTED_MODULE_0__.a2,_binary__WEBPACK_IMPORTED_MODULE_0__.a2)});var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.Num=2]=\"Num\",e[e.Str=3]=\"Str\",e[e.Arr=4]=\"Arr\",e[e.Obj=5]=\"Obj\",e[e.Dot=6]=\"Dot\",e[e.AssignProp=7]=\"AssignProp\",e[e.Ix=8]=\"Ix\",e[e.Add=9]=\"Add\",e[e.Subtract=10]=\"Subtract\",e[e.Multiply=11]=\"Multiply\",e[e.Divide=12]=\"Divide\",e[e.Id=13]=\"Id\",e[e.Lam=14]=\"Lam\",e[e.Arg=15]=\"Arg\",e[e.Apply=16]=\"Apply\",e[e.Call=17]=\"Call\",e[e.AssignVar=18]=\"AssignVar\",e[e.FreeVar=19]=\"FreeVar\",e[e.Var=20]=\"Var\",e[e.FreeScope=21]=\"FreeScope\",e[e.InsertNode=22]=\"InsertNode\",e[e.WithDomBuilder=23]=\"WithDomBuilder\",e[e.CreateElement=24]=\"CreateElement\",e[e.CreateElementNS=25]=\"CreateElementNS\",e[e.CreateText=26]=\"CreateText\",e[e.ElementProp=27]=\"ElementProp\",e[e.ElementAttr=28]=\"ElementAttr\",e[e.AddEventListener=29]=\"AddEventListener\",e[e.ToggleClass=30]=\"ToggleClass\",e[e.AssignText=31]=\"AssignText\",e[e.InsertBoundary=32]=\"InsertBoundary\",e[e.ClearBoundary=33]=\"ClearBoundary\",e[e.RevSeq=34]=\"RevSeq\",e[e.Eval=35]=\"Eval\",e[e.TriggerEvent=36]=\"TriggerEvent\",e[e.AsyncCallback=37]=\"AsyncCallback\",e[e.UncaughtException=38]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.BE((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.a0({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[ExprTag.Num]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({decimal:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.Str]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[ExprTag.Obj]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(_binary__WEBPACK_IMPORTED_MODULE_0__.bc(_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.AssignProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.cS,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,2:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({parent:e,child:e}),[ExprTag.WithDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({builder:e,builderContent:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,eventName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,listener:e}),[ExprTag.ToggleClass]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,className:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,enable:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[ExprTag.AssignText]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,arg:e}),[ExprTag.AsyncCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.Yield=1]=\"Yield\",e[e.HotReload=2]=\"HotReload\",e[e.Exit=3]=\"Exit\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.a0({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({expr}),[HaskellMessageTag.Yield]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({}),[HaskellMessageTag.Exit]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerEvent=2]=\"TriggerEvent\",e[e.AsyncCallback=3]=\"AsyncCallback\",e[e.BeforeUnload=4]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.a0({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({startFlags}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:jvalue}),[JavaScriptMessageTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[JavaScriptMessageTag.AsyncCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({})}),varStorage=new Map;function mkStartMessage(){const e={protocol:location.protocol,hostname:location.hostname,port:location.port,pathname:location.pathname,search:location.search,hash:location.hash};return{tag:JavaScriptMessageTag.Start,startFlags:{initial_url:e,window_inner_size:[window.innerWidth,window.innerHeight]}}}var domBuilder;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.toggleClass=function(e,t,n){const _=r(e);n?_.classList.add(t):_.classList.remove(t)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))}}(domBuilder||(domBuilder={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}Object.create,Object.create,\"function\"==typeof SuppressedError&&SuppressedError;class t{static read_bytes(e,r){let n=new t;return n.buf=e.getUint32(r,!0),n.buf_len=e.getUint32(r+4,!0),n}static read_bytes_array(e,r,n){let _=[];for(let a=0;athis.file.size){let e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class i{open(e){let t=new s(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new _(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}var o=__webpack_require__(849),l=__webpack_require__(741);function c(e,t,r=null){const n=t||l.f(),_=function(e,t){const r=function(e,t){const r=t.byteLength,n=e.exports.hs_malloc(t.length+8);return new DataView(e.exports.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.exports.memory.buffer,n+8,r).set(t),n}(e,l.r.encode(t)),n=function(e,t){const r=new Uint8Array(e.exports.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.exports.memory.buffer,t+8,n).slice().buffer;return e.exports.hs_free(t),new Uint8Array(_)}(e,e.exports.app(r));return l.iI.decode(n)}(e,n),a=(t,r)=>{c(e,t,r)};switch(_.tag){case l.Ub.EvalExpr:{const t=l.sN(u,r,a,_.expr),n=l.Xq(t);return c(e,{tag:l.bK.Return,0:n},r)}case l.Ub.Yield:return void l.sN(u,r,a,_.expr);case l.Ub.HotReload:return void window.location.reload();case l.Ub.Exit:return}(0,o.R)(_)}const u=[window,null];class p extends s{constructor(e,t){super(e),this.printDebug=t}fd_write(e,t){const r=super.fd_write(e,t);return t.forEach((r=>{this.printDebug(e.subarray(t[0].buf,r.buf+r.buf_len))})),r}}function d(e){let t=[];return r=>{const n=r=>{if(0==r.byteLength)return;const _=r.findIndex((e=>e==\"\\n\".charCodeAt(0)));if(_>=0){const a=t.map((e=>new TextDecoder(\"utf8\").decode(e))).join(\"\");t=[];const s=new TextDecoder(\"utf8\").decode(r.subarray(0,_));e(a+s),n(r.subarray(_+1))}else t.push(r.slice())};n(r)}}function E(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case l.Ub.EvalExpr:{const e=l.sN(f,r,n,t.expr),_=l.Xq(e);return n({tag:l.bK.Return,0:_},r)}case l.Ub.Yield:return void l.sN(f,r,n,t.expr);case l.Ub.HotReload:return void window.location.reload();case l.Ub.Exit:return}(0,o.R)(t)}))}const f=[window,null];function g(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startReactor=function(n,_={}){return e(this,void 0,void 0,(function*(){const e=d(console.log),a=d(console.log),o=new class{start(e){this.inst=e,e.exports._start()}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,n,_){this.args=[],this.env=[],this.fds=[],this.args=e,this.env=n,this.fds=_;let a=this;this.wasiImport={args_sizes_get(e,t){let r=new DataView(a.inst.exports.memory.buffer);r.setUint32(e,a.args.length,!0);let n=0;for(let e of a.args)n+=e.length+1;return r.setUint32(t,n,!0),0},args_get(e,t){let r=new DataView(a.inst.exports.memory.buffer),n=new Uint8Array(a.inst.exports.memory.buffer);for(let _=0;_null!=a.fds[e]?a.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=a.fds[e]?a.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=a.fds[e]){let t=a.fds[e].fd_close();return a.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=a.fds[e]?a.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=a.fds[e]){let{ret:r,fdstat:n}=a.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(a.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=a.fds[e]?a.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=a.fds[e]?a.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=a.fds[e]){let{ret:r,filestat:n}=a.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(a.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=a.fds[e]?a.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=a.fds[e]?a.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,r,n,_,s){let i=new DataView(a.inst.exports.memory.buffer),o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let l=t.read_bytes_array(i,r,n),{ret:c,nread:u}=a.fds[e].fd_pread(o,l,_);return i.setUint32(s,u,!0),c}return 8},fd_prestat_get(e,t){let r=new DataView(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let{ret:n,prestat:_}=a.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=a.fds[e]){let{ret:r,prestat_dir_name:n}=a.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(a.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,n,_,s){let i=new DataView(a.inst.exports.memory.buffer),o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let l=r.read_bytes_array(i,t,n),{ret:c,nwritten:u}=a.fds[e].fd_pwrite(o,l,_);return i.setUint32(s,u,!0),c}return 8},fd_read(e,r,n,_){let s=new DataView(a.inst.exports.memory.buffer),i=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let o=t.read_bytes_array(s,r,n),{ret:l,nread:c}=a.fds[e].fd_read(i,o);return s.setUint32(_,c,!0),l}return 8},fd_readdir(e,t,r,n,_){let s=new DataView(a.inst.exports.memory.buffer),i=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let o=0;for(;;){let{ret:l,dirent:c}=a.fds[e].fd_readdir_single(n);if(0!=l)return s.setUint32(_,o,!0),l;if(null==c)break;if(r-onull!=a.fds[e]?a.fds[e].fd_sync():8,fd_tell(e,t){let r=new DataView(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let{ret:n,offset:_}=a.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,n,_){let s=new DataView(a.inst.exports.memory.buffer),i=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let o=r.read_bytes_array(s,t,n),{ret:l,nwritten:c}=a.fds[e].fd_write(i,o);return s.setUint32(_,c,!0),l}return 8},path_create_directory(e,t,r){let n=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return a.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){let s=new DataView(a.inst.exports.memory.buffer),i=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:l,filestat:c}=a.fds[e].path_filestat_get(t,o);return null!=c&&c.write_bytes(s,_),l}return 8},path_filestat_set_times(e,t,r,n,_,s,i){let o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return a.fds[e].path_filestat_set_times(t,l,_,s,i)}return 8},path_link(e,t,r,n,_,s,i){let o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]&&null!=a.fds[_]){let l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),c=new TextDecoder(\"utf-8\").decode(o.slice(s,s+i));return a.fds[_].path_link(e,t,l,c)}return 8},path_open(e,t,r,n,_,s,i,o,l){let c=new DataView(a.inst.exports.memory.buffer),u=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let p=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n)),{ret:d,fd_obj:E}=a.fds[e].path_open(t,p,_,s,i,o);if(0!=d)return d;a.fds.push(E);let f=a.fds.length-1;return c.setUint32(l,f,!0),0}return 8},path_readlink(e,t,r,n,_,s){let i=new DataView(a.inst.exports.memory.buffer),o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let l=new TextDecoder(\"utf-8\").decode(o.slice(t,t+r)),{ret:c,data:u}=a.fds[e].path_readlink(l);if(null!=u){if(u.length>_)return i.setUint32(s,0,!0),8;o.set(u,n),i.setUint32(s,u.length,!0)}return c}return 8},path_remove_directory(e,t,r){let n=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return a.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){let s=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[r]){let i=new TextDecoder(\"utf-8\").decode(s.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(s.slice(n,n+_));return a.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){let n=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return a.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw\"exit with exit code \"+e},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){let r=new Uint8Array(a.inst.exports.memory.buffer);for(let n=0;nc(E,{tag:l.bK.BeforeUnload}))),c(E)}))},window.startDevClient=function(t){return e(this,void 0,void 0,(function*(){const r=new WebSocket(t),n=(t,_)=>e(this,void 0,void 0,(function*(){r.send(l.r.encode(t));const a=yield function(){return new Promise(((t,n)=>{const _=r.onmessage;r.onmessage=a=>e(this,void 0,void 0,(function*(){r.onmessage=_;try{const e=yield g(a.data),r=l.iI.decode(e);t(r)}catch(e){n(e)}}))}))}();yield E(a,_,n)}));r.onopen=e=>{const t=l.r.encode(l.f());r.send(t)},r.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield g(t.data);E(l.iI.decode(e),null,n)})),r.onerror=e=>{console.error(\"WebSocket error:\",e)},r.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}))}})()})();" diff --git a/src/Wasm/Compat/Marshal.hs b/src/Wasm/Compat/Marshal.hs deleted file mode 100644 index 9edb9b5..0000000 --- a/src/Wasm/Compat/Marshal.hs +++ /dev/null @@ -1,398 +0,0 @@ -{-# LANGUAGE PatternSynonyms #-} -{-# LANGUAGE CPP #-} -{-# LANGUAGE ForeignFunctionInterface #-} -{-# LANGUAGE MagicHash #-} -{-# LANGUAGE UnboxedTuples #-} -#if defined(wasm32_HOST_ARCH) -{-# LANGUAGE JavaScriptFFI #-} -#endif -module Wasm.Compat.Marshal where - -import Control.Monad -import Data.Maybe -import Data.String -import Data.Text qualified as Text -import Data.List qualified as List -import Data.Coerce -import Data.Kind -import Wasm.Compat.Prim -import GHC.Prim -import GHC.Ptr -import GHC.Int -import GHC.Generics as G -import GHC.IO -import Data.Text.Internal -import Data.Array.Byte -import Data.Word - -newtype Nullable v = Nullable {unNullable :: JSVal} - -nullableToMaybe :: Coercible v JSVal => Nullable v -> Maybe v -nullableToMaybe (Nullable j) - | js_isNull j > 0 = Nothing - | otherwise = Just (coerce j) - -maybeToNullable :: Coercible v JSVal => Maybe v -> Nullable v -maybeToNullable = Nullable . maybe js_null coerce - -newtype TypeResult = TypeResult {unTypeResult :: Int} - -pattern TypeNull, TypeBool, TypeNumber, TypeString, TypeArray, TypeObject :: TypeResult -pattern TypeNull = TypeResult 0 -pattern TypeBool = TypeResult 1 -pattern TypeNumber = TypeResult 2 -pattern TypeString = TypeResult 3 -pattern TypeArray = TypeResult 4 -pattern TypeObject = TypeResult 5 --------------------------------------------------------------------------------- - -instance IsString JSString where fromString = toJSString - -instance Semigroup JSString where (<>) = js_concatStr - -instance Monoid JSString where mempty = js_emptyStr - -instance Eq JSString where (==) a b = fromJSString a == fromJSString b - -instance Show JSString where show = show . fromJSString - -instance Ord JSString where compare a b = fromJSString a `compare` fromJSString b --------------------------------------------------------------------------------- - -class FromJSVal a where - fromJSVal :: JSVal -> IO (Maybe a) - default fromJSVal :: (Generic a, GFromJSVal (Rep a)) => JSVal -> IO (Maybe a) - fromJSVal = fmap (fmap G.to) . gFromJSVal - -class FromJSValPure v where fromJSValPure :: JSVal -> Maybe v - -instance {-# OVERLAPS #-} FromJSValPure v => FromJSVal v where - fromJSVal = pure . fromJSValPure - -instance FromJSValPure Int where - fromJSValPure j = case js_typeOf j of - TypeNumber -> Just (js_unsafeInt j) - _ -> Nothing - -instance FromJSValPure v => FromJSValPure (Maybe v) where - fromJSValPure j - = maybe (Just Nothing) fromJSValPure - $ nullableToMaybe (Nullable j) - -instance FromJSVal v => FromJSVal (Maybe v) where - fromJSVal j = maybe (pure (Just Nothing)) fromJSVal $ - nullableToMaybe (Nullable j) - -instance FromJSValPure JSVal where fromJSValPure = Just - -instance FromJSValPure JSString where - fromJSValPure j = case js_typeOf j of - TypeString -> Just (JSString j) - _ -> Nothing - -instance FromJSValPure Bool where - fromJSValPure j = case js_typeOf j of - TypeBool -> Just (js_unsafeBool j) - _ -> Nothing - -instance FromJSVal v => FromJSVal [v] where - fromJSVal s = case js_typeOf s of - TypeArray -> do - len <- js_arrayLength s - xs <- forM [0..(len - 1)] $ fromJSVal <=< js_arrayIndex s - return $ Just $ catMaybes xs - _ -> return Nothing - -instance FromJSVal Text where - fromJSVal j = case js_typeOf j of - TypeString -> fmap Just $ textFromJSString $ JSString j - _ -> pure Nothing - -instance (FromJSVal a, FromJSVal b) => FromJSVal (a, b) where - fromJSVal j = do - ma <- fromJSVal =<< js_arrayIndex j 0 - mb <- fromJSVal =<< js_arrayIndex j 1 - return $ liftA2 (,) ma mb - -instance (FromJSVal a, FromJSVal b, FromJSVal c) => FromJSVal (a, b, c) where - fromJSVal j = do - ma <- fromJSVal =<< js_arrayIndex j 0 - mb <- fromJSVal =<< js_arrayIndex j 1 - mc <- fromJSVal =<< js_arrayIndex j 2 - return $ (,,) <$> ma <*> mb <*> mc - --------------------------------------------------------------------------------- -class ToJSVal a where - toJSVal :: a -> IO JSVal - default toJSVal :: (Generic a, GToJSVal (Rep a)) => a -> IO JSVal - toJSVal = gToJSVal . G.from - -class ToJSValPure v where toJSValPure :: v -> JSVal - -instance {-# OVERLAPS #-} ToJSValPure v => ToJSVal v where - toJSVal = pure . toJSValPure - -instance ToJSValPure Int where toJSValPure = js_intJSVal - -instance ToJSValPure Bool where toJSValPure = js_boolJSVal - -instance ToJSValPure JSVal where toJSValPure j = j - -instance ToJSValPure JSString where toJSValPure (JSString j) = j - -instance ToJSVal v => ToJSVal (Maybe v) where - toJSVal = fmap (unNullable . maybeToNullable) . mapM toJSVal - -instance ToJSValPure v => ToJSValPure (Maybe v) where - toJSValPure = unNullable . maybeToNullable . fmap toJSValPure - -instance ToJSVal v => ToJSVal [v] where - toJSVal s = do - arr <- js_newEmptyArray - forM_ s $ toJSVal >=> js_arrayPush arr - return arr - -instance ToJSVal Text where - toJSVal = fmap (\(JSString j) -> j) . textToJSString - -instance (ToJSVal a, ToJSVal b) => ToJSVal (a, b) where - toJSVal (a, b) = do - ja <- toJSVal a - jb <- toJSVal b - toJSVal [ja, jb] - -instance (ToJSVal a, ToJSVal b, ToJSVal c) => ToJSVal (a, b, c) where - toJSVal (a, b, c) = do - ja <- toJSVal a - jb <- toJSVal b - jc <- toJSVal c - toJSVal [ja, jb, jc] - --------------------------------------------------------------------------------- - -class GFromJSVal (f :: Type -> Type) where - gFromJSVal :: JSVal -> IO (Maybe (f a)) - -instance GFromJSVal f => GFromJSVal (M1 m c f) where - gFromJSVal = fmap (fmap M1) . gFromJSVal @f - -instance GFromJSObject (x :*: y) => GFromJSVal (x :*: y) where - gFromJSVal kvs = gFromJSObject kvs - -instance {-# OVERLAPPING #-} FromJSVal a => GFromJSVal (S1 s (Rec0 a)) where - gFromJSVal = fmap (fmap (M1 . K1)) . fromJSVal @a --------------------------------------------------------------------------------- - -class GToJSVal (f :: Type -> Type) where - gToJSVal :: f x -> IO JSVal - -instance GToJSVal f => GToJSVal (M1 m c f) where - gToJSVal (M1 f) = gToJSVal f - -instance GToJSObject (x :*: y) => GToJSVal (x :*: y) where - gToJSVal (x :*: y) = do - o <- js_newObject - gToJSObject (x :*: y) o - return o - -instance {-# OVERLAPPING #-} (ToJSVal a) => GToJSVal (S1 s (Rec0 a)) where - gToJSVal (M1 (K1 a)) = toJSVal a --------------------------------------------------------------------------------- - -class GToJSObject (f :: Type -> Type) where - gToJSObject :: f x -> JSVal -> IO () - -instance (GToJSObject x, GToJSObject y) => GToJSObject (x :*: y) where - gToJSObject (x :*: y) o = gToJSObject x o >> gToJSObject y o - -instance (GToJSObject f) => GToJSObject (M1 m c f) where - gToJSObject (M1 a) o = gToJSObject a o - -instance {-# OVERLAPPING #-} (ToJSVal a, Selector s) => GToJSObject (S1 s (Rec0 a)) where - gToJSObject (M1 (K1 a)) o = do - v <- toJSVal a - js_assignProp o addr len v - where - key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) - !(Text (ByteArray arr) off len) = key - addr = Ptr (byteArrayContents# arr) `plusPtr` off - -class GFromJSObject (f :: Type -> Type) where - gFromJSObject :: JSVal -> IO (Maybe (f x)) - -instance (GFromJSObject x, GFromJSObject y) => GFromJSObject (x :*: y) where - gFromJSObject kvs = do - x <- gFromJSObject kvs - y <- gFromJSObject kvs - return $ liftA2 (:*:) x y - -instance (GFromJSObject f) => GFromJSObject (M1 m c f) where - gFromJSObject = fmap (fmap M1) . gFromJSObject - -instance {-# OVERLAPPING #-} (FromJSVal a, Selector s) => GFromJSObject (S1 s (Rec0 a)) where - gFromJSObject kvs = js_getProp kvs addr len >>= fmap (fmap (M1 . K1)) . fromJSVal - where - key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) - !(Text (ByteArray arr) off len) = key - addr = Ptr (byteArrayContents# arr) `plusPtr` off --------------------------------------------------------------------------------- - -textToJSString :: Text -> IO JSString -textToJSString (Text (ByteArray arr) off len) = do - let addr = byteArrayContents# arr - js_decodeUtf8 (Ptr addr `plusPtr` off) len - -textFromJSString :: JSString -> IO Text -textFromJSString j = IO \s0 -> - let (# s1, len@(I# len#) #) = unIO (js_stringLength j) s0 - (# s2, marr #) = newByteArray# (len# *# 3#) s1 - (# s3, tlen #) = unIO (js_encodeUtf8 j (Ptr (mutableByteArrayContents# marr)) len) s2 - (# s4, arr #) = unsafeFreezeByteArray# marr s3 - in (# s4, (Text (ByteArray arr) 0 tlen) #) - -newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} - deriving newtype (IsString, Semigroup, Monoid) - -evalJavaScript :: UnsafeJavaScript -> IO JSVal -evalJavaScript rjs = do - let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript - addr = byteArrayContents# arr - js_evalJavaScript (Ptr addr `plusPtr` off) len - -evalJavaScript1 :: ToJSVal arg0 => arg0 -> UnsafeJavaScript -> IO JSVal -evalJavaScript1 arg0 rjs = do - a0 <- toJSVal arg0 - let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript - addr = byteArrayContents# arr - js_evalJavaScript1 a0 (Ptr addr `plusPtr` off) len - -evalJavaScript2 :: (ToJSVal arg0, ToJSVal arg1) => arg0 -> arg1 -> UnsafeJavaScript -> IO JSVal -evalJavaScript2 arg0 arg1 rjs = do - a0 <- toJSVal arg0 - a1 <- toJSVal arg1 - let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript - addr = byteArrayContents# arr - js_evalJavaScript2 a0 a1 (Ptr addr `plusPtr` off) len - -evalJavaScript3 :: (ToJSVal arg0, ToJSVal arg1, ToJSVal arg2) => arg0 -> arg1 -> arg2 -> UnsafeJavaScript -> IO JSVal -evalJavaScript3 arg0 arg1 arg2 rjs = do - a0 <- toJSVal arg0 - a1 <- toJSVal arg1 - a2 <- toJSVal arg2 - let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript - addr = byteArrayContents# arr - js_evalJavaScript3 a0 a1 a2 (Ptr addr `plusPtr` off) len - -evalJavaScript4 :: (ToJSVal arg0, ToJSVal arg1, ToJSVal arg2, ToJSVal arg3) => arg0 -> arg1 -> arg2 -> arg3 -> UnsafeJavaScript -> IO JSVal -evalJavaScript4 arg0 arg1 arg2 arg3 rjs = do - a0 <- toJSVal arg0 - a1 <- toJSVal arg1 - a2 <- toJSVal arg2 - a3 <- toJSVal arg3 - let Text (ByteArray arr) off len = rjs.unUnsafeJavaScript - addr = byteArrayContents# arr - js_evalJavaScript4 a0 a1 a2 a3 (Ptr addr `plusPtr` off) len - -#if !defined(wasm32_HOST_ARCH) - -js_true :: JSVal = undefined -js_false :: JSVal = undefined -js_null :: JSVal = undefined -js_emptyStr :: JSString = undefined -js_isString :: JSVal -> JSVal = undefined -js_isNull :: JSVal -> Int = undefined -js_typeOf :: JSVal -> TypeResult = undefined -js_unsafeInt :: JSVal -> Int = undefined -js_unsafeBool :: JSVal -> Bool = undefined -js_intJSVal :: Int -> JSVal = undefined -js_boolJSVal :: Bool -> JSVal = undefined -js_concatStr :: JSString -> JSString -> JSString = undefined -js_newEmptyArray :: IO JSVal = undefined -js_arrayPush :: JSVal -> JSVal -> IO () = undefined -js_arrayLength :: JSVal -> IO Int = undefined -js_arrayIndex :: JSVal -> Int -> IO JSVal = undefined -js_decodeUtf8 :: Ptr Word8 -> Int -> IO JSString = undefined -js_encodeUtf8 :: JSString -> Ptr Word8 -> Int -> IO Int = undefined -js_stringLength :: JSString -> IO Int = undefined -js_evalJavaScript :: Ptr Word8 -> Int -> IO JSVal = undefined -js_evalJavaScript1 :: JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined -js_evalJavaScript2 :: JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined -js_evalJavaScript3 :: JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined -js_evalJavaScript4 :: JSVal -> JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined -js_getProp :: JSVal -> Ptr Word8 -> Int -> IO JSVal = undefined -js_assignProp :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () = undefined -js_newObject :: IO JSVal = undefined - -#else - -foreign import javascript unsafe - "true" js_true :: JSVal -foreign import javascript unsafe - "false" js_false :: JSVal -foreign import javascript unsafe - "null" js_null :: JSVal -foreign import javascript unsafe - "''" js_emptyStr :: JSString -foreign import javascript unsafe - "typeof $1 === 'string'" js_isString :: JSVal -> JSVal -foreign import javascript unsafe - "($1 === null || $1 === undefined)" js_isNull :: JSVal -> Int -foreign import javascript unsafe - "if ($1 === undefined || $1 === null) return 0;\ - if (typeof $1 === 'boolean') return 1;\ - if (typeof $1 === 'number') return 2;\ - if (typeof $1 === 'string') return 3;\ - if (Array.isArray($1)) return 4;\ - return 5;" js_typeOf :: JSVal -> TypeResult -foreign import javascript unsafe - "$1" js_unsafeInt :: JSVal -> Int -foreign import javascript unsafe - "$1" js_unsafeBool :: JSVal -> Bool -foreign import javascript unsafe - "$1" js_intJSVal :: Int -> JSVal -foreign import javascript unsafe - "($1 ? true : false)" js_boolJSVal :: Bool -> JSVal -foreign import javascript unsafe - "$1 + $2" js_concatStr :: JSString -> JSString -> JSString -foreign import javascript unsafe - "[]" js_newEmptyArray :: IO JSVal -foreign import javascript unsafe - "$1.push($2)" js_arrayPush :: JSVal -> JSVal -> IO () -foreign import javascript unsafe - "$1.length" js_arrayLength :: JSVal -> IO Int -foreign import javascript unsafe - "$1[$2]" js_arrayIndex :: JSVal -> Int -> IO JSVal -foreign import javascript unsafe - "(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)))" - js_decodeUtf8 :: Ptr Word8 -> Int -> IO JSString -foreign import javascript unsafe - "(new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written" - js_encodeUtf8 :: JSString -> Ptr Word8 -> Int -> IO Int -foreign import javascript unsafe - "$1.length" - js_stringLength :: JSString -> IO Int -foreign import javascript unsafe - "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)))" - js_evalJavaScript :: Ptr Word8 -> Int -> IO JSVal -foreign import javascript unsafe - "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3)))($1)" - js_evalJavaScript1 :: JSVal -> Ptr Word8 -> Int -> IO JSVal -foreign import javascript unsafe - "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $3, $4)))($1, $2)" - js_evalJavaScript2 :: JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal -foreign import javascript unsafe - "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $4, $5)))($1, $2, $3)" - js_evalJavaScript3 :: JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal -foreign import javascript unsafe - "eval(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $5, $6)))($1, $2, $3, $4)" - js_evalJavaScript4 :: JSVal -> JSVal -> JSVal -> JSVal -> Ptr Word8 -> Int -> IO JSVal -foreign import javascript unsafe - "$1[new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3))]" - js_getProp :: JSVal -> Ptr Word8 -> Int -> IO JSVal -foreign import javascript unsafe - "$1[new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $2, $3))] = $4;" - js_assignProp :: JSVal -> Ptr Word8 -> Int -> JSVal -> IO () -foreign import javascript unsafe - "{}" - js_newObject :: IO JSVal -#endif From 90bd43166a1c724f4b1324327b32ea637b037609 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sun, 31 Mar 2024 19:00:21 +0400 Subject: [PATCH 19/64] Hot reloading --- examples/charts/App.hs | 7 ++- examples/charts/Charts.hs | 5 +- examples/charts/PairSelector.hs | 2 +- examples/charts/charts.hs | 8 ++- examples/charts/dev-server.hs | 9 +++ htmlt.cabal | 11 ++-- jsbits/devserver.ts | 97 +++++++++++++++++++++++++++++++++ jsbits/ffi.ts | 33 +++++++++++ jsbits/index.js | 26 ++------- jsbits/jsffi.js | 3 +- jsbits/protocol.ts | 51 +---------------- src/Clickable/DOM.hs | 22 +++++++- src/Clickable/Internal.hs | 28 ++++------ src/Clickable/Main.hs | 12 ++-- src/Clickable/Main/DevServer.hs | 17 +++--- src/Clickable/Protocol.hs | 28 +--------- 16 files changed, 218 insertions(+), 141 deletions(-) create mode 100644 examples/charts/dev-server.hs create mode 100644 jsbits/devserver.ts diff --git a/examples/charts/App.hs b/examples/charts/App.hs index 5eefba5..12a50a3 100644 --- a/examples/charts/App.hs +++ b/examples/charts/App.hs @@ -35,10 +35,10 @@ html self = do text "Open Charts" on @"click" do inst <- Charts.new - modifyVar self.state_var $ const $ ChartsTab inst + modifyVar_ self.state_var $ const $ ChartsTab inst button_ do text "Open Help" - on @"click" $ modifyVar self.state_var $ const HelpTab + on @"click" $ modifyVar_ self.state_var $ const HelpTab button_ do text "Open Modal" on @"click" do @@ -50,7 +50,8 @@ html self = do on @"click" $ liftIO $ putMVar mvar "dljfhdlsfjh" syncPoint answer <- liftIO $ takeMVar mvar - consoleLog answer + -- consoleLog answer + return () dyn $ self.state_var `mapVar` \case ChartsTab inst -> Charts.html inst HelpTab -> p_ $ text diff --git a/examples/charts/Charts.hs b/examples/charts/Charts.hs index 3739063..702230e 100644 --- a/examples/charts/Charts.hs +++ b/examples/charts/Charts.hs @@ -44,12 +44,13 @@ html self = do button_ do text "Clickable this button" on @"click" do - modifyVar self.state_var \s -> s {counter = s.counter + 1 } + modifyVar_ self.state_var \s -> s {counter = s.counter + 1 } button_ do text "Print state" on @"click" do s <- readVar self.state_var - consoleLog $ Text.pack $ show s + -- consoleLog $ Text.pack $ show s + return () span_ [] $ dynText $ self.state_var `mapVar` \s -> "You clicked " <> Text.pack (show s.counter) <> " times" canvas_ [class_ "Charts-canvas"] $ return () diff --git a/examples/charts/PairSelector.hs b/examples/charts/PairSelector.hs index 35f49f7..6d01ac4 100644 --- a/examples/charts/PairSelector.hs +++ b/examples/charts/PairSelector.hs @@ -31,7 +31,7 @@ html self = do div_ [class_ "PairSelector-root"] do button_ do text "Select pair" - on @"click" $ modifyVar self \s -> case s.selected_pair of + on @"click" $ modifyVar_ self \s -> case s.selected_pair of Just _ -> s {selected_pair = Nothing} Nothing -> s {selected_pair = Just $ TradingPair "BTC" "USDT" "MEXC"} span_ $ dynText $ self `mapVar` \s -> s.selected_pair & maybe diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs index f50244a..310e418 100644 --- a/examples/charts/charts.hs +++ b/examples/charts/charts.hs @@ -1,11 +1,13 @@ import Control.Monad.Reader import Clickable +import GHC.Ptr +import GHC.Word import "this" App qualified as App main :: IO () main = return () -foreign export ccall wasm_main :: IO () -wasm_main = do - _ <- runApp $ lift App.new >>= App.html +foreign export ccall wasm_main :: Ptr Word8 -> IO () +wasm_main p = do + _ <- runApp p \_ -> attachToBody $ lift App.new >>= App.html return () diff --git a/examples/charts/dev-server.hs b/examples/charts/dev-server.hs new file mode 100644 index 0000000..40f5383 --- /dev/null +++ b/examples/charts/dev-server.hs @@ -0,0 +1,9 @@ +import Control.Monad.Reader +import Clickable.Main.DevServer +import Clickable +import GHC.Ptr +import GHC.Word +import "this" App qualified as App + +main :: IO () +main = runDebugDefault 8081 \_ _ -> attachToBody $ lift App.new >>= App.html diff --git a/htmlt.cabal b/htmlt.cabal index daaa4a9..85930e8 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -155,11 +155,14 @@ library executable htmlt-charts import: htmlt-common - main-is: charts.hs hs-source-dirs: ./examples/charts - ghc-options: - -no-hs-main -optl-mexec-model=reactor - -optl-Wl,--export=hs_init,--export=wasm_main,--export=malloc + if arch(wasm32) + ghc-options: + -no-hs-main -optl-mexec-model=reactor + -optl-Wl,--export=hs_init,--export=wasm_main,--export=malloc + main-is: charts.hs + else + main-is: dev-server.hs build-depends: base, htmlt, diff --git a/jsbits/devserver.ts b/jsbits/devserver.ts new file mode 100644 index 0000000..1dda3ed --- /dev/null +++ b/jsbits/devserver.ts @@ -0,0 +1,97 @@ +import { absurd } from './lib'; +import * as p from './protocol'; +import { HaskellMessage, JavaScriptMessage, JavaScriptMessageTag, HaskellMessageTag, Bindings, List } from './protocol'; + +export function startClient(devSocketUri: string, startFlags: unknown = null) { + const websocket = new WebSocket(devSocketUri); + + const sendToHaskell = async (jsMsg: JavaScriptMessage, argScope: List) => { + websocket.send(p.javascriptMessage.encode(jsMsg)); + const haskMsg = await awaitWebsocketMessage(); + await haskellApp(haskMsg, argScope, sendToHaskell); + }; + + websocket.onopen = (_event) => { + const startFlagsValue = p.unknownToValue(startFlags); + const binaryData = p.javascriptMessage.encode({ + tag: JavaScriptMessageTag.Start, + 0: startFlagsValue + }); + websocket.send(binaryData); + }; + + // Event handler for receiving messages from the server + websocket.onmessage = async (event) => { + const binaryDataReceived = await convertBlobToUint8Array(event.data); + const haskMsg = p.haskellMessage.decode(binaryDataReceived); + haskellApp(haskMsg, null, sendToHaskell); + }; + + // Event handler for errors + websocket.onerror = (event) => { + console.error("WebSocket error:", event); + }; + + // Event handler for when the connection is closed + websocket.onclose = (event) => { + console.log("WebSocket connection closed:", event); + }; + + function awaitWebsocketMessage(): Promise { + return new Promise((resolve, reject) => { + const prevCallback = websocket.onmessage; + websocket.onmessage = async (event) => { + websocket.onmessage = prevCallback; + try { + const binaryDataReceived = await convertBlobToUint8Array(event.data); + const haskMsg = p.haskellMessage.decode(binaryDataReceived); + resolve(haskMsg); + } catch (e) { reject(e) } + }; + }) + } +} + +export type HaskellAsyncCallback = (jsMsg: JavaScriptMessage, argScope: List) => Promise; + +export async function haskellApp ( + haskMsg: HaskellMessage, + argScope: List, + send: HaskellAsyncCallback +): Promise { + switch (haskMsg.tag) { + case HaskellMessageTag.EvalExpr: { + const result = p.evalExpr(send, globalContext, argScope, haskMsg.expr); + const jvalue = p.unknownToValue(result); + return send({ tag: JavaScriptMessageTag.Return, 0: jvalue }, argScope); + } + case HaskellMessageTag.HotReload: { + window.location.reload(); + return; + } + case HaskellMessageTag.Halt: { + return; + } + } + absurd(haskMsg); +} + +const globalContext: List = [window as any, null] + +export function convertBlobToUint8Array(blob: Blob): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = () => { + const arrayBuffer = reader.result as ArrayBuffer; + const uint8Array = new Uint8Array(arrayBuffer); + resolve(uint8Array); + }; + + reader.onerror = (error) => { + reject(error); + }; + + reader.readAsArrayBuffer(blob); + }); +} diff --git a/jsbits/ffi.ts b/jsbits/ffi.ts index b9e1db5..e367626 100644 --- a/jsbits/ffi.ts +++ b/jsbits/ffi.ts @@ -1,3 +1,6 @@ +import { WASI, File, OpenFile } from '@bjorn3/browser_wasi_shim'; +// @ts-ignore +import * as jsffi from './jsffi'; import * as p from './protocol'; import { JavaScriptMessage, HaskellMessageTag, List, JavaScriptMessageTag } from './protocol'; @@ -5,6 +8,7 @@ export type HaskellPointer = number; export type HaskellExports = { hs_init: () => void; + wasm_main: (flags: HaskellPointer) => void; malloc: (size: number) => HaskellPointer; memory: WebAssembly.Memory; }; @@ -66,3 +70,32 @@ export function evalMessageFFI(javascriptMessageCallback: SendMessageCallback, e } } } + +let __exports: HaskellExports = {} as any; + +export async function startWasm(wasmUri: string, startFlags: unknown = null) { + const wasi = new WASI([], [], [ + new OpenFile(new File([])), // stdin + new OpenFile(new File([])), // stdout + new OpenFile(new File([])), // stderr + ]); + + const wasm = await WebAssembly.compileStreaming(fetch(wasmUri)); + const inst = await WebAssembly.instantiate(wasm, { + wasi_snapshot_preview1: wasi.wasiImport, + ghc_wasm_jsffi: jsffi.default(__exports) + }); + + Object.assign(__exports, inst.exports); + // @ts-ignore + wasi.initialize(inst); + // @ts-ignore + await inst.exports.hs_init(); + + const startFlagsValue = p.unknownToValue(startFlags); + const startFlagsBuffer = p.jvalue.encode(startFlagsValue); + const startFlagsPtr = storeBuffer(__exports, startFlagsBuffer); + + // @ts-ignore + await inst.exports.wasm_main(startFlagsPtr); +}; diff --git a/jsbits/index.js b/jsbits/index.js index 02d3edf..ee2361c 100644 --- a/jsbits/index.js +++ b/jsbits/index.js @@ -1,23 +1,5 @@ -import { WASI, File, OpenFile } from '@bjorn3/browser_wasi_shim'; -import * as jsffi from './jsffi'; +import * as ffi from './ffi'; +import * as devserver from './devserver'; -let __exports = {}; - -window.startReactor = async function (wasmUri, opt) { - const wasi = new WASI([], [], [ - new OpenFile(new File([])), // stdin - new OpenFile(new File([])), // stdout - new OpenFile(new File([])), // stderr - ]); - - const wasm = await WebAssembly.compileStreaming(fetch(wasmUri)); - const inst = await WebAssembly.instantiate(wasm, { - wasi_snapshot_preview1: wasi.wasiImport, - ghc_wasm_jsffi: jsffi.default(__exports) - }); - - Object.assign(__exports, inst.exports); - await wasi.initialize(inst); - await inst.exports.hs_init(); - await inst.exports.wasm_main(); -}; +window.startWasm = ffi.startWasm; +window.startClient = devserver.startClient; diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index 489c32c..675bbfc 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -101,8 +101,7 @@ getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => (evalMessageFFI($1, __exports, $2)), -ZC9ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, +ZC2ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => (evalMessageFFI($1, __exports, $2)), ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index 628f933..a96ad79 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -332,36 +332,6 @@ export const jvalue = b.recursive(self => b.discriminate({ [ValueTag.Uint8Array]: b.record({ 0: b.u8array }), })); -export type StartLocation = { - protocol: string, - hostname: string, - port: string, - pathname: string, - search: string, - hash: string, -}; - -export const startLocation: b.Decoder = b.record({ - protocol: b.string, - hostname: b.string, - port: b.string, - pathname: b.string, - search: b.string, - hash: b.string, -}); - -export type StartFlags = { - initial_url: StartLocation; - window_inner_size: [number, number]; - devserver_connection_id: Maybe; -}; - -export const startFlags: b.Decoder = b.record({ - initial_url: startLocation, - window_inner_size: b.tuple(b.int64, b.int64), - devserver_connection_id: b.maybe(b.int64), -}); - export enum ExprTag { Null, Boolean, @@ -540,7 +510,7 @@ export enum JavaScriptMessageTag { } export const javascriptMessage = b.discriminate({ - [JavaScriptMessageTag.Start]: b.record({ startFlags }), + [JavaScriptMessageTag.Start]: b.record({ 0: jvalue }), [JavaScriptMessageTag.Return]: b.record({ 0: jvalue }), [JavaScriptMessageTag.TriggerCallback]: b.record({ arg: jvalue, callbackId: b.int64 }), [JavaScriptMessageTag.BeforeUnload]: b.record({}), @@ -555,25 +525,6 @@ export type VarId = number; export const varStorage = new Map>(); export const finalizers = new Map>; -export function mkStartMessage(): JavaScriptMessage { - const initial_url: StartLocation = { - protocol: location.protocol, - hostname: location.hostname, - port: location.port, - pathname: location.pathname, - search: location.search, - hash: location.hash, - }; - return { - tag: JavaScriptMessageTag.Start, - startFlags: { - initial_url, - window_inner_size: [window.innerWidth, window.innerHeight], - devserver_connection_id: { tag: MaybeTag.Nothing }, - } - }; -} - namespace domHelpers { export function insertIntoBuilder(builder: Element|Comment, child: Node): void { if (builder instanceof Comment) { diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index 40b4f34..c4f29b4 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -10,7 +10,7 @@ import Unsafe.Coerce import Clickable.Types import Clickable.Protocol -import Clickable.Protocol.Value (Value, FromJSValue(..)) +import Clickable.Protocol.Value (Value, FromJSValue(..), ToJSValue(..)) import Clickable.Internal @@ -214,6 +214,26 @@ normalEventWrapper eventName opt = preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" +data Location = Location + { protocol :: Text + -- ^ A string containing the protocol scheme of the URL, including + -- the final ':' + , hostname :: Text + -- ^ A string containing the domain of the URL. + , port :: Text + -- ^ A string containing the port number of the URL. + , pathname :: Text + -- ^ A string containing an initial '/' followed by the path of the + -- URL, not including the query string or fragment. + , search :: Text + -- ^ A string containing a '?' followed by the parameters or + -- "querystring" of the URL + , hash :: Text + -- ^ A string containing a '#' followed by the fragment identifier + -- of the URL. + } deriving stock (Show, Eq, Generic) + deriving anyclass (FromJSValue, ToJSValue) + -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event popstateConnectArgs :: ConnectResourceArgs (Location -> ClickM ()) popstateConnectArgs = ConnectResourceArgs diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index b1fb75a..1d810c8 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -3,6 +3,7 @@ module Clickable.Internal where import Control.Monad.Reader import Control.Monad.State import Data.Binary qualified as Binary +import Data.Binary (Binary) import Data.Foldable import Data.ByteString as BS import Data.ByteString.Lazy qualified as BSL @@ -27,9 +28,9 @@ emptyInternalState = InternalState [] [] Map.empty [] 0 newInternalEnv :: IO InternalEnv newInternalEnv = mdo - let scope = ResourceScope emptyInternalState.next_id - internal_state_ref <- newIORef emptyInternalState - {next_id = emptyInternalState.next_id + 1} + let state = emptyInternalState + let scope = ResourceScope state.next_id + internal_state_ref <- newIORef state {next_id = state.next_id + 1} receiveCb <- FFI.js_exportCallback $ receiveMessage env let env = InternalEnv {internal_state_ref, scope, send_message = sendMessage receiveCb} return env @@ -136,7 +137,6 @@ receiveMessage e jptr = do jbytes <- loadByteString jptr let jmsg = Binary.decode $ BSL.fromStrict jbytes case jmsg of - Start _startFlags -> return () Return _value -> return () TriggerCallbackMsg arg sourceId -> launchClickM e $ modify (unsafeTrigger sourceId arg) @@ -197,15 +197,11 @@ data ClientMessage -- DevServer instance (useful for delivering notifications under -- devserver) -handleMessage :: InternalEnv -> (StartFlags -> ClickM ()) -> ClientMessage -> IO HaskellMessage -handleMessage e jsMain = \case - BrowserMessage (Start startFlags) -> do - launchClickM e $ jsMain startFlags - return Halt - BrowserMessage (Return _val) -> return Halt - BrowserMessage (TriggerCallbackMsg arg sourceId) -> do - launchClickM e $ modify (unsafeTrigger sourceId arg) - return Halt - BrowserMessage BeforeUnload -> - return Halt - DevServerMessage a -> Halt <$ launchClickM e a +loadMessage :: Binary msg => Ptr a -> IO msg +loadMessage = fmap (Binary.decode . BSL.fromStrict) . loadByteString + where + loadByteString :: Ptr a -> IO ByteString + loadByteString ptr = do + len <- peek @Word64 (castPtr ptr) + let contentPtr = ptr `plusPtr` 8 + BSU.unsafePackCStringFinalizer contentPtr (fromIntegral len) (Alloc.free ptr) diff --git a/src/Clickable/Main.hs b/src/Clickable/Main.hs index 0207976..925714a 100644 --- a/src/Clickable/Main.hs +++ b/src/Clickable/Main.hs @@ -3,8 +3,11 @@ module Clickable.Main where import GHC.Generics import Clickable.Core import Clickable.Types -import Clickable.Internal (newInternalEnv) +import Clickable.Internal +import Clickable.Protocol import Wasm.Compat.Prim +import Data.Word +import GHC.Ptr -- data AttachOptions = AttachOptions -- { internal_env :: InternalEnv @@ -24,10 +27,11 @@ data RunningApp = RunningApp -- let runApp = RunningApp opt.internal_env domBracket -- return (result, runApp) -runApp :: HtmlM a -> IO a -runApp app = do +runApp :: Ptr Word8 -> (StartFlags -> ClickM a) -> IO a +runApp p app = do env <- newInternalEnv - launchClickM env $ attachToBody app <* syncPoint + startFlags <- loadMessage p + launchClickM env $ app startFlags <* syncPoint -- detach :: RunningApp -> IO () -- detach app = do diff --git a/src/Clickable/Main/DevServer.hs b/src/Clickable/Main/DevServer.hs index 163cfca..da0d786 100644 --- a/src/Clickable/Main/DevServer.hs +++ b/src/Clickable/Main/DevServer.hs @@ -1,4 +1,4 @@ -module Clickable.DevServer where +module Clickable.Main.DevServer where import Control.Concurrent import Control.Concurrent.Async @@ -150,7 +150,7 @@ defaultHtmlTemplate devSocket = \ \n\ \ \n\ \ \n\ \\n\ @@ -185,16 +185,19 @@ devserverWebsocket opt p = case raceResult of Left (Right (incomingBytes::ByteString)) -> do let jsMessage = Binary.decode . BSL.fromStrict $ incomingBytes - reader connInfo $ BrowserMessage jsMessage + reader connInfo runningApp $ BrowserMessage jsMessage loop connInfo Left (Left (_::ConnectionException)) -> return () Right jsAction -> do - reader connInfo $ DevServerMessage jsAction + reader connInfo runningApp $ DevServerMessage jsAction loop connInfo - reader :: ConnectionInfo -> ClientMessage -> IO () - reader conn = \case + reader :: ConnectionInfo -> RunningApp -> ClientMessage -> IO () + reader conn app = \case + BrowserMessage (Start flags) -> do + modifyIORef' conn.queue_ref (app.client_app conn flags:) + putMVar conn.signal_mvar () BrowserMessage (Return val) -> putMVar conn.return_mvar val BrowserMessage (TriggerCallbackMsg arg sourceId) -> do modifyIORef' conn.queue_ref (modify (Internal.unsafeTrigger sourceId arg):) @@ -330,4 +333,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={268:(e,t,r)=>{r.d(t,{BE:()=>m,IM:()=>D,IX:()=>h,Z_:()=>y,a0:()=>T,a2:()=>x,bc:()=>O,cS:()=>M});var n=r(849);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return g(this,r,0,e),r}decode(e){const[t,r]=f(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class l extends _{constructor(e){super(),this._element=e}}class c extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class p extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof o){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof i)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof c){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return b(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof p)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.R)(e)}function f(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof i){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=f(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=b(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=f(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof p)return f(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=f(e,t,n);return n=_,r})),n]}return(0,n.R)(e)}function g(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof o){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof i){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=g(e,t,a,n[r])})),a}return(0,n.R)(e)}function b(e){return Math.ceil(Math.log2(e)/8)}const M=new a,x=new s,y=new o;function h(e){return new l(e)}function D(e){return new c(e)}function T(e){return new u(e)}function O(...e){return new d(e)}function m(e){const t=new p(void 0),r=e(t);return t._self=r,r}new i},849:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{R:()=>n})},741:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Ub:()=>HaskellMessageTag,Xq:()=>unknownToJValue,bK:()=>JavaScriptMessageTag,f:()=>mkStartMessage,iI:()=>haskellMessage,r:()=>javascriptMessage,sN:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(268),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(849),JValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(idenScope,argScope,hscb,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.Num:return Number(exp.decimal);case ExprTag.Str:return exp[0];case ExprTag.Arr:return exp[0].map(evalExpr.bind(void 0,idenScope,argScope,hscb));case ExprTag.Obj:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(idenScope,argScope,hscb,t)])));case ExprTag.Dot:{const e=evalExpr(idenScope,argScope,hscb,exp[0]);return e[exp[1]]}case ExprTag.AssignProp:{const e=evalExpr(idenScope,argScope,hscb,exp[2]),t=evalExpr(idenScope,argScope,hscb,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(idenScope,argScope,hscb,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=evalExpr(idenScope,argScope,hscb,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=evalExpr(idenScope,argScope,hscb,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=evalExpr(idenScope,argScope,hscb,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=evalExpr(idenScope,argScope,hscb,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(idenScope,Cons(arguments,argScope),hscb,exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(idenScope,argScope,hscb,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,idenScope,argScope,hscb)))}case ExprTag.Call:{const e=evalExpr(idenScope,argScope,hscb,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,idenScope,argScope,hscb)))}case ExprTag.AssignVar:{const e=evalExpr(idenScope,argScope,hscb,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:return;case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:return varStorage.delete(exp.scopeId);case ExprTag.InsertNode:{const e=evalExpr(idenScope,argScope,hscb,exp.parent),t=evalExpr(idenScope,argScope,hscb,exp.child);return domBuilder.insertIntoBuilder(e,t),null}case ExprTag.WithDomBuilder:{const e=evalExpr(idenScope,argScope,hscb,exp.builder),t=evalExpr(idenScope,argScope,hscb,exp.builderContent);return t(e),e}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(idenScope,argScope,hscb,exp.node),t=evalExpr(idenScope,argScope,hscb,exp.propValue);return domBuilder.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(idenScope,argScope,hscb,exp.node);return domBuilder.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.AddEventListener:{const e=evalExpr(idenScope,argScope,hscb,exp.node),t=evalExpr(idenScope,argScope,hscb,exp.listener);return domBuilder.addEventListener(e,exp.eventName,t),null}case ExprTag.ToggleClass:{const e=evalExpr(idenScope,argScope,hscb,exp.node);return domBuilder.toggleClass(e,exp.className,Boolean(exp.enable)),null}case ExprTag.AssignText:{const e=evalExpr(idenScope,argScope,hscb,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(idenScope,argScope,hscb,exp.parent);return domBuilder.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(idenScope,argScope,hscb,exp.boundary);return domBuilder.clearBoundary(e,Boolean(exp.detach))}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(idenScope,argScope,hscb,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerEvent:{const e=evalExpr(idenScope,argScope,hscb,exp.arg),t={tag:JavaScriptMessageTag.TriggerEvent,arg:unknownToJValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.AsyncCallback:{const e=evalExpr(idenScope,argScope,hscb,exp.arg),t={tag:JavaScriptMessageTag.AsyncCallback,arg:unknownToJValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.R)(exp)}function unknownToJValue(e){if(\"boolean\"==typeof e)return{tag:JValueTag.JBool,0:e?1:0};if(\"number\"==typeof e){const t=e.toString();return{tag:JValueTag.JNum,decimal:t}}if(\"string\"==typeof e)return{tag:JValueTag.JStr,0:e};if(Array.isArray(e))return{tag:JValueTag.JArr,0:e.map(unknownToJValue)};if(null==e)return{tag:JValueTag.JNull};const t=Object.entries(e).map((([e,t])=>[e,unknownToJValue(t)]));return{tag:JValueTag.JObj,0:t}}!function(e){e[e.JObj=0]=\"JObj\",e[e.JArr=1]=\"JArr\",e[e.JStr=2]=\"JStr\",e[e.JNum=3]=\"JNum\",e[e.JBool=4]=\"JBool\",e[e.JNull=5]=\"JNull\"}(JValueTag||(JValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.BE((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.a0({[JValueTag.JObj]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(_binary__WEBPACK_IMPORTED_MODULE_0__.bc(_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,e))}),[JValueTag.JArr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[JValueTag.JStr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[JValueTag.JNum]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({decimal:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[JValueTag.JBool]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[JValueTag.JNull]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({})}))),startLocation=_binary__WEBPACK_IMPORTED_MODULE_0__.IM({protocol:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,hostname:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,port:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,pathname:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,search:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,hash:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),startFlags=_binary__WEBPACK_IMPORTED_MODULE_0__.IM({initial_url:startLocation,window_inner_size:_binary__WEBPACK_IMPORTED_MODULE_0__.bc(_binary__WEBPACK_IMPORTED_MODULE_0__.a2,_binary__WEBPACK_IMPORTED_MODULE_0__.a2)});var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.Num=2]=\"Num\",e[e.Str=3]=\"Str\",e[e.Arr=4]=\"Arr\",e[e.Obj=5]=\"Obj\",e[e.Dot=6]=\"Dot\",e[e.AssignProp=7]=\"AssignProp\",e[e.Ix=8]=\"Ix\",e[e.Add=9]=\"Add\",e[e.Subtract=10]=\"Subtract\",e[e.Multiply=11]=\"Multiply\",e[e.Divide=12]=\"Divide\",e[e.Id=13]=\"Id\",e[e.Lam=14]=\"Lam\",e[e.Arg=15]=\"Arg\",e[e.Apply=16]=\"Apply\",e[e.Call=17]=\"Call\",e[e.AssignVar=18]=\"AssignVar\",e[e.FreeVar=19]=\"FreeVar\",e[e.Var=20]=\"Var\",e[e.FreeScope=21]=\"FreeScope\",e[e.InsertNode=22]=\"InsertNode\",e[e.WithDomBuilder=23]=\"WithDomBuilder\",e[e.CreateElement=24]=\"CreateElement\",e[e.CreateElementNS=25]=\"CreateElementNS\",e[e.CreateText=26]=\"CreateText\",e[e.ElementProp=27]=\"ElementProp\",e[e.ElementAttr=28]=\"ElementAttr\",e[e.AddEventListener=29]=\"AddEventListener\",e[e.ToggleClass=30]=\"ToggleClass\",e[e.AssignText=31]=\"AssignText\",e[e.InsertBoundary=32]=\"InsertBoundary\",e[e.ClearBoundary=33]=\"ClearBoundary\",e[e.RevSeq=34]=\"RevSeq\",e[e.Eval=35]=\"Eval\",e[e.TriggerEvent=36]=\"TriggerEvent\",e[e.AsyncCallback=37]=\"AsyncCallback\",e[e.UncaughtException=38]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.BE((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.a0({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[ExprTag.Num]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({decimal:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.Str]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[ExprTag.Obj]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(_binary__WEBPACK_IMPORTED_MODULE_0__.bc(_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.AssignProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.cS,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,2:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({parent:e,child:e}),[ExprTag.WithDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({builder:e,builderContent:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,eventName:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,listener:e}),[ExprTag.ToggleClass]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,className:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_,enable:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[ExprTag.AssignText]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.cS}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.IX(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_}),[ExprTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,arg:e}),[ExprTag.AsyncCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Z_})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.Yield=1]=\"Yield\",e[e.HotReload=2]=\"HotReload\",e[e.Exit=3]=\"Exit\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.a0({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({expr}),[HaskellMessageTag.Yield]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({}),[HaskellMessageTag.Exit]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerEvent=2]=\"TriggerEvent\",e[e.AsyncCallback=3]=\"AsyncCallback\",e[e.BeforeUnload=4]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.a0({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({startFlags}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({0:jvalue}),[JavaScriptMessageTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[JavaScriptMessageTag.AsyncCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.a2}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.IM({})}),varStorage=new Map;function mkStartMessage(){const e={protocol:location.protocol,hostname:location.hostname,port:location.port,pathname:location.pathname,search:location.search,hash:location.hash};return{tag:JavaScriptMessageTag.Start,startFlags:{initial_url:e,window_inner_size:[window.innerWidth,window.innerHeight]}}}var domBuilder;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.toggleClass=function(e,t,n){const _=r(e);n?_.classList.add(t):_.classList.remove(t)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))}}(domBuilder||(domBuilder={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}Object.create,Object.create,\"function\"==typeof SuppressedError&&SuppressedError;class t{static read_bytes(e,r){let n=new t;return n.buf=e.getUint32(r,!0),n.buf_len=e.getUint32(r+4,!0),n}static read_bytes_array(e,r,n){let _=[];for(let a=0;athis.file.size){let e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class i{open(e){let t=new s(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new _(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}var o=__webpack_require__(849),l=__webpack_require__(741);function c(e,t,r=null){const n=t||l.f(),_=function(e,t){const r=function(e,t){const r=t.byteLength,n=e.exports.hs_malloc(t.length+8);return new DataView(e.exports.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.exports.memory.buffer,n+8,r).set(t),n}(e,l.r.encode(t)),n=function(e,t){const r=new Uint8Array(e.exports.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.exports.memory.buffer,t+8,n).slice().buffer;return e.exports.hs_free(t),new Uint8Array(_)}(e,e.exports.app(r));return l.iI.decode(n)}(e,n),a=(t,r)=>{c(e,t,r)};switch(_.tag){case l.Ub.EvalExpr:{const t=l.sN(u,r,a,_.expr),n=l.Xq(t);return c(e,{tag:l.bK.Return,0:n},r)}case l.Ub.Yield:return void l.sN(u,r,a,_.expr);case l.Ub.HotReload:return void window.location.reload();case l.Ub.Exit:return}(0,o.R)(_)}const u=[window,null];class p extends s{constructor(e,t){super(e),this.printDebug=t}fd_write(e,t){const r=super.fd_write(e,t);return t.forEach((r=>{this.printDebug(e.subarray(t[0].buf,r.buf+r.buf_len))})),r}}function d(e){let t=[];return r=>{const n=r=>{if(0==r.byteLength)return;const _=r.findIndex((e=>e==\"\\n\".charCodeAt(0)));if(_>=0){const a=t.map((e=>new TextDecoder(\"utf8\").decode(e))).join(\"\");t=[];const s=new TextDecoder(\"utf8\").decode(r.subarray(0,_));e(a+s),n(r.subarray(_+1))}else t.push(r.slice())};n(r)}}function E(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case l.Ub.EvalExpr:{const e=l.sN(f,r,n,t.expr),_=l.Xq(e);return n({tag:l.bK.Return,0:_},r)}case l.Ub.Yield:return void l.sN(f,r,n,t.expr);case l.Ub.HotReload:return void window.location.reload();case l.Ub.Exit:return}(0,o.R)(t)}))}const f=[window,null];function g(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startReactor=function(n,_={}){return e(this,void 0,void 0,(function*(){const e=d(console.log),a=d(console.log),o=new class{start(e){this.inst=e,e.exports._start()}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,n,_){this.args=[],this.env=[],this.fds=[],this.args=e,this.env=n,this.fds=_;let a=this;this.wasiImport={args_sizes_get(e,t){let r=new DataView(a.inst.exports.memory.buffer);r.setUint32(e,a.args.length,!0);let n=0;for(let e of a.args)n+=e.length+1;return r.setUint32(t,n,!0),0},args_get(e,t){let r=new DataView(a.inst.exports.memory.buffer),n=new Uint8Array(a.inst.exports.memory.buffer);for(let _=0;_null!=a.fds[e]?a.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=a.fds[e]?a.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=a.fds[e]){let t=a.fds[e].fd_close();return a.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=a.fds[e]?a.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=a.fds[e]){let{ret:r,fdstat:n}=a.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(a.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=a.fds[e]?a.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=a.fds[e]?a.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=a.fds[e]){let{ret:r,filestat:n}=a.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(a.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=a.fds[e]?a.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=a.fds[e]?a.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,r,n,_,s){let i=new DataView(a.inst.exports.memory.buffer),o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let l=t.read_bytes_array(i,r,n),{ret:c,nread:u}=a.fds[e].fd_pread(o,l,_);return i.setUint32(s,u,!0),c}return 8},fd_prestat_get(e,t){let r=new DataView(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let{ret:n,prestat:_}=a.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=a.fds[e]){let{ret:r,prestat_dir_name:n}=a.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(a.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,n,_,s){let i=new DataView(a.inst.exports.memory.buffer),o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let l=r.read_bytes_array(i,t,n),{ret:c,nwritten:u}=a.fds[e].fd_pwrite(o,l,_);return i.setUint32(s,u,!0),c}return 8},fd_read(e,r,n,_){let s=new DataView(a.inst.exports.memory.buffer),i=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let o=t.read_bytes_array(s,r,n),{ret:l,nread:c}=a.fds[e].fd_read(i,o);return s.setUint32(_,c,!0),l}return 8},fd_readdir(e,t,r,n,_){let s=new DataView(a.inst.exports.memory.buffer),i=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let o=0;for(;;){let{ret:l,dirent:c}=a.fds[e].fd_readdir_single(n);if(0!=l)return s.setUint32(_,o,!0),l;if(null==c)break;if(r-onull!=a.fds[e]?a.fds[e].fd_sync():8,fd_tell(e,t){let r=new DataView(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let{ret:n,offset:_}=a.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,n,_){let s=new DataView(a.inst.exports.memory.buffer),i=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let o=r.read_bytes_array(s,t,n),{ret:l,nwritten:c}=a.fds[e].fd_write(i,o);return s.setUint32(_,c,!0),l}return 8},path_create_directory(e,t,r){let n=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return a.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){let s=new DataView(a.inst.exports.memory.buffer),i=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:l,filestat:c}=a.fds[e].path_filestat_get(t,o);return null!=c&&c.write_bytes(s,_),l}return 8},path_filestat_set_times(e,t,r,n,_,s,i){let o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return a.fds[e].path_filestat_set_times(t,l,_,s,i)}return 8},path_link(e,t,r,n,_,s,i){let o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]&&null!=a.fds[_]){let l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),c=new TextDecoder(\"utf-8\").decode(o.slice(s,s+i));return a.fds[_].path_link(e,t,l,c)}return 8},path_open(e,t,r,n,_,s,i,o,l){let c=new DataView(a.inst.exports.memory.buffer),u=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let p=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n)),{ret:d,fd_obj:E}=a.fds[e].path_open(t,p,_,s,i,o);if(0!=d)return d;a.fds.push(E);let f=a.fds.length-1;return c.setUint32(l,f,!0),0}return 8},path_readlink(e,t,r,n,_,s){let i=new DataView(a.inst.exports.memory.buffer),o=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let l=new TextDecoder(\"utf-8\").decode(o.slice(t,t+r)),{ret:c,data:u}=a.fds[e].path_readlink(l);if(null!=u){if(u.length>_)return i.setUint32(s,0,!0),8;o.set(u,n),i.setUint32(s,u.length,!0)}return c}return 8},path_remove_directory(e,t,r){let n=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return a.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){let s=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[r]){let i=new TextDecoder(\"utf-8\").decode(s.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(s.slice(n,n+_));return a.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){let n=new Uint8Array(a.inst.exports.memory.buffer);if(null!=a.fds[e]){let _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return a.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw\"exit with exit code \"+e},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){let r=new Uint8Array(a.inst.exports.memory.buffer);for(let n=0;nc(E,{tag:l.bK.BeforeUnload}))),c(E)}))},window.startDevClient=function(t){return e(this,void 0,void 0,(function*(){const r=new WebSocket(t),n=(t,_)=>e(this,void 0,void 0,(function*(){r.send(l.r.encode(t));const a=yield function(){return new Promise(((t,n)=>{const _=r.onmessage;r.onmessage=a=>e(this,void 0,void 0,(function*(){r.onmessage=_;try{const e=yield g(a.data),r=l.iI.decode(e);t(r)}catch(e){n(e)}}))}))}();yield E(a,_,n)}));r.onopen=e=>{const t=l.r.encode(l.f());r.send(t)},r.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield g(t.data);E(l.iI.decode(e),null,n)})),r.onerror=e=>{console.error(\"WebSocket error:\",e)},r.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}))}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>x,Gk:()=>y,PV:()=>w,Tf:()=>O,YE:()=>m,YO:()=>M,Yj:()=>T,b9:()=>D,g1:()=>P,tB:()=>C});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class d extends _{constructor(e){super(),this._self=e}}class f extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return h(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof d)return E(e._self,t);if(e instanceof f){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=h(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof d)return g(e._self,t,r);if(e instanceof f){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function h(e){return Math.ceil(Math.log2(e)/8)}const m=new a,y=new s,x=new i,T=new c,D=new o;function M(e){return new l(e)}function P(e){return new p(e)}function O(e){return new u(e)}function w(...e){return new f(e)}function C(e){const t=new d(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,i1:()=>jvalue,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Add=11]=\"Add\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const d=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(d);const{ret:f,fd_obj:E}=o.fds[e].path_open(t,d,_,a,i,c);if(0!=f)return f;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class d{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class f{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new f;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new d,r=new FinalizationRegistry((t=>e.rts_freeStablePtr(t)));return{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>r=>e.ghczuwasmzujsffiZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC(t,r),ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>function(e,t,r){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(t,r),_=g.sy.decode(n),a=(r,n)=>{const _=g.bR.encode(r),a=b(t,_);e(a)};switch(_.tag){case g.I4.EvalExpr:{const e=g.wL(a,[globalThis,null],null,_.expr),r={tag:g.dB.Return,0:g.bp(e)},n=g.bR.encode(r);return b(t,n)}case g.I4.HotReload:{window.location.reload();const e={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(e);return b(t,r)}case g.I4.Halt:{const e={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(e);return b(t,r)}}}(t,e,r),ZC9ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC:(e,t)=>e.reject(new WebAssembly.RuntimeError(t)),ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC:e=>e.resolve(),ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC:()=>{let e,t;const r=new Promise(((r,n)=>{e=r,t=n}));return r.resolve=e,r.reject=t,r},ZC21ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC:(e,t)=>r.register(e,t,e),ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:e=>`${e.stack?e.stack:e}`,ZC1ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:(t,r)=>new TextDecoder(\"utf-8\",{fatal:!0}).decode(new Uint8Array(e.memory.buffer,t,r)),ZC2ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:(t,r,n)=>(new TextEncoder).encodeInto(t,new Uint8Array(e.memory.buffer,r,n)).written,ZC3ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:e=>e.length,ZC4ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:e=>{if(!r.unregister(e))throw new WebAssembly.RuntimeError(\"js_callback_unregister\")},ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziConcziInternalZC:async e=>new Promise((t=>setTimeout(t,e/1e3))),ZC18ZCghczminternalZCGHCziInternalziWasmziPrimziImportsZC:(t,r)=>t.then((()=>e.rts_promiseResolveUnit(r)),(t=>e.rts_promiseReject(r,t)))}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let h={};var m=__webpack_require__(366);function y(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,x,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,m.G)(t)}))}const x=[window,null];function T(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(h)}),a=g.bp(t),s=g.i1.encode(a),i=b(h,s);Object.assign(h,_.exports),r.initialize(_),yield _.exports.hs_init(),yield _.exports.wasm_main(i)}))},window.startClient=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield T(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield y(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield T(t.data);y(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index 0e74087..ab99367 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -31,32 +31,8 @@ data JavaScriptMessage deriving stock (Generic, Show) deriving anyclass (Binary) -data StartFlags = StartFlags - { initial_url :: Location - , window_inner_size :: (Int64, Int64) - , devserver_connection_id :: Maybe Int64 - } deriving stock (Generic, Show) - deriving anyclass (Binary) - -data Location = Location - { protocol :: Text - -- ^ A string containing the protocol scheme of the URL, including - -- the final ':' - , hostname :: Text - -- ^ A string containing the domain of the URL. - , port :: Text - -- ^ A string containing the port number of the URL. - , pathname :: Text - -- ^ A string containing an initial '/' followed by the path of the - -- URL, not including the query string or fragment. - , search :: Text - -- ^ A string containing a '?' followed by the parameters or - -- "querystring" of the URL - , hash :: Text - -- ^ A string containing a '#' followed by the fragment identifier - -- of the URL. - } deriving stock (Show, Eq, Generic) - deriving anyclass (Binary, Value.FromJSValue, Value.ToJSValue) +newtype StartFlags = StartFlags {unStartFlags :: Value.Value} + deriving newtype (Generic, Show, Binary) -- | Strict Lambda calculus with arbitrary side-effects, meant to be -- used as commands executed in the JavaScript side, optimized for From c807dfae424e13c20c64c5564be11a336abfecbc Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 2 Apr 2024 19:15:10 +0400 Subject: [PATCH 20/64] simpleList-v1 --- examples/charts/dev-server.hs | 9 +- examples/todomvc/JsMain.hs | 24 ++ examples/todomvc/TodoItem.hs | 92 +++++ examples/todomvc/TodoList.hs | 574 ++++++++++++++++++++++++++++++++ examples/todomvc/Utils.hs | 18 + examples/todomvc/dev.hs | 6 + examples/todomvc/wasm.hs | 13 + htmlt.cabal | 43 +-- jsbits/jsffi.js | 5 +- src/Clickable/Core.hs | 109 +++++- src/Clickable/DOM.hs | 14 +- src/Clickable/FFI.hs | 14 + src/Clickable/Internal.hs | 10 +- src/Clickable/Main/DevServer.hs | 119 +++---- src/Clickable/Types.hs | 4 + 15 files changed, 942 insertions(+), 112 deletions(-) create mode 100644 examples/todomvc/JsMain.hs create mode 100644 examples/todomvc/TodoItem.hs create mode 100644 examples/todomvc/TodoList.hs create mode 100644 examples/todomvc/Utils.hs create mode 100644 examples/todomvc/dev.hs create mode 100644 examples/todomvc/wasm.hs diff --git a/examples/charts/dev-server.hs b/examples/charts/dev-server.hs index 40f5383..4441c9e 100644 --- a/examples/charts/dev-server.hs +++ b/examples/charts/dev-server.hs @@ -1,9 +1,8 @@ -import Control.Monad.Reader -import Clickable.Main.DevServer import Clickable -import GHC.Ptr -import GHC.Word +import Clickable.Main.DevServer +import Control.Monad.Reader + import "this" App qualified as App main :: IO () -main = runDebugDefault 8081 \_ _ -> attachToBody $ lift App.new >>= App.html +main = runServer \_ _ -> attachToBody $ lift App.new >>= App.html diff --git a/examples/todomvc/JsMain.hs b/examples/todomvc/JsMain.hs new file mode 100644 index 0000000..1ac4c31 --- /dev/null +++ b/examples/todomvc/JsMain.hs @@ -0,0 +1,24 @@ +module JsMain where + +import Data.Maybe +import Clickable +import Clickable.Protocol + +import "this" TodoList qualified as TodoList +import "this" Utils + +jsMain :: StartFlags -> ClickM () +jsMain _ = do + items <- fromMaybe [] <$> readLocalStorage "todo-items" + todoListStateRef <- TodoList.eval $ TodoList.InitAction items + installFinalizer do + tolistState <- readVar todoListStateRef + saveLocalStorage "todo-items" tolistState.items + attachToBody do + el "style" $ text TodoList.styles + TodoList.html TodoList.TodoListConfig + { state_ref = todoListStateRef + } + -- globalAddEventListener (Id "window") popstateEventArgs \loc -> do + -- let filter = fromMaybe TodoList.All $ TodoList.parseFilter loc.hash + -- modifyRef todoListStateRef \s -> s {TodoList.filter} diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs new file mode 100644 index 0000000..ae4e997 --- /dev/null +++ b/examples/todomvc/TodoItem.hs @@ -0,0 +1,92 @@ +module TodoItem where + +import Data.List qualified as List +import Data.Maybe +import Data.Text (Text) +import GHC.Int +import Clickable +import Clickable.Protocol.Value + +data TodoItemConfig = TodoItemConfig + { state_ref :: DynVar TodoItemState + , is_hidden_dyn :: DynVal Bool + , ask_delete_item :: ClickM () + } + +data TodoItemState = TodoItemState + { title :: Text + , completed :: Bool + , editing :: Maybe Text + } deriving stock (Show, Eq) + +data TodoItemAction a where + CancelAction :: TodoItemConfig -> TodoItemAction () + CommitAction :: TodoItemConfig -> TodoItemAction () + InputAction :: TodoItemConfig -> Text -> TodoItemAction () + DoubleClickAction :: TodoItemConfig -> TodoItemAction () + CheckedAction :: TodoItemConfig -> Bool -> TodoItemAction () + KeydownAction :: TodoItemConfig -> Int64 -> TodoItemAction () + +eval :: TodoItemAction a -> ClickM a +eval = \case + CancelAction cfg -> + modifyVar_ cfg.state_ref \s -> s{editing=Nothing} + CommitAction cfg -> do + state <- readVar cfg.state_ref + case state.editing of + Just "" -> + cfg.ask_delete_item + Just t -> + modifyVar_ cfg.state_ref \s -> s {editing=Nothing, title = t} + Nothing -> + pure () + InputAction cfg newVal -> + modifyVar_ cfg.state_ref \s -> s{editing = Just newVal} + DoubleClickAction cfg -> do + modifyVar_ cfg.state_ref \s -> s {editing = Just s.title} +-- liftIO $ js_todoItemInputFocus targetEl + CheckedAction cfg isChecked -> do + modifyVar_ cfg.state_ref \s -> s{completed = isChecked} + KeydownAction cfg key -> case key of + 13 {- Enter -} -> eval (CommitAction cfg) + 27 {- Escape -} -> eval (CancelAction cfg) + _ -> return () + +html :: TodoItemConfig -> HtmlM () +html cfg = li_ do + let + completedDyn = (.completed) <$> fromVar cfg.state_ref + editingDyn = isJust . (.editing) <$> fromVar cfg.state_ref + valueDyn = fromMaybe "" . (.editing) <$> fromVar cfg.state_ref + toggleClass "completed" completedDyn + toggleClass "editing" editingDyn + toggleClass "hidden" cfg.is_hidden_dyn + div_ [class_ "view"] do + on @"dblclick" $ eval $ DoubleClickAction cfg + input_ [class_ "toggle", type_ "checkbox"] do + dynChecked $ (.completed) <$> fromVar cfg.state_ref + on @"checkbox/change" $ eval . CheckedAction cfg + label_ $ dynText $ (.title) <$> fromVar cfg.state_ref + button_ [class_ "destroy"] do + on @"click" cfg.ask_delete_item + input_ [class_ "edit", type_ "text"] do + dynValue valueDyn + on @"input" $ eval . InputAction cfg + on @"keydown" $ eval . KeydownAction cfg + on @"blur" $ eval (CommitAction cfg) + +emptyTodoItemState :: TodoItemState +emptyTodoItemState = TodoItemState "" False Nothing + +instance ToJSValue TodoItemState where + toJSValue s = Object + [ ("title", toJSValue s.title) + , ("completed", toJSValue s.completed) + ] + +instance FromJSValue TodoItemState where + fromJSValue (Object kv) = do + title <- fromJSValue =<< List.lookup "title" kv + completed <- fromJSValue =<< List.lookup "completed" kv + return TodoItemState {editing=Nothing, ..} + fromJSValue _ = Nothing diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs new file mode 100644 index 0000000..f115d91 --- /dev/null +++ b/examples/todomvc/TodoList.hs @@ -0,0 +1,574 @@ +module TodoList where + +import Control.Monad +import Data.List qualified as List +import Data.Text (Text) +import Data.Text qualified as Text +import GHC.Int +import Clickable +import Clickable.FFI + +import "this" TodoItem qualified as TodoItem + + +data TodoListConfig = TodoListConfig + { state_ref :: DynVar TodoListState + } + +data TodoListState = TodoListState + { title :: Text + , items :: [TodoItem.TodoItemState] + , filter :: Filter + } deriving (Show, Eq) + +data Filter = All | Active | Completed + deriving (Show, Eq) + +data TodoListAction a where + InitAction :: [TodoItem.TodoItemState] -> TodoListAction (DynVar TodoListState) + ToggleAllAction :: TodoListConfig -> Bool -> TodoListAction () + InputAction :: TodoListConfig -> Text -> TodoListAction () + CommitAction :: TodoListConfig -> TodoListAction () + KeydownAction :: TodoListConfig -> Int64 -> TodoListAction () + DeleteItemAction :: TodoListConfig -> Int -> TodoListAction () + ClearCompletedAction :: TodoListConfig -> TodoListAction () + +eval :: TodoListAction a -> ClickM a +eval = \case + InitAction items -> do + newDynVar TodoListState + { title = "" + , items = items + , filter = All + } + ToggleAllAction cfg isChecked -> + modifyVar_ cfg.state_ref \s -> s + { items = + fmap (\i -> i {TodoItem.completed = isChecked}) s.items + } + InputAction cfg newVal -> do + modifyVar_ cfg.state_ref \s -> s {title = newVal} + CommitAction cfg -> do + title <- Text.strip . (.title) <$> readVar cfg.state_ref + case title of + "" -> return () + t -> modifyVar_ cfg.state_ref \s -> s + { items = s.items <> [mkNewItem t] + , title = "" + } + KeydownAction cfg key -> do + case key of + 13 {- Enter -} -> eval (CommitAction cfg) + 27 {- Escape -} -> do + s <- readVar cfg.state_ref + consoleLog $ Text.pack $ show s + _ -> return () + DeleteItemAction cfg itemIx -> + modifyVar_ cfg.state_ref \s -> s {items = deleteIx itemIx s.items} + ClearCompletedAction cfg -> + modifyVar_ cfg.state_ref \s -> s + {items = (List.filter (not . TodoItem.completed)) s.items} + where + deleteIx :: Int -> [a] -> [a] + deleteIx _ [] = [] + deleteIx i (a:as) + | i == 0 = as + | otherwise = a : deleteIx (i-1) as + mkNewItem t = + TodoItem.emptyTodoItemState {TodoItem.title = t} + +html :: TodoListConfig -> HtmlM () +html cfg = do + div_ do + section_ [class_ "todoapp"] do + headerWidget + mainWidget + footerWidget + footerInfoWidget + where + headerWidget = header_ [class_ "header"] do + h1_ (text "todos") + input_ [class_ "new-todo", placeholder_ "What needs to be done?", autofocus_ True] do + dynValue $ (.title) <$> fromVar cfg.state_ref + on @"input" $ eval . InputAction cfg + on @"keydown" $ eval . KeydownAction cfg + mainWidget = section_ [class_ "main"] do + toggleClass "hidden" hiddenDyn + input_ [id_ "toggle-all", class_ "toggle-all", type_ "checkbox"] do + on @"checkbox/change" $ eval . ToggleAllAction cfg + label_ do + attribute "for" "toggle-all" + text "Mark all as completed" + ul_ [class_ "todo-list"] do + simpleList itemsDyn \idx todoRef -> + TodoItem.html $ TodoItem.TodoItemConfig + { TodoItem.state_ref = todoRef + -- { modifier = todoItemModifier cfg idx todoRef.modifier + -- } + , TodoItem.is_hidden_dyn = + isTodoItemHidden <$> fromVar cfg.state_ref <*> fromVar todoRef + , TodoItem.ask_delete_item = eval (DeleteItemAction cfg idx) + } + footerWidget = footer_ [class_ "footer"] do + toggleClass "hidden" hiddenDyn + span_ [class_ "todo-count"] do + strong_ $ dynText $ Text.pack . show <$> itemsLeftDyn + dynText $ pluralize " item left" " items left" <$> itemsLeftDyn + ul_ [class_ "filters"] do + forM_ [All, Active, Completed] filterWidget + button_ [class_ "clear-completed"] do + on @"click" $ eval (ClearCompletedAction cfg) + text "Clear completed" + footerInfoWidget = footer_ [class_ "info"] do + p_ "Double-click to edit a todo" + p_ do + text "Created by " + a_ [href_ "https://github.com/lagunoff"] "Vlad Lagunov" + p_ do + text "Part of " + a_ [href_ "http://todomvc.com"] "TodoMVC" + filterWidget :: Filter -> HtmlM () + filterWidget flt = li_ do + a_ [href_ (printFilter flt)] do + toggleClass "selected" $ filterSelectedDyn flt + text $ Text.pack $ show flt + hiddenDyn = + Prelude.null . (.items) <$> fromVar cfg.state_ref + itemsLeftDyn = + countItemsLeft <$> fromVar cfg.state_ref + filterSelectedDyn flt = + (==flt) . (.filter) <$> fromVar cfg.state_ref + itemsDyn = + (.items) <$> fromVar cfg.state_ref + countItemsLeft TodoListState{items} = + foldl (\acc TodoItem.TodoItemState{completed} -> + if not completed then acc + 1 else acc) 0 items + isTodoItemHidden :: TodoListState -> TodoItem.TodoItemState -> Bool + isTodoItemHidden listState itemState = + case (listState.filter, itemState.completed) of + (Active, True) -> True + (Completed, False) -> True + _ -> False + +pluralize :: Text -> Text -> Int -> Text +pluralize singular _plural 0 = singular +pluralize _singular plural _ = plural + +parseFilter :: Text -> Maybe Filter +parseFilter = \case + "#/" -> Just All + "#/active" -> Just Active + "#/completed" -> Just Completed + _ -> Nothing + +printFilter :: Filter -> Text +printFilter = \case + All -> "#/" + Active -> "#/active" + Completed -> "#/completed" + +-- -- | Synchronize changes inside TodoItem widget with the outer +-- -- TodoList widget. +-- todoItemModifier +-- :: TodoListConfig +-- -> Int +-- -> Modifier TodoItem.TodoItemState +-- -> Modifier TodoItem.TodoItemState +-- todoItemModifier cfg idx elemModifier = Modifier \upd f -> do +-- -- Update the local TodoItem element widget +-- ((old, new), result) <- unModifier elemModifier upd \old -> +-- let (new, result) = f old in (new, ((old, new), result)) +-- let +-- -- When False, the update event won't be propagated into the outer +-- -- widget for the sake of optimization +-- needsUpdate = upd && (old.completed /= new.completed) +-- -- Update the outer widget +-- unModifier cfg.state_ref.modifier needsUpdate \old -> +-- (old {items = overIx idx (const new) old.items}, ()) +-- return result +-- where +-- overIx :: Int -> (a -> a) -> [a] -> [a] +-- overIx 0 f (x:xs) = f x : xs +-- overIx n f (x:xs) = x : overIx (pred n) f xs +-- overIx _ _ [] = [] + +styles :: Text +styles = "\ + \body {\ + \ margin: 0;\ + \ padding: 0 ;\ + \}\ + \\ + \button {\ + \ margin: 0;\ + \ padding: 0;\ + \ border: 0;\ + \ background: none;\ + \ font-size: 100%;\ + \ vertical-align: baseline;\ + \ font-family: inherit;\ + \ font-weight: inherit;\ + \ color: inherit;\ + \ -webkit-appearance: none;\ + \ appearance: none;\ + \ -webkit-font-smoothing: antialiased;\ + \ -moz-osx-font-smoothing: grayscale;\ + \}\ + \\ + \body {\ + \ font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;\ + \ line-height: 1.4em;\ + \ background: #f5f5f5;\ + \ color: #4d4d4d;\ + \ min-width: 230px;\ + \ max-width: 550px;\ + \ margin: 0 auto;\ + \ -webkit-font-smoothing: antialiased;\ + \ -moz-osx-font-smoothing: grayscale;\ + \ font-weight: 300;\ + \}\ + \\ + \:focus {\ + \ outline: 0;\ + \}\ + \\ + \.hidden {\ + \ display: none;\ + \}\ + \\ + \.todoapp {\ + \ background: #fff;\ + \ margin: 130px 0 40px 0;\ + \ position: relative;\ + \ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),\ + \ 0 25px 50px 0 rgba(0, 0, 0, 0.1);\ + \}\ + \\ + \.todoapp input::-webkit-input-placeholder {\ + \ font-style: italic;\ + \ font-weight: 300;\ + \ color: #e6e6e6;\ + \}\ + \\ + \.todoapp input::-moz-placeholder {\ + \ font-style: italic;\ + \ font-weight: 300;\ + \ color: #e6e6e6;\ + \}\ + \\ + \.todoapp input::input-placeholder {\ + \ font-style: italic;\ + \ font-weight: 300;\ + \ color: #e6e6e6;\ + \}\ + \\ + \.todoapp h1 {\ + \ position: absolute;\ + \ top: -155px;\ + \ width: 100%;\ + \ font-size: 100px;\ + \ font-weight: 100;\ + \ text-align: center;\ + \ color: rgba(175, 47, 47, 0.15);\ + \ -webkit-text-rendering: optimizeLegibility;\ + \ -moz-text-rendering: optimizeLegibility;\ + \ text-rendering: optimizeLegibility;\ + \}\ + \\ + \.new-todo,\ + \.edit {\ + \ position: relative;\ + \ margin: 0;\ + \ width: 100%;\ + \ font-size: 24px;\ + \ font-family: inherit;\ + \ font-weight: inherit;\ + \ line-height: 1.4em;\ + \ border: 0;\ + \ color: inherit;\ + \ padding: 6px;\ + \ border: 1px solid #999;\ + \ box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);\ + \ box-sizing: border-box;\ + \ -webkit-font-smoothing: antialiased;\ + \ -moz-osx-font-smoothing: grayscale;\ + \}\ + \\ + \.new-todo {\ + \ padding: 16px 16px 16px 60px;\ + \ border: none;\ + \ background: rgba(0, 0, 0, 0.003);\ + \ box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);\ + \}\ + \\ + \.main {\ + \ position: relative;\ + \ z-index: 2;\ + \ border-top: 1px solid #e6e6e6;\ + \}\ + \\ + \.toggle-all {\ + \ width: 1px;\ + \ height: 1px;\ + \ border: none; /* Mobile Safari */\ + \ opacity: 0;\ + \ position: absolute;\ + \ right: 100%;\ + \ bottom: 100%;\ + \}\ + \\ + \.toggle-all + label {\ + \ width: 60px;\ + \ height: 34px;\ + \ font-size: 0;\ + \ position: absolute;\ + \ top: -52px;\ + \ left: -13px;\ + \ -webkit-transform: rotate(90deg);\ + \ transform: rotate(90deg);\ + \}\ + \\ + \.toggle-all + label:before {\ + \ content: '❯';\ + \ font-size: 22px;\ + \ color: #e6e6e6;\ + \ padding: 10px 27px 10px 27px;\ + \}\ + \\ + \.toggle-all:checked + label:before {\ + \ color: #737373;\ + \}\ + \\ + \.todo-list {\ + \ margin: 0;\ + \ padding: 0;\ + \ list-style: none;\ + \}\ + \\ + \.todo-list li {\ + \ position: relative;\ + \ font-size: 24px;\ + \ border-bottom: 1px solid #ededed;\ + \}\ + \\ + \.todo-list li:last-child {\ + \ border-bottom: none;\ + \}\ + \\ + \.todo-list li.editing {\ + \ border-bottom: none;\ + \ padding: 0;\ + \}\ + \\ + \.todo-list li.editing .edit {\ + \ display: block;\ + \ width: calc(100% - 43px);\ + \ padding: 12px 16px;\ + \ margin: 0 0 0 43px;\ + \}\ + \\ + \.todo-list li.editing .view {\ + \ display: none;\ + \}\ + \\ + \.todo-list li .toggle {\ + \ text-align: center;\ + \ width: 40px;\ + \ /* auto, since non-WebKit browsers doesn't support input styling */\ + \ height: auto;\ + \ position: absolute;\ + \ top: 0;\ + \ bottom: 0;\ + \ margin: auto 0;\ + \ border: none; /* Mobile Safari */\ + \ -webkit-appearance: none;\ + \ appearance: none;\ + \}\ + \\ + \.todo-list li .toggle {\ + \ opacity: 0;\ + \}\ + \\ + \.todo-list li .toggle + label {\ + \ /*\ + \ Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433\ + \ IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/\ + \ */\ + \ background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');\ + \ background-repeat: no-repeat;\ + \ background-position: center left;\ + \}\ + \\ + \.todo-list li .toggle:checked + label {\ + \ background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');\ + \}\ + \\ + \.todo-list li label {\ + \ word-break: break-all;\ + \ padding: 15px 15px 15px 60px;\ + \ display: block;\ + \ line-height: 1.2;\ + \ transition: color 0.4s;\ + \}\ + \\ + \.todo-list li.completed label {\ + \ color: #d9d9d9;\ + \ text-decoration: line-through;\ + \}\ + \\ + \.todo-list li .destroy {\ + \ display: none;\ + \ position: absolute;\ + \ top: 0;\ + \ right: 10px;\ + \ bottom: 0;\ + \ width: 40px;\ + \ height: 40px;\ + \ margin: auto 0;\ + \ font-size: 30px;\ + \ color: #cc9a9a;\ + \ margin-bottom: 11px;\ + \ transition: color 0.2s ease-out;\ + \}\ + \\ + \.todo-list li .destroy:hover {\ + \ color: #af5b5e;\ + \}\ + \\ + \.todo-list li .destroy:after {\ + \ content: '×';\ + \}\ + \\ + \.todo-list li:hover .destroy {\ + \ display: block;\ + \}\ + \\ + \.todo-list li .edit {\ + \ display: none;\ + \}\ + \\ + \.todo-list li.editing:last-child {\ + \ margin-bottom: -1px;\ + \}\ + \\ + \.footer {\ + \ color: #777;\ + \ padding: 10px 15px;\ + \ height: 20px;\ + \ text-align: center;\ + \ border-top: 1px solid #e6e6e6;\ + \}\ + \\ + \.footer:before {\ + \ content: '';\ + \ position: absolute;\ + \ right: 0;\ + \ bottom: 0;\ + \ left: 0;\ + \ height: 50px;\ + \ overflow: hidden;\ + \ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),\ + \ 0 8px 0 -3px #f6f6f6,\ + \ 0 9px 1px -3px rgba(0, 0, 0, 0.2),\ + \ 0 16px 0 -6px #f6f6f6,\ + \ 0 17px 2px -6px rgba(0, 0, 0, 0.2);\ + \}\ + \\ + \.todo-count {\ + \ float: left;\ + \ text-align: left;\ + \}\ + \\ + \.todo-count strong {\ + \ font-weight: 300;\ + \}\ + \\ + \.filters {\ + \ margin: 0;\ + \ padding: 0;\ + \ list-style: none;\ + \ position: absolute;\ + \ right: 0;\ + \ left: 0;\ + \}\ + \\ + \.filters li {\ + \ display: inline;\ + \}\ + \\ + \.filters li a {\ + \ color: inherit;\ + \ margin: 3px;\ + \ padding: 3px 7px;\ + \ text-decoration: none;\ + \ border: 1px solid transparent;\ + \ border-radius: 3px;\ + \}\ + \\ + \.filters li a:hover {\ + \ border-color: rgba(175, 47, 47, 0.1);\ + \}\ + \\ + \.filters li a.selected {\ + \ border-color: rgba(175, 47, 47, 0.2);\ + \}\ + \\ + \.clear-completed,\ + \html .clear-completed:active {\ + \ float: right;\ + \ position: relative;\ + \ line-height: 20px;\ + \ text-decoration: none;\ + \ cursor: pointer;\ + \}\ + \\ + \.clear-completed:hover {\ + \ text-decoration: underline;\ + \}\ + \\ + \.info {\ + \ margin: 65px auto 0;\ + \ color: #bfbfbf;\ + \ font-size: 10px;\ + \ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\ + \ text-align: center;\ + \}\ + \\ + \.info p {\ + \ line-height: 1;\ + \}\ + \\ + \.info a {\ + \ color: inherit;\ + \ text-decoration: none;\ + \ font-weight: 400;\ + \}\ + \\ + \.info a:hover {\ + \ text-decoration: underline;\ + \}\ + \\ + \/*\ + \ Hack to remove background from Mobile Safari.\ + \ Can't use it globally since it destroys checkboxes in Firefox\ + \*/\ + \@media screen and (-webkit-min-device-pixel-ratio:0) {\ + \ .toggle-all,\ + \ .todo-list li .toggle {\ + \ background: none;\ + \ }\ + \\ + \ .todo-list li .toggle {\ + \ height: 40px;\ + \ }\ + \}\ + \\ + \@media (max-width: 430px) {\ + \ .footer {\ + \ height: 50px;\ + \ }\ + \\ + \ .filters {\ + \ bottom: 10px;\ + \ }\ + \}" diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs new file mode 100644 index 0000000..98b1d38 --- /dev/null +++ b/examples/todomvc/Utils.hs @@ -0,0 +1,18 @@ +module Utils where + +import Data.Text (Text) + +import Clickable +import Clickable.Protocol +import Clickable.Protocol.Value (FromJSValue(..), ToJSValue(..)) + +readLocalStorage :: FromJSValue v => Text -> ClickM (Maybe v) +readLocalStorage key = do + let jsonParse = Call (Id "JSON") "parse" . (:[]) + jsval <- evalExpr $ jsonParse $ Call (Id "localStorage") "getItem" [String key] + return $ fromJSValue jsval + +saveLocalStorage :: ToJSValue v => Text -> v -> ClickM () +saveLocalStorage key val = do + let stringify = Call (Id "JSON") "stringify" . (:[]) . valueToExpr . toJSValue + enqueueExpr $ Call (Id "localStorage") "setItem" [String key, stringify val] diff --git a/examples/todomvc/dev.hs b/examples/todomvc/dev.hs new file mode 100644 index 0000000..6304257 --- /dev/null +++ b/examples/todomvc/dev.hs @@ -0,0 +1,6 @@ +import Clickable.Main.DevServer + +import "this" JsMain (jsMain) + +main :: IO () +main = runServer jsMain diff --git a/examples/todomvc/wasm.hs b/examples/todomvc/wasm.hs new file mode 100644 index 0000000..d0454ad --- /dev/null +++ b/examples/todomvc/wasm.hs @@ -0,0 +1,13 @@ +import Control.Monad.Reader +import Clickable +import GHC.Ptr +import GHC.Word +import "this" JsMain qualified as App + +main :: IO () +main = return () + +foreign export ccall wasm_main :: Ptr Word8 -> IO () +wasm_main p = do + _ <- runApp p App.jsMain + return () diff --git a/htmlt.cabal b/htmlt.cabal index 85930e8..487c76d 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -78,7 +78,7 @@ common htmlt-common library import: htmlt-common - hs-source-dirs: src ./examples/charts + hs-source-dirs: src ./examples/charts ./examples/todomvc exposed-modules: Clickable Clickable.Core @@ -134,24 +134,28 @@ library -- if !flag(examples) -- buildable: False --- executable htmlt-todomvc --- import: htmlt-common --- main-is: todomvc.hs --- hs-source-dirs: ./examples/todomvc --- ghc-options: --- -no-hs-main -optl-mexec-model=reactor --- -optl-Wl,--export=hs_init,--export=wasm_main --- other-modules: --- TodoItem --- TodoList --- Utils --- build-depends: --- base, --- htmlt, --- text, --- mtl, --- if !flag(examples) --- buildable: False +executable htmlt-todomvc + import: htmlt-common + hs-source-dirs: ./examples/todomvc + if arch(wasm32) + ghc-options: + -no-hs-main -optl-mexec-model=reactor + -optl-Wl,--export=hs_init,--export=wasm_main,--export=malloc + main-is: wasm.hs + else + ghc-options: -threaded + main-is: dev.hs + other-modules: + TodoItem + TodoList + Utils + build-depends: + base, + htmlt, + text, + mtl, + if !flag(examples) + buildable: False executable htmlt-charts import: htmlt-common @@ -162,6 +166,7 @@ executable htmlt-charts -optl-Wl,--export=hs_init,--export=wasm_main,--export=malloc main-is: charts.hs else + ghc-options: -threaded main-is: dev-server.hs build-depends: base, diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index 675bbfc..faff439 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -100,8 +100,9 @@ newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v), getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), -ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), -ZC2ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => (evalMessageFFI($1, __exports, $2)), +ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, +ZC2ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), +ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => (evalMessageFFI($1, __exports, $2)), ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 87299e5..ad091b3 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -5,11 +5,16 @@ module Clickable.Core , Internal.launchClickM ) where +import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.IORef +import Data.Tuple import Data.Function ((&)) import Data.Text (Text) +import Data.Text qualified as Text +import Data.String +import Control.Applicative import Clickable.Internal (reactive, reactive_) import Clickable.Internal qualified as Internal @@ -30,14 +35,21 @@ newDynVar a = do ref <- liftIO $ newIORef a state \s -> (DynVar (SourceId s.next_id) ref, s {next_id = s.next_id + 1}) +elemVar :: MonadIO m => Int -> DynVar [a] -> a -> m (DynVar a) +elemVar i var a = do + ref <- liftIO $ newIORef a + return $ ElemVar var i ref + readVal :: DynVal a -> ClickM a readVal (ConstVal a) = pure a -readVal (FromVar (DynVar _ ref)) = liftIO $ readIORef ref +readVal (FromVar var) = readVar var readVal (MapVal val f) = fmap f $ readVal val readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) readVar :: DynVar a -> ClickM a readVar (DynVar _ ref) = liftIO $ readIORef ref +readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var +readVar (ElemVar _ _ ref) = liftIO $ readIORef ref modifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a modifyVar var@(DynVar varId ref) f = do @@ -46,6 +58,13 @@ modifyVar var@(DynVar varId ref) f = do return a where g old = let (new, a) = f old in (new, (new, a)) +modifyVar (ElemVar var i _) f = modifyVar var $ overIx i f + where + overIx :: forall s a. Int -> (s -> (s, a)) -> [s] -> ([s], a) + overIx 0 f (x:xs) = let (s, a) = f x in (s : xs, a) + overIx n f (x:xs) = let (s, a) = overIx (pred n) f xs in (x : s, a) + overIx _ _ [] = error "ElemVar: invalid index" +modifyVar (LensMap l var) f = modifyVar var (swap . l (swap . f)) modifyVar_ :: DynVar s -> (s -> s) -> ClickM () modifyVar_ var f = modifyVar var ((,()) . f) @@ -63,8 +82,8 @@ subscribe val k = reactive_ $ Internal.subscribe val k enqueueExpr :: Expr -> ClickM () enqueueExpr e = modify \s -> s {evaluation_queue = e : s.evaluation_queue} -evalSync :: Expr -> ClickM Value -evalSync e = do +evalExpr :: Expr -> ClickM Value +evalExpr e = do send_message <- asks (.send_message) queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) result <- liftIO $ send_message $ EvalExpr $ RevSeq $ e : queue @@ -153,8 +172,18 @@ dynBoolProp k val = do f v s = s {evaluation_queue = expr v : s.evaluation_queue } expr v = ElementProp (Arg 0 0) k (Boolean v) -blank :: Applicative m => m () -blank = pure () +toggleClass :: Text -> DynVal Bool -> HtmlM () +toggleClass className val = do + scope <- lift $ asks (.scope) + v <- lift $ readVal val + n <- saveCurrentNode + let + initCmd False queue = queue + initCmd True queue = InsertClassList (Arg 0 0) [className] : queue + updateCmd False = RemoveClassList (Var n) [className] + updateCmd True = InsertClassList (Var n) [className] + lift $ modify \s -> s {evaluation_queue = initCmd v s.evaluation_queue} + lift $ subscribe val $ enqueueIfAlive scope . updateCmd --------------------- -- DYNAMIC CONTENT -- @@ -177,6 +206,70 @@ dyn val = do freeScope False scope exec $ update newVal +-- | Auxilliary datatype used in 'simpleList' implementation +data ElemEnv a = ElemEnv + { elem_boundary :: VarId + , elem_state_ref :: DynVar a + , reactive_scope :: ResourceScope + } + +simpleList + :: forall a. DynVar [a] + -- ^ Some dynamic data from the above scope + -> (Int -> DynVar a -> HtmlM ()) + -- ^ Function to build children widget. Accepts the index inside the + -- collection and dynamic data for that particular element + -> HtmlM () +simpleList listVar h = lift do + let listDyn = fromVar listVar + internalStateRef <- liftIO $ newIORef ([] :: [ElemEnv a]) + boundary <- insertBoundary + let + exec boundary scope h = evalStateT h.unHtmlT Nothing + & htmlBuilder1 (Var boundary) + & local (\s -> s {scope}) + exec1 boundary = htmlBuilder1 (Var boundary) + + setup :: Int -> [a] -> [ElemEnv a] -> ClickM [ElemEnv a] + setup idx new existing = case (existing, new) of + ([], []) -> return [] + -- New list is longer, append new elements + ([], x:xs) -> do + e <- newElem idx x + exec e.elem_boundary e.reactive_scope $ h idx e.elem_state_ref + fmap (e:) $ setup (idx + 1) xs [] + -- New list is shorter, delete the elements that no longer + -- present in the new list + (r:rs, []) -> do + finalizeElems True (r:rs) + return [] + -- Update existing elements along the way + (r:rs, y:ys) -> do + writeVar r.elem_state_ref y + fmap (r:) $ setup (idx + 1) ys rs + newElem :: Int -> a -> ClickM (ElemEnv a) + newElem i a = do + scope <- newScope + local (\s -> s {scope}) do + elem_state_ref <- elemVar i listVar a + elem_boundary <- insertBoundary + return ElemEnv {reactive_scope = scope, elem_state_ref, elem_boundary} + finalizeElems :: Bool -> [ElemEnv a] -> ClickM () + finalizeElems remove = mapM_ \ee -> do + when remove $ destroyBoundary ee.elem_boundary + freeScope True ee.reactive_scope + updateList new = do + eenvs <- liftIO $ readIORef internalStateRef + newEenvs <- setup 0 new eenvs + liftIO $ writeIORef internalStateRef newEenvs + initialVal <- readVal listDyn + exec1 boundary $ updateList initialVal + subscribe listDyn $ exec1 boundary . updateList + +---------------------------- +-- AUXILLIARY DEFINITIONS -- +---------------------------- + htmlBuilder :: Expr -> ClickM a -> ClickM a htmlBuilder builder content = do prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) @@ -240,3 +333,9 @@ attachHtml rootElm contents = do attachToBody :: HtmlM a -> ClickM a attachToBody = attachHtml (Id "document" `Dot` "body") + +blank :: Applicative m => m () +blank = pure () + +instance (a ~ ()) => IsString (HtmlM a) where + fromString = text . Text.pack diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index c4f29b4..e4c2c6e 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -138,7 +138,7 @@ inputConnectArgs eventName = ConnectResourceArgs \ function listener(target){\n\ \ haskellCb(event.target.value);\n\ \ }\n\ - \ window.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => window.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \})") `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromJSValue event) k @@ -151,10 +151,10 @@ keyboardConnectArgs eventName = ConnectResourceArgs { aquire_fn = \scope sourceId -> Eval ( "(function(target, haskellCb){\n\ \ function listener(target){\n\ - \ haskellCb(event.target.value);\n\ + \ haskellCb(event.keyCode);\n\ \ }\n\ - \ window.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \ return () => window.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \})") `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromJSValue event) k } @@ -179,7 +179,7 @@ checkboxChangeConnectArgs = ConnectResourceArgs \ function listener(target){\n\ \ haskellCb(event.target.checked);\n\ \ }\n\ - \ window.addEventListener('change', listener);\n\ + \ target.addEventListener('change', listener);\n\ \ return () => window.removeEventListener('change', listener);\n\ \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromJSValue event) k @@ -193,8 +193,8 @@ selectChangeConnectArgs = ConnectResourceArgs \ function listener(target){\n\ \ haskellCb(event.target.value);\n\ \ }\n\ - \ window.addEventListener('change', listener);\n\ - \ return () => window.removeEventListener('change', listener);\n\ + \ target.addEventListener('change', listener);\n\ + \ return () => target.removeEventListener('change', listener);\n\ \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromJSValue event) k } diff --git a/src/Clickable/FFI.hs b/src/Clickable/FFI.hs index b5dfa12..75b4cc7 100644 --- a/src/Clickable/FFI.hs +++ b/src/Clickable/FFI.hs @@ -9,8 +9,17 @@ module Clickable.FFI where import Wasm.Compat.Prim +import Control.Monad.IO.Class import GHC.Ptr import Data.Word +import Data.Text.Internal +import Data.Array.Byte +import GHC.Prim + +consoleLog :: MonadIO m => Text -> m () +consoleLog (Text (ByteArray arr) off len) = liftIO do + let addr = byteArrayContents# arr + js_consoleLog (Ptr addr `plusPtr` off) len #if !defined(wasm32_HOST_ARCH) js_evalMessageFFI :: JSVal -> Ptr Word8 -> IO (Ptr Word8) @@ -19,10 +28,15 @@ js_evalMessageFFI = undefined js_exportCallback :: (Ptr Word8 {- JavaScriptMessage -} -> IO ()) -> IO JSVal js_exportCallback = undefined +js_consoleLog :: Ptr Word8 -> Int -> IO () +js_consoleLog = undefined #else foreign import javascript unsafe "evalMessageFFI($1, __exports, $2)" js_evalMessageFFI :: JSVal -> Ptr Word8 {- HaskellMessage -} -> IO (Ptr Word8 {- JavaScriptMessage -}) foreign import javascript "wrapper" js_exportCallback :: (Ptr Word8 {- JavaScriptMessage -} -> IO ()) -> IO JSVal +foreign import javascript unsafe + "console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));" + js_consoleLog :: Ptr Word8 -> Int -> IO () #endif diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 1d810c8..81725fe 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -18,6 +18,8 @@ import Foreign.Ptr import Foreign.Storable import Unsafe.Coerce import Wasm.Compat.Prim +import Debug.Trace +import Data.Text qualified as Text import Clickable.FFI qualified as FFI import Clickable.Protocol @@ -38,12 +40,12 @@ newInternalEnv = mdo -- | Unsafe because there is no gurantee that @a@ matches @a@ in -- correspoding @DynVar a@ where SourceId comes from unsafeTrigger :: SourceId -> a -> InternalState -> InternalState -unsafeTrigger sourceId vals = +unsafeTrigger sourceId a = defer sourceId $ gets (.subscriptions) >>= notify where notify [] = return () notify ((_, s, cb) : xs) - | s == sourceId = cb (unsafeCoerce vals) >> notify xs + | s == sourceId = cb (unsafeCoerce a) >> notify xs | otherwise = notify xs defer k act s = s {transaction_queue = Map.insert k act s.transaction_queue} @@ -137,8 +139,10 @@ receiveMessage e jptr = do jbytes <- loadByteString jptr let jmsg = Binary.decode $ BSL.fromStrict jbytes case jmsg of + Start _value -> return () Return _value -> return () - TriggerCallbackMsg arg sourceId -> + TriggerCallbackMsg arg sourceId -> do + FFI.consoleLog $ Text.pack $ show (arg, sourceId) launchClickM e $ modify (unsafeTrigger sourceId arg) BeforeUnload -> return () where diff --git a/src/Clickable/Main/DevServer.hs b/src/Clickable/Main/DevServer.hs index da0d786..5ef9de2 100644 --- a/src/Clickable/Main/DevServer.hs +++ b/src/Clickable/Main/DevServer.hs @@ -20,7 +20,7 @@ import GHC.IO.Exception import Network.HTTP.Types as H import Network.Wai as WAI import Network.Wai.Application.Static -import Network.Wai.Handler.Warp as Warp +import Network.Wai.Handler.Warp qualified as Warp import Network.Wai.Handler.WebSockets import Network.WebSockets import System.Environment @@ -57,30 +57,30 @@ data ApplicationSpec = ApplicationSpec -- ^ Will be executed after a connection closes } deriving Generic -defaultDevServerConfig :: (ConnectionInfo -> StartFlags -> ClickM ()) -> DevServerConfig () -defaultDevServerConfig clientApp = DevServerConfig +defaultConfig :: (ConnectionInfo -> StartFlags -> ClickM ()) -> DevServerConfig () +defaultConfig clientApp = DevServerConfig { aquire_resource = pure () , release_resource = const (pure ()) - , reload_app = \_ -> pure $ ApplicationSpec clientApp defaultFallbackApp (const (pure ())) - , html_template = defaultHtmlTemplate + , reload_app = \_ -> pure $ ApplicationSpec clientApp fallbackApp (const (pure ())) + , html_template = htmlTemplate , docroots = [] } -runDebug :: Typeable resource => Warp.Settings -> DevServerConfig resource -> IO () -runDebug settings cfg = do +runSettings :: Typeable resource => Warp.Settings -> DevServerConfig resource -> IO () +runSettings settings cfg = do -- Using a random constant as the key for Foreign.Store let storeId = 183 hSetBuffering stderr LineBuffering lookupStore storeId >>= \case Nothing -> do - devInst <- newInstance cfg - writeStore (Store storeId) devInst + inst <- newInstance cfg + writeStore (Store storeId) inst let useCurrentApp req resp = do - RunningApp{devserver_config, server_app} <- readIORef devInst.app_state_ref + RunningApp{devserver_config, server_app} <- readIORef inst.app_state_ref withStaticApp devserver_config.docroots server_app req resp forkIfRepl $ tryPort settings $ - devserverMiddleware devInst useCurrentApp + middleware inst useCurrentApp Just store -> do oldInst <- readStore store updateInstance cfg oldInst @@ -91,14 +91,14 @@ runDebug settings cfg = do tryPort :: Warp.Settings -> Application -> IO () tryPort settings application = do hPutStrLn stderr $ "Running a Dev Server at http://localhost:" <> - show (getPort settings) <> "/" - result <- try $ runSettings settings application + show (Warp.getPort settings) <> "/" + result <- try $ Warp.runSettings settings application case result of Right () -> return () Left (e::IOException) | ioe_type e == ResourceBusy -> do hPutStrLn stderr $ "Already in use, trying next port…" - tryPort (setPort (getPort settings + 1) settings) application + tryPort (Warp.setPort (Warp.getPort settings + 1) settings) application | otherwise -> throwIO e withStaticApp :: [FilePath] -> Middleware withStaticApp [] next = next @@ -109,66 +109,60 @@ runDebug settings cfg = do isRepl <- (== "") <$> getProgName if isRepl then void (forkIO action) else action -runDebugPort :: Typeable resource => Warp.Port -> DevServerConfig resource -> IO () -runDebugPort port cfg = - runDebug (Warp.setPort port Warp.defaultSettings) cfg +runServer :: (StartFlags -> ClickM ()) -> IO () +runServer clientApp = runSettings + (Warp.setPort 8080 Warp.defaultSettings) + (defaultConfig (const clientApp)) -runDebugDefault :: Warp.Port -> (ConnectionInfo -> StartFlags -> ClickM ()) -> IO () -runDebugDefault port clientApp = runDebug - (Warp.setPort port Warp.defaultSettings) - (defaultDevServerConfig clientApp) - -devserverMiddleware :: DevServerInstance -> Middleware -devserverMiddleware opts next req resp = +middleware :: DevServerInstance -> Middleware +middleware opts next req resp = case pathInfo req of - [] -> indexHtmlApp req resp - ["index.html"] -> indexHtmlApp req resp - ["dev-server.sock"] -> devserverApp req resp + [] -> indexHtml req resp + ["index.html"] -> indexHtml req resp + ["dev.sock"] -> devserverApp req resp _ -> next req resp where devserverApp = - websocketsOr defaultConnectionOptions (devserverWebsocket opts) - defaultFallbackApp - indexHtmlApp req resp = do - let devSocket = devServerSocketUrl req + websocketsOr defaultConnectionOptions (websocketApp opts) + fallbackApp + indexHtml req resp = do + let devSocket = mkWebsocketUrl req RunningApp{devserver_config} <- readIORef opts.app_state_ref resp $ responseLBS status200 [(hContentType, "text/html; charset=utf-8")] $ devserver_config.html_template devSocket -devServerSocketUrl :: WAI.Request -> BSL.ByteString -devServerSocketUrl req = +mkWebsocketUrl :: WAI.Request -> BSL.ByteString +mkWebsocketUrl req = WAI.requestHeaders req & List.lookup "Host" & maybe "localhost" BSL.fromStrict & ((if WAI.isSecure req then "wss://" else "ws://") <>) - & (<> "/dev-server.sock") + & (<> "/dev.sock") -defaultHtmlTemplate :: BSL.ByteString -> BSL.ByteString -defaultHtmlTemplate devSocket = +htmlTemplate :: BSL.ByteString -> BSL.ByteString +htmlTemplate devUrl = "\n\ \ \n\ \ \n\ \ \n\ - \\n\ - \" + \\n" -defaultFallbackApp :: Application -defaultFallbackApp _ resp = +fallbackApp :: Application +fallbackApp _ resp = resp $ responseLBS status404 [(hContentType, "text/html; charset=utf-8")] "\n\ \ \n\ \

Not Found

\n\ \ \n\ - \\n\ - \" + \\n" -devserverWebsocket :: DevServerInstance -> ServerApp -devserverWebsocket opt p = +websocketApp :: DevServerInstance -> ServerApp +websocketApp opt p = let acceptConn = mdo conn <- acceptRequest p @@ -195,31 +189,21 @@ devserverWebsocket opt p = reader :: ConnectionInfo -> RunningApp -> ClientMessage -> IO () reader conn app = \case - BrowserMessage (Start flags) -> do - modifyIORef' conn.queue_ref (app.client_app conn flags:) - putMVar conn.signal_mvar () + BrowserMessage (Start flags) -> void $ forkIO + $ Internal.launchClickM conn.internal_env + $ app.client_app conn flags BrowserMessage (Return val) -> putMVar conn.return_mvar val - BrowserMessage (TriggerCallbackMsg arg sourceId) -> do - modifyIORef' conn.queue_ref (modify (Internal.unsafeTrigger sourceId arg):) - putMVar conn.signal_mvar () + BrowserMessage (TriggerCallbackMsg arg sourceId) -> void $ forkIO + $ Internal.launchClickM conn.internal_env + $ modify (Internal.unsafeTrigger sourceId arg) BrowserMessage BeforeUnload -> return () - DevServerMessage a -> do - modifyIORef' conn.queue_ref (a:) - putMVar conn.signal_mvar () - - worker :: ConnectionInfo -> IO () - worker conn = do - takeMVar conn.signal_mvar - queue <- atomicModifyIORef' conn.queue_ref ([],) - forM_ queue $ Internal.launchClickM conn.internal_env - worker conn + DevServerMessage a -> void $ forkIO + $ Internal.launchClickM conn.internal_env a newConn connection = mdo command_chan <- newChan return_mvar <- newEmptyMVar - signal_mvar <- newEmptyMVar - queue_ref <- newIORef [] internal_env <- newInternalEnv connection return_mvar connInfo <- atomicModifyIORef' opt.conn_state_ref \m -> let @@ -229,13 +213,9 @@ devserverWebsocket opt p = , connection , command_chan , connection_id - , return_mvar - , signal_mvar - , worker_thread - , queue_ref } + , return_mvar } in (Map.insert connection_id connInfo m, connInfo) - worker_thread <- forkIO $ worker connInfo return connInfo newInternalEnv :: Connection -> MVar Value -> IO InternalEnv newInternalEnv conn resultMvar = do @@ -310,11 +290,8 @@ data DevServerInstance = DevServerInstance data ConnectionInfo = ConnectionInfo { connection :: Connection , return_mvar :: MVar Value - , signal_mvar :: MVar () - , queue_ref :: IORef [ClickM ()] , internal_env :: InternalEnv , command_chan :: Chan (ClickM ()) - , worker_thread :: ~ThreadId -- ^ Writing to the Chan sends a command to the browser to execute , connection_id :: ConnectionId } deriving Generic diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index 513a379..6144d32 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -13,6 +13,8 @@ import Clickable.Protocol data DynVar a where DynVar :: SourceId -> IORef a -> DynVar a + ElemVar :: DynVar [a] -> Int -> IORef a -> DynVar a + LensMap :: Lens' s a -> DynVar s -> DynVar a data DynVal a where ConstVal :: a -> DynVal a @@ -56,3 +58,5 @@ data InternalState = InternalState data FinalizerVal = CustomFinalizer (ClickM ()) | ScopeFinalizer ResourceScope + +type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s From e26e7f825057e0e629b9804640ddcfe2eded7d52 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 3 Apr 2024 18:28:26 +0400 Subject: [PATCH 21/64] Recover TodoMVC example --- examples/todomvc/TodoList.hs | 59 ++++++++++++++++---------------- src/Clickable/Core.hs | 65 ++++++++++++++++++------------------ src/Clickable/Internal.hs | 21 ++++++++---- src/Clickable/Types.hs | 8 +++-- 4 files changed, 82 insertions(+), 71 deletions(-) diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index f115d91..3ce9caa 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -71,9 +71,7 @@ eval = \case where deleteIx :: Int -> [a] -> [a] deleteIx _ [] = [] - deleteIx i (a:as) - | i == 0 = as - | otherwise = a : deleteIx (i-1) as + deleteIx i (a:as) | i == 0 = as | otherwise = a : deleteIx (i-1) as mkNewItem t = TodoItem.emptyTodoItemState {TodoItem.title = t} @@ -102,9 +100,7 @@ html cfg = do ul_ [class_ "todo-list"] do simpleList itemsDyn \idx todoRef -> TodoItem.html $ TodoItem.TodoItemConfig - { TodoItem.state_ref = todoRef - -- { modifier = todoItemModifier cfg idx todoRef.modifier - -- } + { TodoItem.state_ref = spyVar (todoItemUpdated cfg idx) todoRef , TodoItem.is_hidden_dyn = isTodoItemHidden <$> fromVar cfg.state_ref <*> fromVar todoRef , TodoItem.ask_delete_item = eval (DeleteItemAction cfg idx) @@ -167,30 +163,33 @@ printFilter = \case Active -> "#/active" Completed -> "#/completed" --- -- | Synchronize changes inside TodoItem widget with the outer --- -- TodoList widget. --- todoItemModifier --- :: TodoListConfig --- -> Int --- -> Modifier TodoItem.TodoItemState --- -> Modifier TodoItem.TodoItemState --- todoItemModifier cfg idx elemModifier = Modifier \upd f -> do --- -- Update the local TodoItem element widget --- ((old, new), result) <- unModifier elemModifier upd \old -> --- let (new, result) = f old in (new, ((old, new), result)) --- let --- -- When False, the update event won't be propagated into the outer --- -- widget for the sake of optimization --- needsUpdate = upd && (old.completed /= new.completed) --- -- Update the outer widget --- unModifier cfg.state_ref.modifier needsUpdate \old -> --- (old {items = overIx idx (const new) old.items}, ()) --- return result --- where --- overIx :: Int -> (a -> a) -> [a] -> [a] --- overIx 0 f (x:xs) = f x : xs --- overIx n f (x:xs) = x : overIx (pred n) f xs --- overIx _ _ [] = [] +-- | Synchronize changes inside TodoItem widget with the outer +-- TodoList widget. +todoItemUpdated + :: TodoListConfig + -> Int + -> UpdateFn TodoItem.TodoItemState + -> UpdateFn TodoItem.TodoItemState +todoItemUpdated cfg i next f = do + -- Update the local TodoItemState + ((old, new), result) <- next g + let + -- When False, the update event won't be propagated into the outer + -- widget for the sake of optimization + needsUpdate = old.completed /= new.completed + -- Update TodoItemState inside the larger state + if needsUpdate + then modifyVar cfg.state_ref $ h new + else modifyVarQuiet cfg.state_ref $ h new + return result + where + g s = let (s', a) = f s in (s', ((s, s'), a)) + h e s = (s {items = updateIx i e s.items}, ()) + + updateIx :: Int -> a -> [a] -> [a] + updateIx 0 a (x:xs) = a : xs + updateIx n a (x:xs) = x : updateIx (pred n) a xs + updateIx _ _ [] = [] styles :: Text styles = "\ diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index ad091b3..187e3a3 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -35,21 +35,14 @@ newDynVar a = do ref <- liftIO $ newIORef a state \s -> (DynVar (SourceId s.next_id) ref, s {next_id = s.next_id + 1}) -elemVar :: MonadIO m => Int -> DynVar [a] -> a -> m (DynVar a) -elemVar i var a = do - ref <- liftIO $ newIORef a - return $ ElemVar var i ref +spyVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a +spyVar = SpyVar readVal :: DynVal a -> ClickM a -readVal (ConstVal a) = pure a -readVal (FromVar var) = readVar var -readVal (MapVal val f) = fmap f $ readVal val -readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) +readVal = Internal.readVal readVar :: DynVar a -> ClickM a -readVar (DynVar _ ref) = liftIO $ readIORef ref -readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var -readVar (ElemVar _ _ ref) = liftIO $ readIORef ref +readVar = Internal.readVar modifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a modifyVar var@(DynVar varId ref) f = do @@ -58,12 +51,8 @@ modifyVar var@(DynVar varId ref) f = do return a where g old = let (new, a) = f old in (new, (new, a)) -modifyVar (ElemVar var i _) f = modifyVar var $ overIx i f - where - overIx :: forall s a. Int -> (s -> (s, a)) -> [s] -> ([s], a) - overIx 0 f (x:xs) = let (s, a) = f x in (s : xs, a) - overIx n f (x:xs) = let (s, a) = overIx (pred n) f xs in (x : s, a) - overIx _ _ [] = error "ElemVar: invalid index" +modifyVar (SpyVar ufn var) f = + ufn (modifyVar var) f modifyVar (LensMap l var) f = modifyVar var (swap . l (swap . f)) modifyVar_ :: DynVar s -> (s -> s) -> ClickM () @@ -75,6 +64,19 @@ writeVar var s = modifyVar_ var $ const s subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () subscribe val k = reactive_ $ Internal.subscribe val k +modifyVarQuiet :: DynVar s -> (s -> (s, a)) -> ClickM a +modifyVarQuiet var@(DynVar varId ref) f = do + (newVal, a) <- liftIO $ atomicModifyIORef' ref g + return a + where + g s = let (s', a) = f s in (s', (s', a)) +modifyVarQuiet (SpyVar ufn var) f = + ufn (modifyVarQuiet var) f +modifyVarQuiet (LensMap l var) f = modifyVarQuiet var (swap . l (swap . f)) + +modifyVarQuiet_ :: DynVar s -> (s -> s) -> ClickM () +modifyVarQuiet_ var f = modifyVarQuiet var ((,()) . f) + -------------------------------------- -- OPERATIONS OVER evaluation_queue -- -------------------------------------- @@ -208,20 +210,19 @@ dyn val = do -- | Auxilliary datatype used in 'simpleList' implementation data ElemEnv a = ElemEnv - { elem_boundary :: VarId - , elem_state_ref :: DynVar a - , reactive_scope :: ResourceScope + { boundary :: VarId + , state_var :: DynVar a + , elem_scope :: ResourceScope } simpleList - :: forall a. DynVar [a] + :: forall a. DynVal [a] -- ^ Some dynamic data from the above scope -> (Int -> DynVar a -> HtmlM ()) -- ^ Function to build children widget. Accepts the index inside the -- collection and dynamic data for that particular element -> HtmlM () -simpleList listVar h = lift do - let listDyn = fromVar listVar +simpleList listDyn h = lift do internalStateRef <- liftIO $ newIORef ([] :: [ElemEnv a]) boundary <- insertBoundary let @@ -236,7 +237,7 @@ simpleList listVar h = lift do -- New list is longer, append new elements ([], x:xs) -> do e <- newElem idx x - exec e.elem_boundary e.reactive_scope $ h idx e.elem_state_ref + exec e.boundary e.elem_scope $ h idx e.state_var fmap (e:) $ setup (idx + 1) xs [] -- New list is shorter, delete the elements that no longer -- present in the new list @@ -245,19 +246,19 @@ simpleList listVar h = lift do return [] -- Update existing elements along the way (r:rs, y:ys) -> do - writeVar r.elem_state_ref y + writeVar r.state_var y fmap (r:) $ setup (idx + 1) ys rs newElem :: Int -> a -> ClickM (ElemEnv a) newElem i a = do - scope <- newScope - local (\s -> s {scope}) do - elem_state_ref <- elemVar i listVar a - elem_boundary <- insertBoundary - return ElemEnv {reactive_scope = scope, elem_state_ref, elem_boundary} + elem_scope <- newScope + local (\s -> s {scope = elem_scope}) do + state_var <- newDynVar a + boundary <- insertBoundary + return ElemEnv {elem_scope, state_var, boundary} finalizeElems :: Bool -> [ElemEnv a] -> ClickM () finalizeElems remove = mapM_ \ee -> do - when remove $ destroyBoundary ee.elem_boundary - freeScope True ee.reactive_scope + when remove $ destroyBoundary ee.boundary + freeScope True ee.elem_scope updateList new = do eenvs <- liftIO $ readIORef internalStateRef newEenvs <- setup 0 new eenvs diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 81725fe..855b25e 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -18,8 +18,8 @@ import Foreign.Ptr import Foreign.Storable import Unsafe.Coerce import Wasm.Compat.Prim -import Debug.Trace import Data.Text qualified as Text +import Control.Applicative import Clickable.FFI qualified as FFI import Clickable.Protocol @@ -81,6 +81,7 @@ installFinalizer :: ClickM () -> ResourceScope -> InternalState -> InternalState installFinalizer k scope s = s {finalizers = (scope, CustomFinalizer k) : s.finalizers} + subscribe :: DynVal a -> (a -> ClickM ()) -> @@ -91,6 +92,8 @@ subscribe (FromVar (DynVar varId _)) fn scope s = s {subscriptions} where subscriptions = newSub : s.subscriptions newSub = (scope, varId, fn . unsafeCoerce) +subscribe (FromVar (SpyVar _ var)) fn scope s = + subscribe (FromVar var) fn scope s subscribe (MapVal v f) fn scope s = subscribe v (fn . f) scope s subscribe (SplatVal fv av) fn scope s = subscribe av g scope $ subscribe fv f scope $ attachCb s @@ -106,11 +109,17 @@ subscribe (SplatVal fv av) fn scope s = , next_id = s.next_id + 1 } varid = SourceId s.next_id - readVal :: DynVal a -> ClickM a - readVal (ConstVal a) = pure a - readVal (FromVar (DynVar _ ref)) = liftIO $ readIORef ref - readVal (MapVal val f) = fmap f $ readVal val - readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) + +readVal :: DynVal a -> ClickM a +readVal (ConstVal a) = pure a +readVal (FromVar var) = readVar var +readVal (MapVal val f) = fmap f $ readVal val +readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) + +readVar :: DynVar a -> ClickM a +readVar (DynVar _ ref) = liftIO $ readIORef ref +readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var +readVar (SpyVar _ var) = readVar var sendMessage :: JSVal -> HaskellMessage -> IO JavaScriptMessage sendMessage receiveCb hmsg = do diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index 6144d32..fa7ea56 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -13,9 +13,13 @@ import Clickable.Protocol data DynVar a where DynVar :: SourceId -> IORef a -> DynVar a - ElemVar :: DynVar [a] -> Int -> IORef a -> DynVar a + SpyVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a LensMap :: Lens' s a -> DynVar s -> DynVar a +type UpdateFn s = forall a. (s -> (s, a)) -> ClickM a + +type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s + data DynVal a where ConstVal :: a -> DynVal a FromVar :: DynVar a -> DynVal a @@ -58,5 +62,3 @@ data InternalState = InternalState data FinalizerVal = CustomFinalizer (ClickM ()) | ScopeFinalizer ResourceScope - -type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s From a26a5e2aa13616f6618cec4a34e9ecbac251cb71 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 4 Apr 2024 10:03:52 +0400 Subject: [PATCH 22/64] TodoMVC popstate --- examples/charts/App.hs | 69 --------------------- examples/charts/Charts.hs | 102 -------------------------------- examples/charts/PairSelector.hs | 44 -------------- examples/charts/charts.hs | 13 ---- examples/charts/dev-server.hs | 8 --- examples/todomvc/App.hs | 25 ++++++++ examples/todomvc/JsMain.hs | 24 -------- examples/todomvc/TodoItem.hs | 30 +++++----- examples/todomvc/TodoList.hs | 54 ++++++++--------- examples/todomvc/dev.hs | 5 +- examples/todomvc/wasm.hs | 4 +- htmlt.cabal | 23 ------- src/Clickable/Core.hs | 62 ++++++++----------- src/Clickable/DOM.hs | 35 +++++++---- src/Clickable/Internal.hs | 17 +++--- src/Clickable/Types.hs | 2 +- 16 files changed, 128 insertions(+), 389 deletions(-) delete mode 100644 examples/charts/App.hs delete mode 100644 examples/charts/Charts.hs delete mode 100644 examples/charts/PairSelector.hs delete mode 100644 examples/charts/charts.hs delete mode 100644 examples/charts/dev-server.hs create mode 100644 examples/todomvc/App.hs delete mode 100644 examples/todomvc/JsMain.hs diff --git a/examples/charts/App.hs b/examples/charts/App.hs deleted file mode 100644 index 12a50a3..0000000 --- a/examples/charts/App.hs +++ /dev/null @@ -1,69 +0,0 @@ -module App where - -import Charts qualified as Charts -import Control.Monad.State -import Control.Concurrent -import Data.Proxy -import Data.Text (Text) -import Data.Text qualified as Text -import GHC.Generics -import Clickable -import Clickable.FFI - - -data AppInstance = AppInstance - { state_var :: DynVar AppTab - } deriving (Generic) - -data AppTab - = ChartsTab Charts.ChartInstance - | HelpTab - -new :: ClickM AppInstance -new = do - charts_instance <- Charts.new - state_var <- newDynVar $ ChartsTab charts_instance - return AppInstance - { state_var - } - -html :: AppInstance -> HtmlM () -html self = do - el "style" $ text styles - div_ do - button_ do - text "Open Charts" - on @"click" do - inst <- Charts.new - modifyVar_ self.state_var $ const $ ChartsTab inst - button_ do - text "Open Help" - on @"click" $ modifyVar_ self.state_var $ const HelpTab - button_ do - text "Open Modal" - on @"click" do - mvar <- liftIO newEmptyMVar - attachToBody do - p_ $ text "Content of the modal" - button_ do - text "Close" - on @"click" $ liftIO $ putMVar mvar "dljfhdlsfjh" - syncPoint - answer <- liftIO $ takeMVar mvar - -- consoleLog answer - return () - dyn $ self.state_var `mapVar` \case - ChartsTab inst -> Charts.html inst - HelpTab -> p_ $ text - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod \ - \tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim \ - \veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea \ - \commodo consequat. Duis aute irure dolor in reprehenderit in voluptate \ - \velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint \ - \occaecat cupidatat non proident, sunt in culpa qui officia deserunt \ - \mollit anim id est laborum." - -styles :: Text -styles = "\ - \ \ - \ " diff --git a/examples/charts/Charts.hs b/examples/charts/Charts.hs deleted file mode 100644 index 702230e..0000000 --- a/examples/charts/Charts.hs +++ /dev/null @@ -1,102 +0,0 @@ -module Charts where - -import Data.Text (Text) -import Data.Text qualified as Text -import GHC.Generics - -import Clickable -import Clickable.FFI -import PairSelector qualified as PairSelector - -------------------------------------------------------- --- EXAMPLE OF APPLICATION FEATURING FINANCIAL CHARTS -- -------------------------------------------------------- - -data ChartState = ChartState - { main_transform :: Transform2D - , mouse_position :: Point - , counter :: Int - } deriving (Show, Eq, Generic) - -data ChartInstance = ChartInstance - { state_var :: DynVar ChartState - , pair_selector_instance :: DynVar PairSelector.PairSelectorState - } deriving (Generic) - -new :: ClickM ChartInstance -new = do - pair_selector_instance <- PairSelector.new - state_var <- newDynVar ChartState - { main_transform = Transform2D 0 0 0 0 - , mouse_position = Point 0 0 - , counter = 0 - } - return ChartInstance {state_var, pair_selector_instance} - -html :: ChartInstance -> HtmlM () -html self = do - el "style" $ text styles - div_ [class_ "Charts-root"] do - h1_ $ text "Canvas with candle chart" - div_ do - PairSelector.html self.pair_selector_instance - div_ do - button_ do - text "Clickable this button" - on @"click" do - modifyVar_ self.state_var \s -> s {counter = s.counter + 1 } - button_ do - text "Print state" - on @"click" do - s <- readVar self.state_var - -- consoleLog $ Text.pack $ show s - return () - span_ [] $ dynText $ self.state_var `mapVar` \s -> - "You clicked " <> Text.pack (show s.counter) <> " times" - canvas_ [class_ "Charts-canvas"] $ return () - -styles :: Text -styles = "\ - \.Charts-root {\ - \ max-width: 900;\ - \ width: 100%\ - \ padding: 16px;\ - \ margin: 0 auto;\ - \}\ - \.Charts-canvas {\ - \ width: 100%;\ - \ height: 550px;\ - \ border: solid 1px black;\ - \}\ - \ " - -data Transform2D = Transform2D - { a :: Double -- ^ X scaling - , c :: Double -- ^ X translation - , e :: Double -- ^ Y scaling - , f :: Double -- ^ Y translation - } deriving (Show, Eq, Generic) - -data Point = Point - { point_x :: Double - , point_y :: Double - } deriving (Eq, Show, Generic) - --- setMouseCoords :: Point -> Edit ChartState --- setMouseCoords p = Fld (Proxy @"mouse_position") (Ins p) - - --- moveScreen :: Double -> Jet ChartState -> Jet ChartState --- moveScreen dir old = --- let --- beg = negate old.position.main_transform.c / old.position.main_transform.a --- end = (w - old.position.main_transform.c) / old.position.main_transform.a --- inc = (end - beg) * dir --- w = 1000 --- c = old.position.main_transform.c - --- (inc * old.position.main_transform.a) --- new = old.position --- { main_transform = old.position.main_transform {c} --- } --- in --- Jet new (Fld (Proxy @"main_transform") (Fld (Proxy @"c") (Ins c)) : old.velocity) diff --git a/examples/charts/PairSelector.hs b/examples/charts/PairSelector.hs deleted file mode 100644 index 6d01ac4..0000000 --- a/examples/charts/PairSelector.hs +++ /dev/null @@ -1,44 +0,0 @@ -module PairSelector where - -import Data.Text (Text) -import Data.Text qualified as Text -import Data.Function hiding (on) -import GHC.Generics - -import Clickable - -data TradingPair = TradingPair - { base :: Text - , quote :: Text - , exchange :: Text - } deriving (Show, Eq, Generic) - -data PairSelectorState = PairSelectorState - { selected_pair :: Maybe TradingPair - , options :: [TradingPair] - } deriving (Show, Eq, Generic) - -new :: ClickM (DynVar PairSelectorState) -new = - newDynVar PairSelectorState - { selected_pair = Nothing - , options = [] - } - -html :: DynVar PairSelectorState -> HtmlM () -html self = do - el "style" $ text styles - div_ [class_ "PairSelector-root"] do - button_ do - text "Select pair" - on @"click" $ modifyVar_ self \s -> case s.selected_pair of - Just _ -> s {selected_pair = Nothing} - Nothing -> s {selected_pair = Just $ TradingPair "BTC" "USDT" "MEXC"} - span_ $ dynText $ self `mapVar` \s -> s.selected_pair & maybe - "Nothing selected" - (("Selected pair: " <>) . Text.pack . show) - -styles :: Text -styles = "\ - \ \ - \ " diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs deleted file mode 100644 index 310e418..0000000 --- a/examples/charts/charts.hs +++ /dev/null @@ -1,13 +0,0 @@ -import Control.Monad.Reader -import Clickable -import GHC.Ptr -import GHC.Word -import "this" App qualified as App - -main :: IO () -main = return () - -foreign export ccall wasm_main :: Ptr Word8 -> IO () -wasm_main p = do - _ <- runApp p \_ -> attachToBody $ lift App.new >>= App.html - return () diff --git a/examples/charts/dev-server.hs b/examples/charts/dev-server.hs deleted file mode 100644 index 4441c9e..0000000 --- a/examples/charts/dev-server.hs +++ /dev/null @@ -1,8 +0,0 @@ -import Clickable -import Clickable.Main.DevServer -import Control.Monad.Reader - -import "this" App qualified as App - -main :: IO () -main = runServer \_ _ -> attachToBody $ lift App.new >>= App.html diff --git a/examples/todomvc/App.hs b/examples/todomvc/App.hs new file mode 100644 index 0000000..9068dd1 --- /dev/null +++ b/examples/todomvc/App.hs @@ -0,0 +1,25 @@ +module App where + +import Control.Monad.Trans +import Data.Maybe +import Clickable +import Clickable.Protocol + +import "this" TodoList qualified as TodoList +import "this" Utils + +app :: StartFlags -> ClickM () +app _ = do + items <- fromMaybe [] <$> readLocalStorage "todo-items" + stateVar <- TodoList.new items + installFinalizer do + s <- readVar stateVar + saveLocalStorage "todo-items" s.items + attachToBody do + el "style" $ text TodoList.styles + TodoList.html TodoList.TodoListConfig + { state_var = stateVar + } + lift $ connectResource popstateConnectArgs \loc -> do + let filter = fromMaybe TodoList.All $ TodoList.parseFilter loc.hash + modifyVar_ stateVar \s -> s {TodoList.filter} diff --git a/examples/todomvc/JsMain.hs b/examples/todomvc/JsMain.hs deleted file mode 100644 index 1ac4c31..0000000 --- a/examples/todomvc/JsMain.hs +++ /dev/null @@ -1,24 +0,0 @@ -module JsMain where - -import Data.Maybe -import Clickable -import Clickable.Protocol - -import "this" TodoList qualified as TodoList -import "this" Utils - -jsMain :: StartFlags -> ClickM () -jsMain _ = do - items <- fromMaybe [] <$> readLocalStorage "todo-items" - todoListStateRef <- TodoList.eval $ TodoList.InitAction items - installFinalizer do - tolistState <- readVar todoListStateRef - saveLocalStorage "todo-items" tolistState.items - attachToBody do - el "style" $ text TodoList.styles - TodoList.html TodoList.TodoListConfig - { state_ref = todoListStateRef - } - -- globalAddEventListener (Id "window") popstateEventArgs \loc -> do - -- let filter = fromMaybe TodoList.All $ TodoList.parseFilter loc.hash - -- modifyRef todoListStateRef \s -> s {TodoList.filter} diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index ae4e997..e9a5bff 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -8,7 +8,7 @@ import Clickable import Clickable.Protocol.Value data TodoItemConfig = TodoItemConfig - { state_ref :: DynVar TodoItemState + { state_var :: DynVar TodoItemState , is_hidden_dyn :: DynVal Bool , ask_delete_item :: ClickM () } @@ -27,26 +27,29 @@ data TodoItemAction a where CheckedAction :: TodoItemConfig -> Bool -> TodoItemAction () KeydownAction :: TodoItemConfig -> Int64 -> TodoItemAction () +emptyState :: TodoItemState +emptyState = TodoItemState "" False Nothing + eval :: TodoItemAction a -> ClickM a eval = \case CancelAction cfg -> - modifyVar_ cfg.state_ref \s -> s{editing=Nothing} + modifyVar_ cfg.state_var \s -> s{editing=Nothing} CommitAction cfg -> do - state <- readVar cfg.state_ref + state <- readVar cfg.state_var case state.editing of Just "" -> cfg.ask_delete_item Just t -> - modifyVar_ cfg.state_ref \s -> s {editing=Nothing, title = t} + modifyVar_ cfg.state_var \s -> s {editing=Nothing, title = t} Nothing -> pure () InputAction cfg newVal -> - modifyVar_ cfg.state_ref \s -> s{editing = Just newVal} + modifyVar_ cfg.state_var \s -> s{editing = Just newVal} DoubleClickAction cfg -> do - modifyVar_ cfg.state_ref \s -> s {editing = Just s.title} + modifyVar_ cfg.state_var \s -> s {editing = Just s.title} -- liftIO $ js_todoItemInputFocus targetEl CheckedAction cfg isChecked -> do - modifyVar_ cfg.state_ref \s -> s{completed = isChecked} + modifyVar_ cfg.state_var \s -> s{completed = isChecked} KeydownAction cfg key -> case key of 13 {- Enter -} -> eval (CommitAction cfg) 27 {- Escape -} -> eval (CancelAction cfg) @@ -55,18 +58,18 @@ eval = \case html :: TodoItemConfig -> HtmlM () html cfg = li_ do let - completedDyn = (.completed) <$> fromVar cfg.state_ref - editingDyn = isJust . (.editing) <$> fromVar cfg.state_ref - valueDyn = fromMaybe "" . (.editing) <$> fromVar cfg.state_ref + completedDyn = (.completed) <$> fromVar cfg.state_var + editingDyn = isJust . (.editing) <$> fromVar cfg.state_var + valueDyn = fromMaybe "" . (.editing) <$> fromVar cfg.state_var toggleClass "completed" completedDyn toggleClass "editing" editingDyn toggleClass "hidden" cfg.is_hidden_dyn div_ [class_ "view"] do on @"dblclick" $ eval $ DoubleClickAction cfg input_ [class_ "toggle", type_ "checkbox"] do - dynChecked $ (.completed) <$> fromVar cfg.state_ref + dynChecked $ (.completed) <$> fromVar cfg.state_var on @"checkbox/change" $ eval . CheckedAction cfg - label_ $ dynText $ (.title) <$> fromVar cfg.state_ref + label_ $ dynText $ (.title) <$> fromVar cfg.state_var button_ [class_ "destroy"] do on @"click" cfg.ask_delete_item input_ [class_ "edit", type_ "text"] do @@ -75,9 +78,6 @@ html cfg = li_ do on @"keydown" $ eval . KeydownAction cfg on @"blur" $ eval (CommitAction cfg) -emptyTodoItemState :: TodoItemState -emptyTodoItemState = TodoItemState "" False Nothing - instance ToJSValue TodoItemState where toJSValue s = Object [ ("title", toJSValue s.title) diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index 3ce9caa..574adc4 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -12,7 +12,7 @@ import "this" TodoItem qualified as TodoItem data TodoListConfig = TodoListConfig - { state_ref :: DynVar TodoListState + { state_var :: DynVar TodoListState } data TodoListState = TodoListState @@ -25,7 +25,6 @@ data Filter = All | Active | Completed deriving (Show, Eq) data TodoListAction a where - InitAction :: [TodoItem.TodoItemState] -> TodoListAction (DynVar TodoListState) ToggleAllAction :: TodoListConfig -> Bool -> TodoListAction () InputAction :: TodoListConfig -> Text -> TodoListAction () CommitAction :: TodoListConfig -> TodoListAction () @@ -33,47 +32,48 @@ data TodoListAction a where DeleteItemAction :: TodoListConfig -> Int -> TodoListAction () ClearCompletedAction :: TodoListConfig -> TodoListAction () +new :: [TodoItem.TodoItemState] -> ClickM (DynVar TodoListState) +new items = + newDynVar TodoListState + { title = "" + , items = items + , filter = All + } + eval :: TodoListAction a -> ClickM a eval = \case - InitAction items -> do - newDynVar TodoListState - { title = "" - , items = items - , filter = All - } ToggleAllAction cfg isChecked -> - modifyVar_ cfg.state_ref \s -> s + modifyVar_ cfg.state_var \s -> s { items = fmap (\i -> i {TodoItem.completed = isChecked}) s.items } InputAction cfg newVal -> do - modifyVar_ cfg.state_ref \s -> s {title = newVal} + modifyVar_ cfg.state_var \s -> s {title = newVal} CommitAction cfg -> do - title <- Text.strip . (.title) <$> readVar cfg.state_ref + title <- Text.strip . (.title) <$> readVar cfg.state_var case title of "" -> return () - t -> modifyVar_ cfg.state_ref \s -> s - { items = s.items <> [mkNewItem t] + t -> modifyVar_ cfg.state_var \s -> s + { items = s.items <> [mkNewTodo t] , title = "" } KeydownAction cfg key -> do case key of 13 {- Enter -} -> eval (CommitAction cfg) 27 {- Escape -} -> do - s <- readVar cfg.state_ref + s <- readVar cfg.state_var consoleLog $ Text.pack $ show s _ -> return () DeleteItemAction cfg itemIx -> - modifyVar_ cfg.state_ref \s -> s {items = deleteIx itemIx s.items} + modifyVar_ cfg.state_var \s -> s {items = deleteIx itemIx s.items} ClearCompletedAction cfg -> - modifyVar_ cfg.state_ref \s -> s + modifyVar_ cfg.state_var \s -> s {items = (List.filter (not . TodoItem.completed)) s.items} where deleteIx :: Int -> [a] -> [a] deleteIx _ [] = [] deleteIx i (a:as) | i == 0 = as | otherwise = a : deleteIx (i-1) as - mkNewItem t = - TodoItem.emptyTodoItemState {TodoItem.title = t} + mkNewTodo t = TodoItem.emptyState {TodoItem.title = t} html :: TodoListConfig -> HtmlM () html cfg = do @@ -87,7 +87,7 @@ html cfg = do headerWidget = header_ [class_ "header"] do h1_ (text "todos") input_ [class_ "new-todo", placeholder_ "What needs to be done?", autofocus_ True] do - dynValue $ (.title) <$> fromVar cfg.state_ref + dynValue $ (.title) <$> fromVar cfg.state_var on @"input" $ eval . InputAction cfg on @"keydown" $ eval . KeydownAction cfg mainWidget = section_ [class_ "main"] do @@ -100,9 +100,9 @@ html cfg = do ul_ [class_ "todo-list"] do simpleList itemsDyn \idx todoRef -> TodoItem.html $ TodoItem.TodoItemConfig - { TodoItem.state_ref = spyVar (todoItemUpdated cfg idx) todoRef + { TodoItem.state_var = overrideVar (todoItemUpdated cfg idx) todoRef , TodoItem.is_hidden_dyn = - isTodoItemHidden <$> fromVar cfg.state_ref <*> fromVar todoRef + isTodoItemHidden <$> fromVar cfg.state_var <*> fromVar todoRef , TodoItem.ask_delete_item = eval (DeleteItemAction cfg idx) } footerWidget = footer_ [class_ "footer"] do @@ -129,13 +129,13 @@ html cfg = do toggleClass "selected" $ filterSelectedDyn flt text $ Text.pack $ show flt hiddenDyn = - Prelude.null . (.items) <$> fromVar cfg.state_ref + Prelude.null . (.items) <$> fromVar cfg.state_var itemsLeftDyn = - countItemsLeft <$> fromVar cfg.state_ref + countItemsLeft <$> fromVar cfg.state_var filterSelectedDyn flt = - (==flt) . (.filter) <$> fromVar cfg.state_ref + (==flt) . (.filter) <$> fromVar cfg.state_var itemsDyn = - (.items) <$> fromVar cfg.state_ref + (.items) <$> fromVar cfg.state_var countItemsLeft TodoListState{items} = foldl (\acc TodoItem.TodoItemState{completed} -> if not completed then acc + 1 else acc) 0 items @@ -179,8 +179,8 @@ todoItemUpdated cfg i next f = do needsUpdate = old.completed /= new.completed -- Update TodoItemState inside the larger state if needsUpdate - then modifyVar cfg.state_ref $ h new - else modifyVarQuiet cfg.state_ref $ h new + then modifyVar cfg.state_var $ h new + else modifyVarQuiet cfg.state_var $ h new return result where g s = let (s', a) = f s in (s', ((s, s'), a)) diff --git a/examples/todomvc/dev.hs b/examples/todomvc/dev.hs index 6304257..dce83d8 100644 --- a/examples/todomvc/dev.hs +++ b/examples/todomvc/dev.hs @@ -1,6 +1,5 @@ import Clickable.Main.DevServer - -import "this" JsMain (jsMain) +import App (app) main :: IO () -main = runServer jsMain +main = runServer app diff --git a/examples/todomvc/wasm.hs b/examples/todomvc/wasm.hs index d0454ad..9152834 100644 --- a/examples/todomvc/wasm.hs +++ b/examples/todomvc/wasm.hs @@ -2,12 +2,12 @@ import Control.Monad.Reader import Clickable import GHC.Ptr import GHC.Word -import "this" JsMain qualified as App +import App (app) main :: IO () main = return () foreign export ccall wasm_main :: Ptr Word8 -> IO () wasm_main p = do - _ <- runApp p App.jsMain + _ <- runApp p app return () diff --git a/htmlt.cabal b/htmlt.cabal index 487c76d..04f9d32 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -157,29 +157,6 @@ executable htmlt-todomvc if !flag(examples) buildable: False -executable htmlt-charts - import: htmlt-common - hs-source-dirs: ./examples/charts - if arch(wasm32) - ghc-options: - -no-hs-main -optl-mexec-model=reactor - -optl-Wl,--export=hs_init,--export=wasm_main,--export=malloc - main-is: charts.hs - else - ghc-options: -threaded - main-is: dev-server.hs - build-depends: - base, - htmlt, - text, - mtl, - other-modules: - App - Charts - PairSelector - if !flag(examples) - buildable: False - -- executable htmlt-simple-routing -- import: htmlt-common -- main-is: simple-routing.hs diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 187e3a3..3bd247f 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -8,13 +8,12 @@ module Clickable.Core import Control.Monad import Control.Monad.Reader import Control.Monad.State -import Data.IORef -import Data.Tuple import Data.Function ((&)) +import Data.IORef +import Data.String import Data.Text (Text) import Data.Text qualified as Text -import Data.String -import Control.Applicative +import Data.Tuple import Clickable.Internal (reactive, reactive_) import Clickable.Internal qualified as Internal @@ -27,16 +26,13 @@ import Clickable.Protocol.Value qualified as Value -- OPERATIONS OVER DYNAMIC VARIABLES -- --------------------------------------- -mapVar :: DynVar a -> (a -> b) -> DynVal b -mapVar var = MapVal (FromVar var) - newDynVar :: a -> ClickM (DynVar a) newDynVar a = do ref <- liftIO $ newIORef a state \s -> (DynVar (SourceId s.next_id) ref, s {next_id = s.next_id + 1}) -spyVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a -spyVar = SpyVar +overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a +overrideVar = OverrideVar readVal :: DynVal a -> ClickM a readVal = Internal.readVal @@ -51,7 +47,7 @@ modifyVar var@(DynVar varId ref) f = do return a where g old = let (new, a) = f old in (new, (new, a)) -modifyVar (SpyVar ufn var) f = +modifyVar (OverrideVar ufn var) f = ufn (modifyVar var) f modifyVar (LensMap l var) f = modifyVar var (swap . l (swap . f)) @@ -70,7 +66,7 @@ modifyVarQuiet var@(DynVar varId ref) f = do return a where g s = let (s', a) = f s in (s', (s', a)) -modifyVarQuiet (SpyVar ufn var) f = +modifyVarQuiet (OverrideVar ufn var) f = ufn (modifyVarQuiet var) f modifyVarQuiet (LensMap l var) f = modifyVarQuiet var (swap . l (swap . f)) @@ -147,7 +143,7 @@ dynText val = do t <- lift $ readVal val v <- lift $ newVar lift $ modify $ f v t - lift $ subscribe val $ enqueueIfAlive scope . UpdateTextNode (Var v) + lift $ subscribe val $ enqueueExpr . UpdateTextNode (Var v) where f v t s = s {evaluation_queue = expr v t : s.evaluation_queue } expr v t = InsertNode (Arg 0 0) $ AssignVar v $ CreateTextNode t @@ -158,7 +154,7 @@ dynProp k val = do t <- lift $ readVal val v <- saveCurrentNode lift $ modify $ f t - lift $ subscribe val $ enqueueIfAlive scope . ElementProp (Var v) k . String + lift $ subscribe val $ enqueueExpr . ElementProp (Var v) k . String where f v s = s {evaluation_queue = expr v : s.evaluation_queue } expr v = ElementProp (Arg 0 0) k (String v) @@ -169,7 +165,7 @@ dynBoolProp k val = do t <- lift $ readVal val v <- saveCurrentNode lift $ modify $ f t - lift $ subscribe val $ enqueueIfAlive scope . ElementProp (Var v) k . Boolean + lift $ subscribe val $ enqueueExpr . ElementProp (Var v) k . Boolean where f v s = s {evaluation_queue = expr v : s.evaluation_queue } expr v = ElementProp (Arg 0 0) k (Boolean v) @@ -185,7 +181,7 @@ toggleClass className val = do updateCmd False = RemoveClassList (Var n) [className] updateCmd True = InsertClassList (Var n) [className] lift $ modify \s -> s {evaluation_queue = initCmd v s.evaluation_queue} - lift $ subscribe val $ enqueueIfAlive scope . updateCmd + lift $ subscribe val $ enqueueExpr . updateCmd --------------------- -- DYNAMIC CONTENT -- @@ -209,21 +205,24 @@ dyn val = do exec $ update newVal -- | Auxilliary datatype used in 'simpleList' implementation -data ElemEnv a = ElemEnv +data InternalElem a = InternalElem { boundary :: VarId , state_var :: DynVar a , elem_scope :: ResourceScope } +-- | Display dynamic collection of widgets. NOTE: changes in `DynVar +-- a` do not automatically propagate into the larger state. See +-- `OverrideVar` and todomvc example to see one way to upstream +-- changes into the larger state. simpleList :: forall a. DynVal [a] - -- ^ Some dynamic data from the above scope + -- ^ Dynamic collection -> (Int -> DynVar a -> HtmlM ()) - -- ^ Function to build children widget. Accepts the index inside the - -- collection and dynamic data for that particular element + -- ^ Build HTML for each element in the list -> HtmlM () simpleList listDyn h = lift do - internalStateRef <- liftIO $ newIORef ([] :: [ElemEnv a]) + internalStateRef <- liftIO $ newIORef ([] :: [InternalElem a]) boundary <- insertBoundary let exec boundary scope h = evalStateT h.unHtmlT Nothing @@ -231,7 +230,7 @@ simpleList listDyn h = lift do & local (\s -> s {scope}) exec1 boundary = htmlBuilder1 (Var boundary) - setup :: Int -> [a] -> [ElemEnv a] -> ClickM [ElemEnv a] + setup :: Int -> [a] -> [InternalElem a] -> ClickM [InternalElem a] setup idx new existing = case (existing, new) of ([], []) -> return [] -- New list is longer, append new elements @@ -248,14 +247,14 @@ simpleList listDyn h = lift do (r:rs, y:ys) -> do writeVar r.state_var y fmap (r:) $ setup (idx + 1) ys rs - newElem :: Int -> a -> ClickM (ElemEnv a) + newElem :: Int -> a -> ClickM (InternalElem a) newElem i a = do elem_scope <- newScope local (\s -> s {scope = elem_scope}) do state_var <- newDynVar a boundary <- insertBoundary - return ElemEnv {elem_scope, state_var, boundary} - finalizeElems :: Bool -> [ElemEnv a] -> ClickM () + return InternalElem {elem_scope, state_var, boundary} + finalizeElems :: Bool -> [InternalElem a] -> ClickM () finalizeElems remove = mapM_ \ee -> do when remove $ destroyBoundary ee.boundary freeScope True ee.elem_scope @@ -287,16 +286,6 @@ htmlBuilder1 builder content = do modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} return result -enqueueIfAlive :: ResourceScope -> Expr -> ClickM () -enqueueIfAlive scope e = modify \s -> - let - evaluation_queue = - -- if Map.member scope s.finalizers - if True - then e : s.evaluation_queue else s.evaluation_queue - in - s {evaluation_queue} - saveCurrentNode :: HtmlM VarId saveCurrentNode = do alreadySaved <- HtmlT get @@ -326,9 +315,8 @@ attachHtml rootElm contents = do evalStateT contents.unHtmlT Nothing <* modify (enqueueHtml savedQueue) where - enqueueHtml savedQueue s = s {evaluation_queue = e : savedQueue} - where - e = Lam (RevSeq (Arg 0 0 : s.evaluation_queue)) `Apply` [rootElm] + enqueueHtml saved s = s {evaluation_queue = e : saved} where + e = Lam (RevSeq (Arg 0 0 : s.evaluation_queue)) `Apply` [rootElm] saveQueue s = (s.evaluation_queue, s {evaluation_queue = []}) diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index e4c2c6e..c331ff6 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -29,7 +29,11 @@ addEventListener :: ConnectResourceArgs callback -> callback -> HtmlM () addEventListener args k = lift $ connectResource args k data ConnectResourceArgs callback = ConnectResourceArgs - { aquire_fn :: ResourceScope -> SourceId -> Expr + { aquire_resource :: ResourceScope -> SourceId -> Expr + -- ^ When evaluated, as a side-effect resulting `Expr` must + -- initialize some resource (could be DOM event, WebSocket + -- connection etc) also must return a function that frees that + -- resource , mk_callback :: callback -> Value -> ClickM () } @@ -40,7 +44,7 @@ connectResource args k = reactive_ \scope s -> callback = local (\e -> e {scope}) . args.mk_callback k sourceId = SourceId s.next_id newSub = (scope, sourceId, callback . unsafeCoerce) - connectExpr = ConnectResource scope $ args.aquire_fn scope sourceId + connectExpr = ConnectResource scope $ args.aquire_resource scope sourceId in s { evaluation_queue = connectExpr : s.evaluation_queue , subscriptions = newSub : s.subscriptions @@ -113,7 +117,7 @@ instance IsEventName "select/change" where -- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event pointerConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) pointerConnectArgs eventName = ConnectResourceArgs - { aquire_fn = \scope sourceId -> + { aquire_resource = \scope sourceId -> Eval (normalEventWrapper eventName defaultEventListenerOptions) `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k _ -> k @@ -122,7 +126,7 @@ pointerConnectArgs eventName = ConnectResourceArgs -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event submitConnectArgs :: ConnectResourceArgs (ClickM ()) submitConnectArgs = ConnectResourceArgs - { aquire_fn = \scope sourceId -> + { aquire_resource = \scope sourceId -> Eval (normalEventWrapper "submit" EventListenerOptions { prevent_default = True , stop_propagation = True @@ -133,7 +137,7 @@ submitConnectArgs = ConnectResourceArgs -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event inputConnectArgs :: Text -> ConnectResourceArgs (Text -> ClickM ()) inputConnectArgs eventName = ConnectResourceArgs - { aquire_fn = \scope sourceId -> Eval + { aquire_resource = \scope sourceId -> Eval ("(function(target, haskellCb){\n\ \ function listener(target){\n\ \ haskellCb(event.target.value);\n\ @@ -148,7 +152,7 @@ inputConnectArgs eventName = ConnectResourceArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event keyboardConnectArgs :: Text -> ConnectResourceArgs (Int64 -> ClickM ()) keyboardConnectArgs eventName = ConnectResourceArgs - { aquire_fn = \scope sourceId -> Eval ( + { aquire_resource = \scope sourceId -> Eval ( "(function(target, haskellCb){\n\ \ function listener(target){\n\ \ haskellCb(event.keyCode);\n\ @@ -165,7 +169,7 @@ keyboardConnectArgs eventName = ConnectResourceArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event focusConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) focusConnectArgs eventName = ConnectResourceArgs - { aquire_fn = \scope sourceId -> + { aquire_resource = \scope sourceId -> Eval (normalEventWrapper eventName defaultEventListenerOptions) `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k _ -> k @@ -174,7 +178,7 @@ focusConnectArgs eventName = ConnectResourceArgs -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event checkboxChangeConnectArgs :: ConnectResourceArgs (Bool -> ClickM ()) checkboxChangeConnectArgs = ConnectResourceArgs - { aquire_fn = \scope sourceId -> Eval + { aquire_resource = \scope sourceId -> Eval "(function(target, haskellCb){\n\ \ function listener(target){\n\ \ haskellCb(event.target.checked);\n\ @@ -188,7 +192,7 @@ checkboxChangeConnectArgs = ConnectResourceArgs -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event selectChangeConnectArgs :: ConnectResourceArgs (Text -> ClickM ()) selectChangeConnectArgs = ConnectResourceArgs - { aquire_fn = \scope sourceId -> Eval + { aquire_resource = \scope sourceId -> Eval "(function(target, haskellCb){\n\ \ function listener(target){\n\ \ haskellCb(event.target.value);\n\ @@ -237,13 +241,20 @@ data Location = Location -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event popstateConnectArgs :: ConnectResourceArgs (Location -> ClickM ()) popstateConnectArgs = ConnectResourceArgs - { aquire_fn = \scope sourceId -> Eval + { aquire_resource = \scope sourceId -> Eval "(function(target, haskellCb){\n\ \ function listener(){\n\ - \ haskellCb(location);\n\ + \ haskellCb({\n\ + \ protocol: location.protocol,\n\ + \ hostname: location.hostname,\n\ + \ port: location.port,\n\ + \ pathname: location.pathname,\n\ + \ search: location.search,\n\ + \ hash: location.hash\n\ + \ });\n\ \ }\n\ \ target.addEventListener('popstate', listener);\n\ \ return () => target.removeEventListener('popstate', listener);\n\ - \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + \})" `Apply` [Id "window", Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromJSValue event) k } diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 855b25e..dd17cde 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -1,13 +1,14 @@ module Clickable.Internal where +import Control.Applicative import Control.Monad.Reader import Control.Monad.State -import Data.Binary qualified as Binary import Data.Binary (Binary) -import Data.Foldable +import Data.Binary qualified as Binary import Data.ByteString as BS import Data.ByteString.Lazy qualified as BSL import Data.ByteString.Unsafe qualified as BSU +import Data.Foldable import Data.IORef import Data.List qualified as List import Data.Map qualified as Map @@ -18,8 +19,6 @@ import Foreign.Ptr import Foreign.Storable import Unsafe.Coerce import Wasm.Compat.Prim -import Data.Text qualified as Text -import Control.Applicative import Clickable.FFI qualified as FFI import Clickable.Protocol @@ -81,7 +80,6 @@ installFinalizer :: ClickM () -> ResourceScope -> InternalState -> InternalState installFinalizer k scope s = s {finalizers = (scope, CustomFinalizer k) : s.finalizers} - subscribe :: DynVal a -> (a -> ClickM ()) -> @@ -92,8 +90,10 @@ subscribe (FromVar (DynVar varId _)) fn scope s = s {subscriptions} where subscriptions = newSub : s.subscriptions newSub = (scope, varId, fn . unsafeCoerce) -subscribe (FromVar (SpyVar _ var)) fn scope s = +subscribe (FromVar (OverrideVar _ var)) fn scope s = subscribe (FromVar var) fn scope s +subscribe (FromVar (LensMap l var)) fn scope s = + subscribe (FromVar var) (fn . getConst . l Const) scope s subscribe (MapVal v f) fn scope s = subscribe v (fn . f) scope s subscribe (SplatVal fv av) fn scope s = subscribe av g scope $ subscribe fv f scope $ attachCb s @@ -119,7 +119,7 @@ readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) readVar :: DynVar a -> ClickM a readVar (DynVar _ ref) = liftIO $ readIORef ref readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var -readVar (SpyVar _ var) = readVar var +readVar (OverrideVar _ var) = readVar var sendMessage :: JSVal -> HaskellMessage -> IO JavaScriptMessage sendMessage receiveCb hmsg = do @@ -150,8 +150,7 @@ receiveMessage e jptr = do case jmsg of Start _value -> return () Return _value -> return () - TriggerCallbackMsg arg sourceId -> do - FFI.consoleLog $ Text.pack $ show (arg, sourceId) + TriggerCallbackMsg arg sourceId -> launchClickM e $ modify (unsafeTrigger sourceId arg) BeforeUnload -> return () where diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index fa7ea56..c5cbe74 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -13,7 +13,7 @@ import Clickable.Protocol data DynVar a where DynVar :: SourceId -> IORef a -> DynVar a - SpyVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a + OverrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a LensMap :: Lens' s a -> DynVar s -> DynVar a type UpdateFn s = forall a. (s -> (s, a)) -> ClickM a From d77a892173b092387b8232d65f7930f4fb189b7a Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 4 Apr 2024 13:29:47 +0400 Subject: [PATCH 23/64] WASM message exchange mechanism --- examples/todomvc/wasm.hs | 6 +-- htmlt.cabal | 2 +- jsbits/ffi.ts | 7 ++-- jsbits/jsffi.js | 16 +------- jsbits/prelude.js | 2 +- src/Clickable.hs | 1 - src/Clickable/FFI.hs | 13 ++----- src/Clickable/Internal.hs | 68 ++++----------------------------- src/Clickable/Main.hs | 39 ------------------- src/Clickable/Main/DevServer.hs | 15 +++----- src/Clickable/Main/WASM.hs | 60 +++++++++++++++++++++++++++++ 11 files changed, 86 insertions(+), 143 deletions(-) delete mode 100644 src/Clickable/Main.hs create mode 100644 src/Clickable/Main/WASM.hs diff --git a/examples/todomvc/wasm.hs b/examples/todomvc/wasm.hs index 9152834..b8461b5 100644 --- a/examples/todomvc/wasm.hs +++ b/examples/todomvc/wasm.hs @@ -1,5 +1,5 @@ import Control.Monad.Reader -import Clickable +import Clickable.Main.WASM import GHC.Ptr import GHC.Word import App (app) @@ -8,6 +8,4 @@ main :: IO () main = return () foreign export ccall wasm_main :: Ptr Word8 -> IO () -wasm_main p = do - _ <- runApp p app - return () +wasm_main = runApp app diff --git a/htmlt.cabal b/htmlt.cabal index 04f9d32..b54ac00 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -85,7 +85,7 @@ library Clickable.DOM Clickable.Element Clickable.Property - Clickable.Main + Clickable.Main.WASM Clickable.Types Clickable.Internal Clickable.Protocol diff --git a/jsbits/ffi.ts b/jsbits/ffi.ts index e367626..4c55dbb 100644 --- a/jsbits/ffi.ts +++ b/jsbits/ffi.ts @@ -42,13 +42,13 @@ export function storeBuffer(exports: HaskellExports, u8array: Uint8Array): Haske type SendMessageCallback = (jptr: HaskellPointer) => void; -export function evalMessageFFI(javascriptMessageCallback: SendMessageCallback, exports: HaskellExports, ptr: HaskellPointer): HaskellPointer { +export function evalMessage(exports: HaskellExports, ptr: HaskellPointer): HaskellPointer { const inbuf = loadBuffer(exports, ptr); const haskMsg = p.haskellMessage.decode(inbuf); const jsCallback = (jsmsg: JavaScriptMessage, _argScope: List) => { const outbuf = p.javascriptMessage.encode(jsmsg); const ptr = storeBuffer(exports, outbuf); - javascriptMessageCallback(ptr); + exports.wasm_main(ptr); }; switch (haskMsg.tag) { case HaskellMessageTag.EvalExpr: { @@ -93,7 +93,8 @@ export async function startWasm(wasmUri: string, startFlags: unknown = null) { await inst.exports.hs_init(); const startFlagsValue = p.unknownToValue(startFlags); - const startFlagsBuffer = p.jvalue.encode(startFlagsValue); + const startFlagsMessage: JavaScriptMessage = { tag: JavaScriptMessageTag.Start, 0: startFlagsValue }; + const startFlagsBuffer = p.javascriptMessage.encode(startFlagsMessage); const startFlagsPtr = storeBuffer(__exports, startFlagsBuffer); // @ts-ignore diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index faff439..62432b1 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -1,4 +1,4 @@ -import { evalMessageFFI } from './ffi'; +import { evalMessage } from './ffi'; // This file implements the JavaScript runtime logic for Haskell // modules that use JSFFI. It is not an ESM module, but the template @@ -101,18 +101,6 @@ getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, -ZC2ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => ((a1) => __exports.ghczuwasmzujsffiZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC($1,a1)), -ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => (evalMessageFFI($1, __exports, $2)), -ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => ($1.reject(new WebAssembly.RuntimeError($2))), -ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1) => ($1.resolve()), -ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: () => {let res, rej; const p = new Promise((resolve, reject) => { res = resolve; rej = reject; }); p.resolve = res; p.reject = rej; return p;}, -ZC21ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC: ($1,$2) => (__ghc_wasm_jsffi_finalization_registry.register($1, $2, $1)), -ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => (`${$1.stack ? $1.stack : $1}`), -ZC1ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2) => ((new TextDecoder('utf-8', {fatal: true})).decode(new Uint8Array(__exports.memory.buffer, $1, $2))), -ZC2ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1,$2,$3) => ((new TextEncoder()).encodeInto($1, new Uint8Array(__exports.memory.buffer, $2, $3)).written), -ZC3ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => ($1.length), -ZC4ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC: ($1) => {if (!__ghc_wasm_jsffi_finalization_registry.unregister($1)) { throw new WebAssembly.RuntimeError('js_callback_unregister'); }}, -ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziConcziInternalZC: async ($1) => (new Promise(res => setTimeout(res, $1 / 1000))), -ZC18ZCghczminternalZCGHCziInternalziWasmziPrimziImportsZC: ($1,$2) => ($1.then(() => __exports.rts_promiseResolveUnit($2), err => __exports.rts_promiseReject($2, err))), +ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => (evalMessage(__exports, $1)), }; }; diff --git a/jsbits/prelude.js b/jsbits/prelude.js index dc9d257..bf957f7 100644 --- a/jsbits/prelude.js +++ b/jsbits/prelude.js @@ -1,4 +1,4 @@ -import { evalMessageFFI } from './ffi'; +import { evalMessage } from './ffi'; // This file implements the JavaScript runtime logic for Haskell // modules that use JSFFI. It is not an ESM module, but the template diff --git a/src/Clickable.hs b/src/Clickable.hs index 431b77e..028a511 100644 --- a/src/Clickable.hs +++ b/src/Clickable.hs @@ -3,7 +3,6 @@ module Clickable (module Exports) where import Clickable.DOM as Exports import Clickable.Core as Exports import Clickable.Element as Exports -import Clickable.Main as Exports import Clickable.Property as Exports import Clickable.Types as Exports import Wasm.Compat.Prim as Exports diff --git a/src/Clickable/FFI.hs b/src/Clickable/FFI.hs index 75b4cc7..20c3c8f 100644 --- a/src/Clickable/FFI.hs +++ b/src/Clickable/FFI.hs @@ -22,20 +22,15 @@ consoleLog (Text (ByteArray arr) off len) = liftIO do js_consoleLog (Ptr addr `plusPtr` off) len #if !defined(wasm32_HOST_ARCH) -js_evalMessageFFI :: JSVal -> Ptr Word8 -> IO (Ptr Word8) -js_evalMessageFFI = undefined - -js_exportCallback :: (Ptr Word8 {- JavaScriptMessage -} -> IO ()) -> IO JSVal -js_exportCallback = undefined +js_evalMessage :: Ptr Word8 -> IO (Ptr Word8) +js_evalMessage = undefined js_consoleLog :: Ptr Word8 -> Int -> IO () js_consoleLog = undefined #else foreign import javascript unsafe - "evalMessageFFI($1, __exports, $2)" - js_evalMessageFFI :: JSVal -> Ptr Word8 {- HaskellMessage -} -> IO (Ptr Word8 {- JavaScriptMessage -}) -foreign import javascript "wrapper" - js_exportCallback :: (Ptr Word8 {- JavaScriptMessage -} -> IO ()) -> IO JSVal + "evalMessage(__exports, $1)" + js_evalMessage :: Ptr Word8 {- HaskellMessage -} -> IO (Ptr Word8 {- JavaScriptMessage -}) foreign import javascript unsafe "console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));" js_consoleLog :: Ptr Word8 -> Int -> IO () diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index dd17cde..2bceeb9 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -14,27 +14,21 @@ import Data.List qualified as List import Data.Map qualified as Map import Data.Word import Foreign.Marshal.Alloc qualified as Alloc -import Foreign.Marshal.Utils import Foreign.Ptr import Foreign.Storable import Unsafe.Coerce -import Wasm.Compat.Prim -import Clickable.FFI qualified as FFI import Clickable.Protocol import Clickable.Types -emptyInternalState :: InternalState -emptyInternalState = InternalState [] [] Map.empty [] 0 +emptyState :: InternalState +emptyState = InternalState [] [] Map.empty [] 0 -newInternalEnv :: IO InternalEnv -newInternalEnv = mdo - let state = emptyInternalState - let scope = ResourceScope state.next_id - internal_state_ref <- newIORef state {next_id = state.next_id + 1} - receiveCb <- FFI.js_exportCallback $ receiveMessage env - let env = InternalEnv {internal_state_ref, scope, send_message = sendMessage receiveCb} - return env +newInternalEnv :: (HaskellMessage -> IO JavaScriptMessage) -> IO InternalEnv +newInternalEnv send_message = do + let scope = ResourceScope emptyState.next_id + internal_state_ref <- newIORef emptyState {next_id = emptyState.next_id + 1} + return InternalEnv {internal_state_ref, scope, send_message} -- | Unsafe because there is no gurantee that @a@ matches @a@ in -- correspoding @DynVar a@ where SourceId comes from @@ -121,45 +115,6 @@ readVar (DynVar _ ref) = liftIO $ readIORef ref readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var readVar (OverrideVar _ var) = readVar var -sendMessage :: JSVal -> HaskellMessage -> IO JavaScriptMessage -sendMessage receiveCb hmsg = do - hptr <- storeByteString $ BSL.toStrict $ Binary.encode hmsg - jptr <- FFI.js_evalMessageFFI receiveCb hptr - Alloc.free hptr - Binary.decode . BSL.fromStrict <$> loadByteString jptr - where - storeByteString :: ByteString -> IO (Ptr a) - storeByteString bs = do - let len = BS.length bs - dest <- Alloc.callocBytes (len + 8) - poke @Word64 dest (fromIntegral len) - BSU.unsafeUseAsCStringLen bs $ \(src, _) -> - copyBytes (dest `plusPtr` 8) src len - return (castPtr dest) - - loadByteString :: Ptr a -> IO ByteString - loadByteString ptr = do - len <- peek @Word64 (castPtr ptr) - let contentPtr = ptr `plusPtr` 8 - BSU.unsafePackCStringFinalizer contentPtr (fromIntegral len) (Alloc.free ptr) - -receiveMessage :: InternalEnv -> Ptr Word8 -> IO () -receiveMessage e jptr = do - jbytes <- loadByteString jptr - let jmsg = Binary.decode $ BSL.fromStrict jbytes - case jmsg of - Start _value -> return () - Return _value -> return () - TriggerCallbackMsg arg sourceId -> - launchClickM e $ modify (unsafeTrigger sourceId arg) - BeforeUnload -> return () - where - loadByteString :: Ptr a -> IO ByteString - loadByteString ptr = do - len <- peek @Word64 (castPtr ptr) - let contentPtr = ptr `plusPtr` 8 - BSU.unsafePackCStringFinalizer contentPtr (fromIntegral len) (Alloc.free ptr) - launchClickM :: InternalEnv -> ClickM a -> IO a launchClickM env = flip runReaderT env . unClickT . (<* syncPoint) . trampoline @@ -208,12 +163,3 @@ data ClientMessage -- ^ Bypass protocol and inject a command directly into the -- DevServer instance (useful for delivering notifications under -- devserver) - -loadMessage :: Binary msg => Ptr a -> IO msg -loadMessage = fmap (Binary.decode . BSL.fromStrict) . loadByteString - where - loadByteString :: Ptr a -> IO ByteString - loadByteString ptr = do - len <- peek @Word64 (castPtr ptr) - let contentPtr = ptr `plusPtr` 8 - BSU.unsafePackCStringFinalizer contentPtr (fromIntegral len) (Alloc.free ptr) diff --git a/src/Clickable/Main.hs b/src/Clickable/Main.hs deleted file mode 100644 index 925714a..0000000 --- a/src/Clickable/Main.hs +++ /dev/null @@ -1,39 +0,0 @@ -module Clickable.Main where - -import GHC.Generics -import Clickable.Core -import Clickable.Types -import Clickable.Internal -import Clickable.Protocol -import Wasm.Compat.Prim -import Data.Word -import GHC.Ptr - --- data AttachOptions = AttachOptions --- { internal_env :: InternalEnv --- , dom_builder :: JSVal --- } deriving Generic - --- | Needed to manually finalize and detach the application -data RunningApp = RunningApp - { internal_env :: InternalEnv - , dom_bracket :: JSVal - } deriving Generic - --- attachWithOptions :: AttachOptions -> HtmlM a -> IO (a, RunningApp) --- attachWithOptions opt app = do --- domBracket <- js_insertBrackets opt.dom_builder --- result <- launchHtmlM domBracket opt.internal_env app --- let runApp = RunningApp opt.internal_env domBracket --- return (result, runApp) - -runApp :: Ptr Word8 -> (StartFlags -> ClickM a) -> IO a -runApp p app = do - env <- newInternalEnv - startFlags <- loadMessage p - launchClickM env $ app startFlags <* syncPoint - --- detach :: RunningApp -> IO () --- detach app = do --- launchClickM app.internal_env $ freeScope True app.internal_env.scope --- js_removeBrackets app.dom_bracket diff --git a/src/Clickable/Main/DevServer.hs b/src/Clickable/Main/DevServer.hs index 5ef9de2..a684032 100644 --- a/src/Clickable/Main/DevServer.hs +++ b/src/Clickable/Main/DevServer.hs @@ -218,15 +218,10 @@ websocketApp opt p = (Map.insert connection_id connInfo m, connInfo) return connInfo newInternalEnv :: Connection -> MVar Value -> IO InternalEnv - newInternalEnv conn resultMvar = do - let scope = ResourceScope Internal.emptyInternalState.next_id - internal_state_ref <- newIORef Internal.emptyInternalState - {next_id = Internal.emptyInternalState.next_id + 1} - let - sendMessage haskMessage = do - sendDataMessage conn . Binary $ Binary.encode haskMessage - Return <$> takeMVar resultMvar - return InternalEnv {internal_state_ref, scope, send_message = sendMessage} + newInternalEnv conn resultMvar = + Internal.newInternalEnv \haskMessage -> do + sendDataMessage conn . Binary $ Binary.encode haskMessage + Return <$> takeMVar resultMvar in bracket acceptConn dropConn \connInfo -> withPingThread connInfo.connection 30 (pure ()) $ loop connInfo @@ -310,4 +305,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>x,Gk:()=>y,PV:()=>w,Tf:()=>O,YE:()=>m,YO:()=>M,Yj:()=>T,b9:()=>D,g1:()=>P,tB:()=>C});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class d extends _{constructor(e){super(),this._self=e}}class f extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return h(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof d)return E(e._self,t);if(e instanceof f){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=h(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof d)return g(e._self,t,r);if(e instanceof f){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function h(e){return Math.ceil(Math.log2(e)/8)}const m=new a,y=new s,x=new i,T=new c,D=new o;function M(e){return new l(e)}function P(e){return new p(e)}function O(e){return new u(e)}function w(...e){return new f(e)}function C(e){const t=new d(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,i1:()=>jvalue,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Add=11]=\"Add\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const d=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(d);const{ret:f,fd_obj:E}=o.fds[e].path_open(t,d,_,a,i,c);if(0!=f)return f;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class d{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class f{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new f;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new d,r=new FinalizationRegistry((t=>e.rts_freeStablePtr(t)));return{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>r=>e.ghczuwasmzujsffiZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC(t,r),ZC3ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>function(e,t,r){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(t,r),_=g.sy.decode(n),a=(r,n)=>{const _=g.bR.encode(r),a=b(t,_);e(a)};switch(_.tag){case g.I4.EvalExpr:{const e=g.wL(a,[globalThis,null],null,_.expr),r={tag:g.dB.Return,0:g.bp(e)},n=g.bR.encode(r);return b(t,n)}case g.I4.HotReload:{window.location.reload();const e={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(e);return b(t,r)}case g.I4.Halt:{const e={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(e);return b(t,r)}}}(t,e,r),ZC9ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC:(e,t)=>e.reject(new WebAssembly.RuntimeError(t)),ZC19ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC:e=>e.resolve(),ZC20ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC:()=>{let e,t;const r=new Promise(((r,n)=>{e=r,t=n}));return r.resolve=e,r.reject=t,r},ZC21ZCghczminternalZCGHCziInternalziWasmziPrimziExportsZC:(e,t)=>r.register(e,t,e),ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:e=>`${e.stack?e.stack:e}`,ZC1ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:(t,r)=>new TextDecoder(\"utf-8\",{fatal:!0}).decode(new Uint8Array(e.memory.buffer,t,r)),ZC2ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:(t,r,n)=>(new TextEncoder).encodeInto(t,new Uint8Array(e.memory.buffer,r,n)).written,ZC3ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:e=>e.length,ZC4ZCghczminternalZCGHCziInternalziWasmziPrimziTypesZC:e=>{if(!r.unregister(e))throw new WebAssembly.RuntimeError(\"js_callback_unregister\")},ZC0ZCghczminternalZCGHCziInternalziWasmziPrimziConcziInternalZC:async e=>new Promise((t=>setTimeout(t,e/1e3))),ZC18ZCghczminternalZCGHCziInternalziWasmziPrimziImportsZC:(t,r)=>t.then((()=>e.rts_promiseResolveUnit(r)),(t=>e.rts_promiseReject(r,t)))}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let h={};var m=__webpack_require__(366);function y(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,x,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,m.G)(t)}))}const x=[window,null];function T(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(h)}),a=g.bp(t),s=g.i1.encode(a),i=b(h,s);Object.assign(h,_.exports),r.initialize(_),yield _.exports.hs_init(),yield _.exports.wasm_main(i)}))},window.startClient=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield T(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield y(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield T(t.data);y(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>m,Gk:()=>x,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>T,b9:()=>D,g1:()=>O,tB:()=>U});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class d extends _{constructor(e){super(),this._self=e}}class f extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return y(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof d)return E(e._self,t);if(e instanceof f){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=y(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof d)return g(e._self,t,r);if(e instanceof f){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function y(e){return Math.ceil(Math.log2(e)/8)}const h=new a,x=new s,m=new i,T=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new f(e)}function U(e){const t=new d(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Add=11]=\"Add\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const d=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(d);const{ret:f,fd_obj:E}=o.fds[e].path_open(t,d,_,a,i,c);if(0!=f)return f;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class d{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class f{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new f;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new d;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_main(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};var h=__webpack_require__(366);function x(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,m,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}const m=[window,null];function T(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(y)});Object.assign(y,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(y,i);yield _.exports.wasm_main(o)}))},window.startClient=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield T(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield x(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield T(t.data);x(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" diff --git a/src/Clickable/Main/WASM.hs b/src/Clickable/Main/WASM.hs new file mode 100644 index 0000000..d7f5701 --- /dev/null +++ b/src/Clickable/Main/WASM.hs @@ -0,0 +1,60 @@ +module Clickable.Main.WASM where + +import Control.Monad.State +import Data.Binary (Binary) +import Data.Binary qualified as Binary +import Data.ByteString as BS +import Data.ByteString.Lazy qualified as BSL +import Data.ByteString.Unsafe qualified as BSU +import Data.Word +import Foreign.Marshal.Alloc qualified as Alloc +import Foreign.Marshal.Utils +import Foreign.Ptr +import Foreign.Storable +import System.IO.Unsafe + +import Clickable.FFI qualified as FFI +import Clickable.Protocol +import Clickable.Core +import Clickable.Internal qualified as Internal +import Clickable.Types + +runApp :: (StartFlags -> ClickM ()) -> Ptr Word8 -> IO () +runApp app p = mdo + jmsg <- loadMessage p + case jmsg of + Start flags -> + launchClickM internalEnv $ app flags <* syncPoint + Return _value -> return () + TriggerCallbackMsg arg sourceId -> + launchClickM internalEnv $ modify $ Internal.unsafeTrigger sourceId arg + BeforeUnload -> + launchClickM internalEnv $ freeScope True $ ResourceScope Internal.emptyState.next_id + +internalEnv :: InternalEnv +internalEnv = unsafePerformIO $ Internal.newInternalEnv sendMessage + +sendMessage :: HaskellMessage -> IO JavaScriptMessage +sendMessage hmsg = do + hptr <- storeByteString $ BSL.toStrict $ Binary.encode hmsg + jptr <- FFI.js_evalMessage hptr + Alloc.free hptr + loadMessage jptr + where + storeByteString :: ByteString -> IO (Ptr a) + storeByteString bs = do + let len = BS.length bs + dest <- Alloc.callocBytes (len + 8) + poke @Word64 dest (fromIntegral len) + BSU.unsafeUseAsCStringLen bs $ \(src, _) -> + copyBytes (dest `plusPtr` 8) src len + return (castPtr dest) + +loadMessage :: Binary msg => Ptr a -> IO msg +loadMessage = fmap (Binary.decode . BSL.fromStrict) . loadByteString + where + loadByteString :: Ptr a -> IO ByteString + loadByteString ptr = do + len <- peek @Word64 (castPtr ptr) + let contentPtr = ptr `plusPtr` 8 + BSU.unsafePackCStringFinalizer contentPtr (fromIntegral len) (Alloc.free ptr) From 366aa47617318ba8cdf639a5463abf23f921be64 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 4 Apr 2024 13:40:07 +0400 Subject: [PATCH 24/64] Renaming --- examples/todomvc/dev.hs | 4 +-- examples/todomvc/wasm.hs | 6 ++-- htmlt.cabal | 10 +++--- jsbits/{devserver.ts => dev.ts} | 0 jsbits/index.js | 8 ++--- jsbits/jsffi.js | 2 +- jsbits/prelude.js | 2 +- jsbits/{ffi.ts => wasm.ts} | 15 ++++++--- src/Clickable/Main/{DevServer.hs => Dev.hs} | 34 ++++++++++----------- src/Clickable/Main/{WASM.hs => Wasm.hs} | 6 ++-- 10 files changed, 46 insertions(+), 41 deletions(-) rename jsbits/{devserver.ts => dev.ts} (100%) rename jsbits/{ffi.ts => wasm.ts} (89%) rename src/Clickable/Main/{DevServer.hs => Dev.hs} (62%) rename src/Clickable/Main/{WASM.hs => Wasm.hs} (94%) diff --git a/examples/todomvc/dev.hs b/examples/todomvc/dev.hs index dce83d8..9dfe642 100644 --- a/examples/todomvc/dev.hs +++ b/examples/todomvc/dev.hs @@ -1,5 +1,5 @@ -import Clickable.Main.DevServer +import Clickable.Main.Dev import App (app) main :: IO () -main = runServer app +main = runDev app diff --git a/examples/todomvc/wasm.hs b/examples/todomvc/wasm.hs index b8461b5..a5ef076 100644 --- a/examples/todomvc/wasm.hs +++ b/examples/todomvc/wasm.hs @@ -1,5 +1,5 @@ import Control.Monad.Reader -import Clickable.Main.WASM +import Clickable.Main.Wasm import GHC.Ptr import GHC.Word import App (app) @@ -7,5 +7,5 @@ import App (app) main :: IO () main = return () -foreign export ccall wasm_main :: Ptr Word8 -> IO () -wasm_main = runApp app +foreign export ccall wasm_app :: Ptr Word8 -> IO () +wasm_app = runWasm app diff --git a/htmlt.cabal b/htmlt.cabal index b54ac00..b7b7909 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -85,7 +85,7 @@ library Clickable.DOM Clickable.Element Clickable.Property - Clickable.Main.WASM + Clickable.Main.Wasm Clickable.Types Clickable.Internal Clickable.Protocol @@ -107,7 +107,7 @@ library ghc-prim, if !arch(wasm32) exposed-modules: - Clickable.Main.DevServer + Clickable.Main.Dev build-depends: async, foreign-store, @@ -124,7 +124,7 @@ library -- hs-source-dirs: ./examples/counter -- ghc-options: -- -no-hs-main -optl-mexec-model=reactor --- -optl-Wl,--export=hs_init,--export=wasm_main +-- -optl-Wl,--export=hs_init,--export=wasm_app -- build-depends: -- base, -- htmlt, @@ -140,7 +140,7 @@ executable htmlt-todomvc if arch(wasm32) ghc-options: -no-hs-main -optl-mexec-model=reactor - -optl-Wl,--export=hs_init,--export=wasm_main,--export=malloc + -optl-Wl,--export=hs_init,--export=wasm_app,--export=malloc main-is: wasm.hs else ghc-options: -threaded @@ -163,7 +163,7 @@ executable htmlt-todomvc -- hs-source-dirs: ./examples/simple-routing -- ghc-options: -- -no-hs-main -optl-mexec-model=reactor --- -optl-Wl,--export=hs_init,--export=wasm_main +-- -optl-Wl,--export=hs_init,--export=wasm_app -- other-modules: -- Assets -- Router diff --git a/jsbits/devserver.ts b/jsbits/dev.ts similarity index 100% rename from jsbits/devserver.ts rename to jsbits/dev.ts diff --git a/jsbits/index.js b/jsbits/index.js index ee2361c..d24c9b9 100644 --- a/jsbits/index.js +++ b/jsbits/index.js @@ -1,5 +1,5 @@ -import * as ffi from './ffi'; -import * as devserver from './devserver'; +import * as wasm from './wasm'; +import * as dev from './dev'; -window.startWasm = ffi.startWasm; -window.startClient = devserver.startClient; +window.startWasm = wasm.startWasm; +window.startDev = devserver.startDev; diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js index 62432b1..807eabc 100644 --- a/jsbits/jsffi.js +++ b/jsbits/jsffi.js @@ -1,4 +1,4 @@ -import { evalMessage } from './ffi'; +import { evalMessage } from './wasm'; // This file implements the JavaScript runtime logic for Haskell // modules that use JSFFI. It is not an ESM module, but the template diff --git a/jsbits/prelude.js b/jsbits/prelude.js index bf957f7..9f99b83 100644 --- a/jsbits/prelude.js +++ b/jsbits/prelude.js @@ -1,4 +1,4 @@ -import { evalMessage } from './ffi'; +import { evalMessage } from './wasm'; // This file implements the JavaScript runtime logic for Haskell // modules that use JSFFI. It is not an ESM module, but the template diff --git a/jsbits/ffi.ts b/jsbits/wasm.ts similarity index 89% rename from jsbits/ffi.ts rename to jsbits/wasm.ts index 4c55dbb..bad25cd 100644 --- a/jsbits/ffi.ts +++ b/jsbits/wasm.ts @@ -8,7 +8,7 @@ export type HaskellPointer = number; export type HaskellExports = { hs_init: () => void; - wasm_main: (flags: HaskellPointer) => void; + wasm_app: (flags: HaskellPointer) => void; malloc: (size: number) => HaskellPointer; memory: WebAssembly.Memory; }; @@ -40,15 +40,13 @@ export function storeBuffer(exports: HaskellExports, u8array: Uint8Array): Haske return ptr; } -type SendMessageCallback = (jptr: HaskellPointer) => void; - export function evalMessage(exports: HaskellExports, ptr: HaskellPointer): HaskellPointer { const inbuf = loadBuffer(exports, ptr); const haskMsg = p.haskellMessage.decode(inbuf); const jsCallback = (jsmsg: JavaScriptMessage, _argScope: List) => { const outbuf = p.javascriptMessage.encode(jsmsg); const ptr = storeBuffer(exports, outbuf); - exports.wasm_main(ptr); + exports.wasm_app(ptr); }; switch (haskMsg.tag) { case HaskellMessageTag.EvalExpr: { @@ -98,5 +96,12 @@ export async function startWasm(wasmUri: string, startFlags: unknown = null) { const startFlagsPtr = storeBuffer(__exports, startFlagsBuffer); // @ts-ignore - await inst.exports.wasm_main(startFlagsPtr); + await inst.exports.wasm_app(startFlagsPtr); + + window.addEventListener("beforeunload", () => { + const unloadMessage: JavaScriptMessage = { tag: JavaScriptMessageTag.BeforeUnload }; + const unloadBuffer = p.javascriptMessage.encode(unloadMessage); + const unloadPtr = storeBuffer(__exports, unloadBuffer); + __exports.wasm_app(unloadPtr); + }); }; diff --git a/src/Clickable/Main/DevServer.hs b/src/Clickable/Main/Dev.hs similarity index 62% rename from src/Clickable/Main/DevServer.hs rename to src/Clickable/Main/Dev.hs index a684032..5614d24 100644 --- a/src/Clickable/Main/DevServer.hs +++ b/src/Clickable/Main/Dev.hs @@ -1,4 +1,4 @@ -module Clickable.Main.DevServer where +module Clickable.Main.Dev where import Control.Concurrent import Control.Concurrent.Async @@ -33,7 +33,7 @@ import "this" Clickable.Internal (ClientMessage(..)) import "this" Clickable.Internal qualified as Internal -data DevServerConfig a = DevServerConfig +data DevConfig a = DevConfig { aquire_resource :: IO a -- ^ Usualy runs once just after ghci session is loaded, -- e.g. establish connection to database etc @@ -57,8 +57,8 @@ data ApplicationSpec = ApplicationSpec -- ^ Will be executed after a connection closes } deriving Generic -defaultConfig :: (ConnectionInfo -> StartFlags -> ClickM ()) -> DevServerConfig () -defaultConfig clientApp = DevServerConfig +defaultConfig :: (ConnectionInfo -> StartFlags -> ClickM ()) -> DevConfig () +defaultConfig clientApp = DevConfig { aquire_resource = pure () , release_resource = const (pure ()) , reload_app = \_ -> pure $ ApplicationSpec clientApp fallbackApp (const (pure ())) @@ -66,7 +66,7 @@ defaultConfig clientApp = DevServerConfig , docroots = [] } -runSettings :: Typeable resource => Warp.Settings -> DevServerConfig resource -> IO () +runSettings :: Typeable resource => Warp.Settings -> DevConfig resource -> IO () runSettings settings cfg = do -- Using a random constant as the key for Foreign.Store let storeId = 183 @@ -109,12 +109,12 @@ runSettings settings cfg = do isRepl <- (== "") <$> getProgName if isRepl then void (forkIO action) else action -runServer :: (StartFlags -> ClickM ()) -> IO () -runServer clientApp = runSettings +runDev :: (StartFlags -> ClickM ()) -> IO () +runDev clientApp = runSettings (Warp.setPort 8080 Warp.defaultSettings) (defaultConfig (const clientApp)) -middleware :: DevServerInstance -> Middleware +middleware :: DevInstance -> Middleware middleware opts next req resp = case pathInfo req of [] -> indexHtml req resp @@ -161,7 +161,7 @@ fallbackApp _ resp = \ \n\ \\n" -websocketApp :: DevServerInstance -> ServerApp +websocketApp :: DevInstance -> ServerApp websocketApp opt p = let acceptConn = mdo @@ -226,7 +226,7 @@ websocketApp opt p = bracket acceptConn dropConn \connInfo -> withPingThread connInfo.connection 30 (pure ()) $ loop connInfo -newInstance :: Typeable resource => DevServerConfig resource -> IO DevServerInstance +newInstance :: Typeable resource => DevConfig resource -> IO DevInstance newInstance cfg = do resource <- cfg.aquire_resource appSpec <- cfg.reload_app resource @@ -238,16 +238,16 @@ newInstance cfg = do , connection_lost = appSpec.connection_lost } conn_state_ref <- newIORef Map.empty - return DevServerInstance {conn_state_ref, app_state_ref} + return DevInstance {conn_state_ref, app_state_ref} updateInstance :: Typeable resource - => DevServerConfig resource - -> DevServerInstance + => DevConfig resource + -> DevInstance -> IO () updateInstance cfg devInst = do let - tryOldResource :: forall a. Typeable a => DevServerConfig a -> + tryOldResource :: forall a. Typeable a => DevConfig a -> RunningApp -> Either (IO ()) a tryOldResource _ RunningApp {resource, devserver_config} | Just Refl <- eqResource @a resource = Right resource @@ -277,7 +277,7 @@ updateInstance cfg devInst = do , connection_lost = appSpec.connection_lost } -data DevServerInstance = DevServerInstance +data DevInstance = DevInstance { conn_state_ref :: IORef (Map ConnectionId ConnectionInfo) , app_state_ref :: IORef RunningApp } deriving Generic @@ -293,7 +293,7 @@ data ConnectionInfo = ConnectionInfo data RunningApp = forall a. Typeable a => RunningApp { resource :: a - , devserver_config :: DevServerConfig a + , devserver_config :: DevConfig a , client_app :: ConnectionInfo -> StartFlags -> ClickM () , server_app :: Application , connection_lost :: ConnectionInfo -> IO () @@ -305,4 +305,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>m,Gk:()=>x,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>T,b9:()=>D,g1:()=>O,tB:()=>U});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class d extends _{constructor(e){super(),this._self=e}}class f extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return y(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof d)return E(e._self,t);if(e instanceof f){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=y(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof d)return g(e._self,t,r);if(e instanceof f){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function y(e){return Math.ceil(Math.log2(e)/8)}const h=new a,x=new s,m=new i,T=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new f(e)}function U(e){const t=new d(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Add=11]=\"Add\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const d=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(d);const{ret:f,fd_obj:E}=o.fds[e].path_open(t,d,_,a,i,c);if(0!=f)return f;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class d{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class f{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new f;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new d;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_main(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};var h=__webpack_require__(366);function x(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,m,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}const m=[window,null];function T(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(y)});Object.assign(y,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(y,i);yield _.exports.wasm_main(o)}))},window.startClient=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield T(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield x(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield T(t.data);x(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,Gk:()=>y,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>m,b9:()=>D,g1:()=>O,tB:()=>U});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return x(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=x(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function x(e){return Math.ceil(Math.log2(e)/8)}const h=new a,y=new s,T=new i,m=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function U(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Add=11]=\"Add\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{const e=58;class t{static read_bytes(e,r){const n=new t;return n.buf=e.getUint32(r,!0),n.buf_len=e.getUint32(r+4,!0),n}static read_bytes_array(e,r,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class s extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let i,o=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof s)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,n,_,i={}){this.args=[],this.env=[],this.fds=[],a.enable(i.debug),this.args=e,this.env=n,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),a.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,r,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=t.read_bytes_array(s,r,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=t.read_bytes_array(a,r,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,s,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));a.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,s,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,s){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));a.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(s,0,!0),8;c.set(e,n),i.setUint32(s,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new s(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class p{open(e){const t=new l(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new _(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class u{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class f{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)i=globalThis.setImmediate;else{const e=new f;i=(t,...r)=>e.setImmediate(t,...r)}const d=e=>{const t=new u;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>i(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=E.sy.decode(r),_=(t,r)=>{const n=E.bR.encode(t),_=g(e,n);e.wasm_app(_)};switch(n.tag){case E.I4.EvalExpr:{const t=E.wL(_,[globalThis,null],null,n.expr),r={tag:E.dB.Return,0:E.bp(t)},a=E.bR.encode(r);return g(e,a)}case E.I4.HotReload:{window.location.reload();const t={tag:E.dB.Return,0:E.bp(null)},r=E.bR.encode(t);return g(e,r)}case E.I4.Halt:{const t={tag:E.dB.Return,0:E.bp(null)},r=E.bR.encode(t);return g(e,r)}}}(e,t)}};var E=__webpack_require__(933);function g(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let b={};window,window.startWasm=function(e){return t=this,r=arguments,_=function*(e,t=null){const r=new o([],[],[new l(new p([])),new l(new p([])),new l(new p([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:d(b)});Object.assign(b,_.exports),r.initialize(_),yield _.exports.hs_init();const a=E.bp(t),s={tag:E.dB.Start,0:a},i=E.bR.encode(s),c=g(b,i);yield _.exports.wasm_app(c),window.addEventListener(\"beforeunload\",(()=>{const e={tag:E.dB.BeforeUnload},t=E.bR.encode(e),r=g(b,t);b.wasm_app(r)}))},new((n=void 0)||(n=Promise))((function(e,a){function s(e){try{o(_.next(e))}catch(e){a(e)}}function i(e){try{o(_.throw(e))}catch(e){a(e)}}function o(t){var r;t.done?e(t.value):(r=t.value,r instanceof n?r:new n((function(e){e(r)}))).then(s,i)}o((_=_.apply(t,r||[])).next())}));var t,r,n,_},window.startDev=devserver.startDev})()})();" diff --git a/src/Clickable/Main/WASM.hs b/src/Clickable/Main/Wasm.hs similarity index 94% rename from src/Clickable/Main/WASM.hs rename to src/Clickable/Main/Wasm.hs index d7f5701..dc744ab 100644 --- a/src/Clickable/Main/WASM.hs +++ b/src/Clickable/Main/Wasm.hs @@ -1,4 +1,4 @@ -module Clickable.Main.WASM where +module Clickable.Main.Wasm where import Control.Monad.State import Data.Binary (Binary) @@ -19,8 +19,8 @@ import Clickable.Core import Clickable.Internal qualified as Internal import Clickable.Types -runApp :: (StartFlags -> ClickM ()) -> Ptr Word8 -> IO () -runApp app p = mdo +runWasm :: (StartFlags -> ClickM ()) -> Ptr Word8 -> IO () +runWasm app p = mdo jmsg <- loadMessage p case jmsg of Start flags -> From fc5e02a75cc57cc90d78d9f1f0722ff60bf76eb8 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 4 Apr 2024 16:20:10 +0400 Subject: [PATCH 25/64] Input focus on double-click --- examples/todomvc/TodoItem.hs | 57 +++++++++++++----------- examples/todomvc/TodoList.hs | 84 ++++++++++++++++++------------------ examples/todomvc/Utils.hs | 3 ++ htmlt.cabal | 51 +--------------------- jsbits/dev.ts | 2 +- jsbits/index.js | 2 +- src/Clickable/Core.hs | 34 +++++++-------- src/Clickable/Internal.hs | 17 ++------ src/Clickable/Main/Dev.hs | 4 +- src/Clickable/Types.hs | 7 +-- 10 files changed, 107 insertions(+), 154 deletions(-) diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index e9a5bff..6e0042d 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -5,8 +5,11 @@ import Data.Maybe import Data.Text (Text) import GHC.Int import Clickable +import Clickable.Protocol (VarId) import Clickable.Protocol.Value +import "this" Utils + data TodoItemConfig = TodoItemConfig { state_var :: DynVar TodoItemState , is_hidden_dyn :: DynVal Bool @@ -20,21 +23,21 @@ data TodoItemState = TodoItemState } deriving stock (Show, Eq) data TodoItemAction a where - CancelAction :: TodoItemConfig -> TodoItemAction () - CommitAction :: TodoItemConfig -> TodoItemAction () - InputAction :: TodoItemConfig -> Text -> TodoItemAction () - DoubleClickAction :: TodoItemConfig -> TodoItemAction () - CheckedAction :: TodoItemConfig -> Bool -> TodoItemAction () - KeydownAction :: TodoItemConfig -> Int64 -> TodoItemAction () + CancelAction :: TodoItemAction () + CommitAction :: TodoItemAction () + InputAction :: Text -> TodoItemAction () + DoubleClickAction :: VarId -> TodoItemAction () + CheckedAction :: Bool -> TodoItemAction () + KeydownAction :: Int64 -> TodoItemAction () emptyState :: TodoItemState emptyState = TodoItemState "" False Nothing -eval :: TodoItemAction a -> ClickM a -eval = \case - CancelAction cfg -> +eval :: TodoItemConfig -> TodoItemAction a -> ClickM a +eval cfg = \case + CancelAction -> modifyVar_ cfg.state_var \s -> s{editing=Nothing} - CommitAction cfg -> do + CommitAction -> do state <- readVar cfg.state_var case state.editing of Just "" -> @@ -43,20 +46,22 @@ eval = \case modifyVar_ cfg.state_var \s -> s {editing=Nothing, title = t} Nothing -> pure () - InputAction cfg newVal -> + InputAction newVal -> modifyVar_ cfg.state_var \s -> s{editing = Just newVal} - DoubleClickAction cfg -> do - modifyVar_ cfg.state_var \s -> s {editing = Just s.title} --- liftIO $ js_todoItemInputFocus targetEl - CheckedAction cfg isChecked -> do + DoubleClickAction inpElm -> do + trampoline do + modifyVar_ cfg.state_var \s -> s {editing = Just s.title} + syncPoint + assignFocus inpElm + CheckedAction isChecked -> do modifyVar_ cfg.state_var \s -> s{completed = isChecked} - KeydownAction cfg key -> case key of - 13 {- Enter -} -> eval (CommitAction cfg) - 27 {- Escape -} -> eval (CancelAction cfg) + KeydownAction key -> case key of + 13 {- Enter -} -> eval cfg CommitAction + 27 {- Escape -} -> eval cfg CancelAction _ -> return () html :: TodoItemConfig -> HtmlM () -html cfg = li_ do +html cfg = li_ mdo let completedDyn = (.completed) <$> fromVar cfg.state_var editingDyn = isJust . (.editing) <$> fromVar cfg.state_var @@ -65,18 +70,20 @@ html cfg = li_ do toggleClass "editing" editingDyn toggleClass "hidden" cfg.is_hidden_dyn div_ [class_ "view"] do - on @"dblclick" $ eval $ DoubleClickAction cfg + on @"dblclick" $ eval cfg $ DoubleClickAction inp input_ [class_ "toggle", type_ "checkbox"] do dynChecked $ (.completed) <$> fromVar cfg.state_var - on @"checkbox/change" $ eval . CheckedAction cfg + on @"checkbox/change" $ eval cfg . CheckedAction label_ $ dynText $ (.title) <$> fromVar cfg.state_var button_ [class_ "destroy"] do on @"click" cfg.ask_delete_item - input_ [class_ "edit", type_ "text"] do + inp <- input_ [class_ "edit", type_ "text"] do dynValue valueDyn - on @"input" $ eval . InputAction cfg - on @"keydown" $ eval . KeydownAction cfg - on @"blur" $ eval (CommitAction cfg) + on @"input" $ eval cfg . InputAction + on @"keydown" $ eval cfg . KeydownAction + on @"blur" $ eval cfg CommitAction + saveCurrentNode + return () instance ToJSValue TodoItemState where toJSValue s = Object diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index 574adc4..c91353c 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -25,31 +25,31 @@ data Filter = All | Active | Completed deriving (Show, Eq) data TodoListAction a where - ToggleAllAction :: TodoListConfig -> Bool -> TodoListAction () - InputAction :: TodoListConfig -> Text -> TodoListAction () - CommitAction :: TodoListConfig -> TodoListAction () - KeydownAction :: TodoListConfig -> Int64 -> TodoListAction () - DeleteItemAction :: TodoListConfig -> Int -> TodoListAction () - ClearCompletedAction :: TodoListConfig -> TodoListAction () + ToggleAllAction :: Bool -> TodoListAction () + InputAction :: Text -> TodoListAction () + CommitAction :: TodoListAction () + KeydownAction :: Int64 -> TodoListAction () + DeleteItemAction :: Int -> TodoListAction () + ClearCompletedAction :: TodoListAction () new :: [TodoItem.TodoItemState] -> ClickM (DynVar TodoListState) new items = - newDynVar TodoListState + newVar TodoListState { title = "" , items = items , filter = All } -eval :: TodoListAction a -> ClickM a -eval = \case - ToggleAllAction cfg isChecked -> +eval :: TodoListConfig -> TodoListAction a -> ClickM a +eval cfg = \case + ToggleAllAction isChecked -> modifyVar_ cfg.state_var \s -> s { items = fmap (\i -> i {TodoItem.completed = isChecked}) s.items } - InputAction cfg newVal -> do + InputAction newVal -> do modifyVar_ cfg.state_var \s -> s {title = newVal} - CommitAction cfg -> do + CommitAction -> do title <- Text.strip . (.title) <$> readVar cfg.state_var case title of "" -> return () @@ -57,16 +57,16 @@ eval = \case { items = s.items <> [mkNewTodo t] , title = "" } - KeydownAction cfg key -> do + KeydownAction key -> do case key of - 13 {- Enter -} -> eval (CommitAction cfg) + 13 {- Enter -} -> eval cfg CommitAction 27 {- Escape -} -> do s <- readVar cfg.state_var consoleLog $ Text.pack $ show s _ -> return () - DeleteItemAction cfg itemIx -> + DeleteItemAction itemIx -> modifyVar_ cfg.state_var \s -> s {items = deleteIx itemIx s.items} - ClearCompletedAction cfg -> + ClearCompletedAction -> modifyVar_ cfg.state_var \s -> s {items = (List.filter (not . TodoItem.completed)) s.items} where @@ -88,22 +88,22 @@ html cfg = do h1_ (text "todos") input_ [class_ "new-todo", placeholder_ "What needs to be done?", autofocus_ True] do dynValue $ (.title) <$> fromVar cfg.state_var - on @"input" $ eval . InputAction cfg - on @"keydown" $ eval . KeydownAction cfg + on @"input" $ eval cfg . InputAction + on @"keydown" $ eval cfg . KeydownAction mainWidget = section_ [class_ "main"] do toggleClass "hidden" hiddenDyn input_ [id_ "toggle-all", class_ "toggle-all", type_ "checkbox"] do - on @"checkbox/change" $ eval . ToggleAllAction cfg + on @"checkbox/change" $ eval cfg . ToggleAllAction label_ do attribute "for" "toggle-all" text "Mark all as completed" ul_ [class_ "todo-list"] do - simpleList itemsDyn \idx todoRef -> + simpleList itemsDyn \i todoRef -> TodoItem.html $ TodoItem.TodoItemConfig - { TodoItem.state_var = overrideVar (todoItemUpdated cfg idx) todoRef + { TodoItem.state_var = overrideVar (todoItemUpdated cfg i) todoRef , TodoItem.is_hidden_dyn = isTodoItemHidden <$> fromVar cfg.state_var <*> fromVar todoRef - , TodoItem.ask_delete_item = eval (DeleteItemAction cfg idx) + , TodoItem.ask_delete_item = eval cfg $ DeleteItemAction i } footerWidget = footer_ [class_ "footer"] do toggleClass "hidden" hiddenDyn @@ -113,7 +113,7 @@ html cfg = do ul_ [class_ "filters"] do forM_ [All, Active, Completed] filterWidget button_ [class_ "clear-completed"] do - on @"click" $ eval (ClearCompletedAction cfg) + on @"click" $ eval cfg ClearCompletedAction text "Clear completed" footerInfoWidget = footer_ [class_ "info"] do p_ "Double-click to edit a todo" @@ -146,25 +146,8 @@ html cfg = do (Completed, False) -> True _ -> False -pluralize :: Text -> Text -> Int -> Text -pluralize singular _plural 0 = singular -pluralize _singular plural _ = plural - -parseFilter :: Text -> Maybe Filter -parseFilter = \case - "#/" -> Just All - "#/active" -> Just Active - "#/completed" -> Just Completed - _ -> Nothing - -printFilter :: Filter -> Text -printFilter = \case - All -> "#/" - Active -> "#/active" - Completed -> "#/completed" - --- | Synchronize changes inside TodoItem widget with the outer --- TodoList widget. +-- | Synchronize TodoItem state with the larger state of TodoList +-- widget. todoItemUpdated :: TodoListConfig -> Int @@ -191,6 +174,23 @@ todoItemUpdated cfg i next f = do updateIx n a (x:xs) = x : updateIx (pred n) a xs updateIx _ _ [] = [] +pluralize :: Text -> Text -> Int -> Text +pluralize singular _plural 0 = singular +pluralize _singular plural _ = plural + +parseFilter :: Text -> Maybe Filter +parseFilter = \case + "#/" -> Just All + "#/active" -> Just Active + "#/completed" -> Just Completed + _ -> Nothing + +printFilter :: Filter -> Text +printFilter = \case + All -> "#/" + Active -> "#/active" + Completed -> "#/completed" + styles :: Text styles = "\ \body {\ diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs index 98b1d38..7dc043b 100644 --- a/examples/todomvc/Utils.hs +++ b/examples/todomvc/Utils.hs @@ -16,3 +16,6 @@ saveLocalStorage :: ToJSValue v => Text -> v -> ClickM () saveLocalStorage key val = do let stringify = Call (Id "JSON") "stringify" . (:[]) . valueToExpr . toJSValue enqueueExpr $ Call (Id "localStorage") "setItem" [String key, stringify val] + +assignFocus :: VarId -> ClickM () +assignFocus elem = enqueueExpr $ Call (Var elem) "focus" [] diff --git a/htmlt.cabal b/htmlt.cabal index b7b7909..060d3bd 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -117,22 +117,6 @@ library wai-websockets, warp, websockets, - --- executable htmlt-counter --- import: htmlt-common --- main-is: counter.hs --- hs-source-dirs: ./examples/counter --- ghc-options: --- -no-hs-main -optl-mexec-model=reactor --- -optl-Wl,--export=hs_init,--export=wasm_app --- build-depends: --- base, --- htmlt, --- text, --- mtl, --- transformers, --- if !flag(examples) --- buildable: False executable htmlt-todomvc import: htmlt-common @@ -146,6 +130,7 @@ executable htmlt-todomvc ghc-options: -threaded main-is: dev.hs other-modules: + App TodoItem TodoList Utils @@ -156,37 +141,3 @@ executable htmlt-todomvc mtl, if !flag(examples) buildable: False - --- executable htmlt-simple-routing --- import: htmlt-common --- main-is: simple-routing.hs --- hs-source-dirs: ./examples/simple-routing --- ghc-options: --- -no-hs-main -optl-mexec-model=reactor --- -optl-Wl,--export=hs_init,--export=wasm_app --- other-modules: --- Assets --- Router --- Pages --- Utils --- build-depends: --- base, --- bytestring, --- mtl, --- htmlt, --- text, --- if !flag(examples) --- buildable: False - --- executable htmlt-benchmarks --- import: htmlt-common --- main-is: benchmarks.hs --- hs-source-dirs: ./benchmarks/ --- build-depends: --- base, --- htmlt, --- text, --- gauge, --- -- Fails to build with javascript-backend --- buildable: False - diff --git a/jsbits/dev.ts b/jsbits/dev.ts index 1dda3ed..9839f22 100644 --- a/jsbits/dev.ts +++ b/jsbits/dev.ts @@ -2,7 +2,7 @@ import { absurd } from './lib'; import * as p from './protocol'; import { HaskellMessage, JavaScriptMessage, JavaScriptMessageTag, HaskellMessageTag, Bindings, List } from './protocol'; -export function startClient(devSocketUri: string, startFlags: unknown = null) { +export function startDev(devSocketUri: string, startFlags: unknown = null) { const websocket = new WebSocket(devSocketUri); const sendToHaskell = async (jsMsg: JavaScriptMessage, argScope: List) => { diff --git a/jsbits/index.js b/jsbits/index.js index d24c9b9..208a2e3 100644 --- a/jsbits/index.js +++ b/jsbits/index.js @@ -2,4 +2,4 @@ import * as wasm from './wasm'; import * as dev from './dev'; window.startWasm = wasm.startWasm; -window.startDev = devserver.startDev; +window.startDev = dev.startDev; diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 3bd247f..b4e92a5 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -26,10 +26,10 @@ import Clickable.Protocol.Value qualified as Value -- OPERATIONS OVER DYNAMIC VARIABLES -- --------------------------------------- -newDynVar :: a -> ClickM (DynVar a) -newDynVar a = do +newVar :: a -> ClickM (DynVar a) +newVar a = do ref <- liftIO $ newIORef a - state \s -> (DynVar (SourceId s.next_id) ref, s {next_id = s.next_id + 1}) + state \s -> (SourceVar (SourceId s.next_id) ref, s {next_id = s.next_id + 1}) overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a overrideVar = OverrideVar @@ -41,7 +41,7 @@ readVar :: DynVar a -> ClickM a readVar = Internal.readVar modifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a -modifyVar var@(DynVar varId ref) f = do +modifyVar var@(SourceVar varId ref) f = do (newVal, a) <- liftIO $ atomicModifyIORef' ref g modify $ Internal.unsafeTrigger varId newVal return a @@ -61,7 +61,7 @@ subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () subscribe val k = reactive_ $ Internal.subscribe val k modifyVarQuiet :: DynVar s -> (s -> (s, a)) -> ClickM a -modifyVarQuiet var@(DynVar varId ref) f = do +modifyVarQuiet var@(SourceVar varId ref) f = do (newVal, a) <- liftIO $ atomicModifyIORef' ref g return a where @@ -107,8 +107,8 @@ freeScope unlink s = installFinalizer :: ClickM () -> ClickM () installFinalizer k = reactive_ $ Internal.installFinalizer k -newVar :: ClickM VarId -newVar = reactive Internal.newVar +newVarId :: ClickM VarId +newVarId = reactive Internal.newVarId ------------------ -- BUILDING DOM -- @@ -141,7 +141,7 @@ dynText :: DynVal Text -> HtmlM () dynText val = do scope <- lift $ asks (.scope) t <- lift $ readVal val - v <- lift $ newVar + v <- lift $ newVarId lift $ modify $ f v t lift $ subscribe val $ enqueueExpr . UpdateTextNode (Var v) where @@ -205,7 +205,7 @@ dyn val = do exec $ update newVal -- | Auxilliary datatype used in 'simpleList' implementation -data InternalElem a = InternalElem +data ElemEnv a = ElemEnv { boundary :: VarId , state_var :: DynVar a , elem_scope :: ResourceScope @@ -222,7 +222,7 @@ simpleList -- ^ Build HTML for each element in the list -> HtmlM () simpleList listDyn h = lift do - internalStateRef <- liftIO $ newIORef ([] :: [InternalElem a]) + internalStateRef <- liftIO $ newIORef ([] :: [ElemEnv a]) boundary <- insertBoundary let exec boundary scope h = evalStateT h.unHtmlT Nothing @@ -230,7 +230,7 @@ simpleList listDyn h = lift do & local (\s -> s {scope}) exec1 boundary = htmlBuilder1 (Var boundary) - setup :: Int -> [a] -> [InternalElem a] -> ClickM [InternalElem a] + setup :: Int -> [a] -> [ElemEnv a] -> ClickM [ElemEnv a] setup idx new existing = case (existing, new) of ([], []) -> return [] -- New list is longer, append new elements @@ -247,14 +247,14 @@ simpleList listDyn h = lift do (r:rs, y:ys) -> do writeVar r.state_var y fmap (r:) $ setup (idx + 1) ys rs - newElem :: Int -> a -> ClickM (InternalElem a) + newElem :: Int -> a -> ClickM (ElemEnv a) newElem i a = do elem_scope <- newScope local (\s -> s {scope = elem_scope}) do - state_var <- newDynVar a + state_var <- newVar a boundary <- insertBoundary - return InternalElem {elem_scope, state_var, boundary} - finalizeElems :: Bool -> [InternalElem a] -> ClickM () + return ElemEnv {elem_scope, state_var, boundary} + finalizeElems :: Bool -> [ElemEnv a] -> ClickM () finalizeElems remove = mapM_ \ee -> do when remove $ destroyBoundary ee.boundary freeScope True ee.elem_scope @@ -291,7 +291,7 @@ saveCurrentNode = do alreadySaved <- HtmlT get case alreadySaved of Nothing -> do - varId <- lift newVar + varId <- lift newVarId HtmlT $ put $ Just varId lift $ enqueueExpr $ AssignVar varId (Arg 0 0) return varId @@ -299,7 +299,7 @@ saveCurrentNode = do insertBoundary :: ClickM VarId insertBoundary = do - boundary <- newVar + boundary <- newVarId enqueueExpr $ AssignVar boundary (InsertBoundary (Arg 0 0)) return boundary diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 2bceeb9..0171dd7 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -3,19 +3,10 @@ module Clickable.Internal where import Control.Applicative import Control.Monad.Reader import Control.Monad.State -import Data.Binary (Binary) -import Data.Binary qualified as Binary -import Data.ByteString as BS -import Data.ByteString.Lazy qualified as BSL -import Data.ByteString.Unsafe qualified as BSU import Data.Foldable import Data.IORef import Data.List qualified as List import Data.Map qualified as Map -import Data.Word -import Foreign.Marshal.Alloc qualified as Alloc -import Foreign.Ptr -import Foreign.Storable import Unsafe.Coerce import Clickable.Protocol @@ -51,8 +42,8 @@ newScope p s = in (s', scopeId) -newVar :: ResourceScope -> InternalState -> (InternalState, VarId) -newVar e s = +newVarId :: ResourceScope -> InternalState -> (InternalState, VarId) +newVarId e s = (s {next_id = s.next_id + 1}, VarId e s.next_id) freeScope :: @@ -80,7 +71,7 @@ subscribe :: ResourceScope -> InternalState -> InternalState subscribe (ConstVal _) _ _ s = s -subscribe (FromVar (DynVar varId _)) fn scope s = s {subscriptions} +subscribe (FromVar (SourceVar varId _)) fn scope s = s {subscriptions} where subscriptions = newSub : s.subscriptions newSub = (scope, varId, fn . unsafeCoerce) @@ -111,7 +102,7 @@ readVal (MapVal val f) = fmap f $ readVal val readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) readVar :: DynVar a -> ClickM a -readVar (DynVar _ ref) = liftIO $ readIORef ref +readVar (SourceVar _ ref) = liftIO $ readIORef ref readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var readVar (OverrideVar _ var) = readVar var diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 5614d24..27ce015 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -146,7 +146,7 @@ htmlTemplate devUrl = \ \n\ \ \n\ \ \n\ \\n" @@ -305,4 +305,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,Gk:()=>y,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>m,b9:()=>D,g1:()=>O,tB:()=>U});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return x(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=x(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function x(e){return Math.ceil(Math.log2(e)/8)}const h=new a,y=new s,T=new i,m=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function U(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Add=11]=\"Add\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{const e=58;class t{static read_bytes(e,r){const n=new t;return n.buf=e.getUint32(r,!0),n.buf_len=e.getUint32(r+4,!0),n}static read_bytes_array(e,r,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class s extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let i,o=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof s)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,n,_,i={}){this.args=[],this.env=[],this.fds=[],a.enable(i.debug),this.args=e,this.env=n,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),a.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,r,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=t.read_bytes_array(s,r,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=t.read_bytes_array(a,r,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,s,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));a.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,s,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,s){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));a.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(s,0,!0),8;c.set(e,n),i.setUint32(s,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new s(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class p{open(e){const t=new l(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new _(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class u{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class f{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)i=globalThis.setImmediate;else{const e=new f;i=(t,...r)=>e.setImmediate(t,...r)}const d=e=>{const t=new u;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>i(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=E.sy.decode(r),_=(t,r)=>{const n=E.bR.encode(t),_=g(e,n);e.wasm_app(_)};switch(n.tag){case E.I4.EvalExpr:{const t=E.wL(_,[globalThis,null],null,n.expr),r={tag:E.dB.Return,0:E.bp(t)},a=E.bR.encode(r);return g(e,a)}case E.I4.HotReload:{window.location.reload();const t={tag:E.dB.Return,0:E.bp(null)},r=E.bR.encode(t);return g(e,r)}case E.I4.Halt:{const t={tag:E.dB.Return,0:E.bp(null)},r=E.bR.encode(t);return g(e,r)}}}(e,t)}};var E=__webpack_require__(933);function g(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let b={};window,window.startWasm=function(e){return t=this,r=arguments,_=function*(e,t=null){const r=new o([],[],[new l(new p([])),new l(new p([])),new l(new p([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:d(b)});Object.assign(b,_.exports),r.initialize(_),yield _.exports.hs_init();const a=E.bp(t),s={tag:E.dB.Start,0:a},i=E.bR.encode(s),c=g(b,i);yield _.exports.wasm_app(c),window.addEventListener(\"beforeunload\",(()=>{const e={tag:E.dB.BeforeUnload},t=E.bR.encode(e),r=g(b,t);b.wasm_app(r)}))},new((n=void 0)||(n=Promise))((function(e,a){function s(e){try{o(_.next(e))}catch(e){a(e)}}function i(e){try{o(_.throw(e))}catch(e){a(e)}}function o(t){var r;t.done?e(t.value):(r=t.value,r instanceof n?r:new n((function(e){e(r)}))).then(s,i)}o((_=_.apply(t,r||[])).next())}));var t,r,n,_},window.startDev=devserver.startDev})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>m,Gk:()=>x,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>T,b9:()=>D,g1:()=>O,tB:()=>U});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class d extends _{constructor(e){super(),this._self=e}}class f extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return y(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof d)return E(e._self,t);if(e instanceof f){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=y(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof d)return g(e._self,t,r);if(e instanceof f){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function y(e){return Math.ceil(Math.log2(e)/8)}const h=new a,x=new s,m=new i,T=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new f(e)}function U(e){const t=new d(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Add=11]=\"Add\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const d=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(d);const{ret:f,fd_obj:E}=o.fds[e].path_open(t,d,_,a,i,c);if(0!=f)return f;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class d{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class f{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new f;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new d;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};var h=__webpack_require__(366);function x(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,m,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}const m=[window,null];function T(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(y)});Object.assign(y,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(y,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(y,t);y.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield T(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield x(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield T(t.data);x(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index c5cbe74..055d527 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -1,6 +1,7 @@ module Clickable.Types where import Control.Monad.Reader +import Control.Monad.Fix import Control.Monad.State import Data.IORef import Data.Int @@ -12,7 +13,7 @@ import GHC.Exts import Clickable.Protocol data DynVar a where - DynVar :: SourceId -> IORef a -> DynVar a + SourceVar :: SourceId -> IORef a -> DynVar a OverrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a LensMap :: Lens' s a -> DynVar s -> DynVar a @@ -34,10 +35,10 @@ fromVar :: DynVar a -> DynVal a fromVar = FromVar newtype HtmlT m a = HtmlT {unHtmlT :: StateT (Maybe VarId) m a} - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadTrans) + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadFix, MonadTrans) newtype ClickT m a = ClickT {unClickT :: ReaderT InternalEnv m a} - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv, MonadTrans) + deriving newtype (Functor, Applicative, Monad, MonadIO, MonadFix, MonadReader InternalEnv, MonadTrans) type HtmlM = HtmlT ClickM type ClickM = ClickT IO From db28bd580753e95ce4192dc91d4ca7a5bb848ce9 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sat, 6 Apr 2024 03:27:39 +0400 Subject: [PATCH 26/64] MapHoldVal --- examples/todomvc/TodoItem.hs | 18 ++--- examples/todomvc/Utils.hs | 10 +-- src/Clickable.hs | 1 + src/Clickable/Core.hs | 6 ++ src/Clickable/DOM.hs | 36 +++++---- src/Clickable/Internal.hs | 37 ++++++++- src/Clickable/Protocol/Value.hs | 128 ++++++++++++++++---------------- src/Clickable/Types.hs | 1 + 8 files changed, 143 insertions(+), 94 deletions(-) diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index 6e0042d..28d957d 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -85,15 +85,15 @@ html cfg = li_ mdo saveCurrentNode return () -instance ToJSValue TodoItemState where - toJSValue s = Object - [ ("title", toJSValue s.title) - , ("completed", toJSValue s.completed) +instance ToValue TodoItemState where + toValue s = Object + [ ("title", toValue s.title) + , ("completed", toValue s.completed) ] -instance FromJSValue TodoItemState where - fromJSValue (Object kv) = do - title <- fromJSValue =<< List.lookup "title" kv - completed <- fromJSValue =<< List.lookup "completed" kv +instance FromValue TodoItemState where + fromValue (Object kv) = do + title <- fromValue =<< List.lookup "title" kv + completed <- fromValue =<< List.lookup "completed" kv return TodoItemState {editing=Nothing, ..} - fromJSValue _ = Nothing + fromValue _ = Nothing diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs index 7dc043b..83da890 100644 --- a/examples/todomvc/Utils.hs +++ b/examples/todomvc/Utils.hs @@ -4,17 +4,17 @@ import Data.Text (Text) import Clickable import Clickable.Protocol -import Clickable.Protocol.Value (FromJSValue(..), ToJSValue(..)) +import Clickable.Protocol.Value (FromValue(..), ToValue(..)) -readLocalStorage :: FromJSValue v => Text -> ClickM (Maybe v) +readLocalStorage :: FromValue v => Text -> ClickM (Maybe v) readLocalStorage key = do let jsonParse = Call (Id "JSON") "parse" . (:[]) jsval <- evalExpr $ jsonParse $ Call (Id "localStorage") "getItem" [String key] - return $ fromJSValue jsval + return $ fromValue jsval -saveLocalStorage :: ToJSValue v => Text -> v -> ClickM () +saveLocalStorage :: ToValue v => Text -> v -> ClickM () saveLocalStorage key val = do - let stringify = Call (Id "JSON") "stringify" . (:[]) . valueToExpr . toJSValue + let stringify = Call (Id "JSON") "stringify" . (:[]) . valueToExpr . toValue enqueueExpr $ Call (Id "localStorage") "setItem" [String key, stringify val] assignFocus :: VarId -> ClickM () diff --git a/src/Clickable.hs b/src/Clickable.hs index 028a511..4eda004 100644 --- a/src/Clickable.hs +++ b/src/Clickable.hs @@ -4,5 +4,6 @@ import Clickable.DOM as Exports import Clickable.Core as Exports import Clickable.Element as Exports import Clickable.Property as Exports +import Clickable.Protocol as Exports import Clickable.Types as Exports import Wasm.Compat.Prim as Exports diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index b4e92a5..73a553f 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -34,6 +34,9 @@ newVar a = do overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a overrideVar = OverrideVar +mapHoldVal :: (a -> b) -> DynVal a -> ClickM (DynVal b) +mapHoldVal = Internal.mapHoldVal + readVal :: DynVal a -> ClickM a readVal = Internal.readVal @@ -110,6 +113,9 @@ installFinalizer k = reactive_ $ Internal.installFinalizer k newVarId :: ClickM VarId newVarId = reactive Internal.newVarId +newCallback :: (Value -> ClickM ()) -> ClickM SourceId +newCallback k = reactive $ Internal.newCallback k + ------------------ -- BUILDING DOM -- ------------------ diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index c331ff6..0ce0995 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -10,7 +10,7 @@ import Unsafe.Coerce import Clickable.Types import Clickable.Protocol -import Clickable.Protocol.Value (Value, FromJSValue(..), ToJSValue(..)) +import Clickable.Protocol.Value (Value, FromValue(..), ToValue(..)) import Clickable.Internal @@ -114,12 +114,20 @@ instance IsEventName "select/change" where type EventListenerCb "select/change" = Text -> ClickM () addEventListenerArgs = selectChangeConnectArgs +eventListenerOptions :: Text -> Bool -> Bool -> ConnectResourceArgs (ClickM ()) +eventListenerOptions eventName preventDef stopProp = ConnectResourceArgs + { aquire_resource = \scope sourceId -> + Eval (normalEventWrapper eventName $ EventListenerOptions preventDef stopProp) + `Apply` [Arg 0 0, Lam (TriggerCallback sourceId Null)] + , mk_callback = \k _ -> k + } + -- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event pointerConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) pointerConnectArgs eventName = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval (normalEventWrapper eventName defaultEventListenerOptions) - `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + `Apply` [Arg 0 0, Lam (TriggerCallback sourceId Null)] , mk_callback = \k _ -> k } @@ -136,16 +144,16 @@ submitConnectArgs = ConnectResourceArgs -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event inputConnectArgs :: Text -> ConnectResourceArgs (Text -> ClickM ()) -inputConnectArgs eventName = ConnectResourceArgs +inputConnectArgs eventName = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval ("(function(target, haskellCb){\n\ - \ function listener(target){\n\ + \ function listener(event){\n\ \ haskellCb(event.target.value);\n\ \ }\n\ \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => window.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \})") `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromJSValue event) k + , mk_callback = \k event -> forM_ (fromValue event) k } -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event @@ -154,13 +162,13 @@ keyboardConnectArgs :: Text -> ConnectResourceArgs (Int64 -> ClickM ()) keyboardConnectArgs eventName = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval ( "(function(target, haskellCb){\n\ - \ function listener(target){\n\ - \ haskellCb(event.keyCode);\n\ + \ function listener(event){\n\ + \ haskellCb(event.target.keyCode);\n\ \ }\n\ \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \})") `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromJSValue event) k + , mk_callback = \k event -> forM_ (fromValue event) k } -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event @@ -180,13 +188,13 @@ checkboxChangeConnectArgs :: ConnectResourceArgs (Bool -> ClickM ()) checkboxChangeConnectArgs = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval "(function(target, haskellCb){\n\ - \ function listener(target){\n\ + \ function listener(event){\n\ \ haskellCb(event.target.checked);\n\ \ }\n\ \ target.addEventListener('change', listener);\n\ \ return () => window.removeEventListener('change', listener);\n\ \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromJSValue event) k + , mk_callback = \k event -> forM_ (fromValue event) k } -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event @@ -194,13 +202,13 @@ selectChangeConnectArgs :: ConnectResourceArgs (Text -> ClickM ()) selectChangeConnectArgs = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval "(function(target, haskellCb){\n\ - \ function listener(target){\n\ + \ function listener(event){\n\ \ haskellCb(event.target.value);\n\ \ }\n\ \ target.addEventListener('change', listener);\n\ \ return () => target.removeEventListener('change', listener);\n\ \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromJSValue event) k + , mk_callback = \k event -> forM_ (fromValue event) k } normalEventWrapper :: Text -> EventListenerOptions -> UnsafeJavaScript @@ -236,7 +244,7 @@ data Location = Location -- ^ A string containing a '#' followed by the fragment identifier -- of the URL. } deriving stock (Show, Eq, Generic) - deriving anyclass (FromJSValue, ToJSValue) + deriving anyclass (FromValue, ToValue) -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event popstateConnectArgs :: ConnectResourceArgs (Location -> ClickM ()) @@ -256,5 +264,5 @@ popstateConnectArgs = ConnectResourceArgs \ target.addEventListener('popstate', listener);\n\ \ return () => target.removeEventListener('popstate', listener);\n\ \})" `Apply` [Id "window", Lam (TriggerCallback sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromJSValue event) k + , mk_callback = \k event -> forM_ (fromValue event) k } diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 0171dd7..8f99896 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -10,6 +10,7 @@ import Data.Map qualified as Map import Unsafe.Coerce import Clickable.Protocol +import Clickable.Protocol.Value (Value) import Clickable.Types emptyState :: InternalState @@ -71,15 +72,19 @@ subscribe :: ResourceScope -> InternalState -> InternalState subscribe (ConstVal _) _ _ s = s -subscribe (FromVar (SourceVar varId _)) fn scope s = s {subscriptions} +subscribe (FromVar (SourceVar srcId _)) fn scope s = s {subscriptions} where subscriptions = newSub : s.subscriptions - newSub = (scope, varId, fn . unsafeCoerce) + newSub = (scope, srcId, fn . unsafeCoerce) subscribe (FromVar (OverrideVar _ var)) fn scope s = subscribe (FromVar var) fn scope s subscribe (FromVar (LensMap l var)) fn scope s = subscribe (FromVar var) (fn . getConst . l Const) scope s subscribe (MapVal v f) fn scope s = subscribe v (fn . f) scope s +subscribe (MapHoldVal _ _ srcId ref) fn scope s = s {subscriptions} + where + subscriptions = newSub : s.subscriptions + newSub = (scope, srcId, fn . unsafeCoerce) subscribe (SplatVal fv av) fn scope s = subscribe av g scope $ subscribe fv f scope $ attachCb s where @@ -99,6 +104,7 @@ readVal :: DynVal a -> ClickM a readVal (ConstVal a) = pure a readVal (FromVar var) = readVar var readVal (MapVal val f) = fmap f $ readVal val +readVal (MapHoldVal _ _ _ ref) = liftIO $ readIORef ref readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) readVar :: DynVar a -> ClickM a @@ -106,6 +112,17 @@ readVar (SourceVar _ ref) = liftIO $ readIORef ref readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var readVar (OverrideVar _ var) = readVar var +newCallback :: + (Value -> ClickM ()) -> + ResourceScope -> + InternalState -> (InternalState, SourceId) +newCallback k rscope s = + let + new = (rscope, SourceId s.next_id, k . unsafeCoerce) + subscriptions = new : s.subscriptions + in + (s { next_id = s.next_id + 1, subscriptions}, SourceId s.next_id) + launchClickM :: InternalEnv -> ClickM a -> IO a launchClickM env = flip runReaderT env . unClickT . (<* syncPoint) . trampoline @@ -154,3 +171,19 @@ data ClientMessage -- ^ Bypass protocol and inject a command directly into the -- DevServer instance (useful for delivering notifications under -- devserver) + +mapHoldVal :: (a -> b) -> DynVal a -> ClickM (DynVal b) +mapHoldVal f a = do + a <- readVal a + ref <- liftIO $ newIORef $ f a + reactive $ g ref + where + g ref scope s = (s', val) where + srcId = SourceId s.next_id + newSub = (scope, srcId, k . unsafeCoerce) + k a = do + let b = f a + liftIO $ writeIORef ref b + modify $ unsafeTrigger srcId b + s' = s {subscriptions = newSub : s.subscriptions, next_id = succ s.next_id} + val = MapHoldVal a f srcId ref diff --git a/src/Clickable/Protocol/Value.hs b/src/Clickable/Protocol/Value.hs index 67fab21..c939e4a 100644 --- a/src/Clickable/Protocol/Value.hs +++ b/src/Clickable/Protocol/Value.hs @@ -22,110 +22,110 @@ data Value deriving stock (Generic, Show) deriving anyclass (Binary) -class ToJSValue a where - toJSValue :: a -> Value - default toJSValue :: (Generic a, GToJSValue (Rep a)) => a -> Value - toJSValue = gToJSValue . G.from +class ToValue a where + toValue :: a -> Value + default toValue :: (Generic a, GToValue (Rep a)) => a -> Value + toValue = gToValue . G.from -instance ToJSValue Value where toJSValue = Prelude.id +instance ToValue Value where toValue = Prelude.id -instance ToJSValue Bool where toJSValue = Bool +instance ToValue Bool where toValue = Bool -instance ToJSValue Int64 where toJSValue = I64 +instance ToValue Int64 where toValue = I64 -instance ToJSValue Double where toJSValue = F64 +instance ToValue Double where toValue = F64 -instance ToJSValue Char where - toJSValue c = String $ Text.cons c Text.empty +instance ToValue Char where + toValue c = String $ Text.cons c Text.empty -instance ToJSValue Text where toJSValue = String +instance ToValue Text where toValue = String -instance ToJSValue a => ToJSValue [a] where toJSValue = Array . fmap toJSValue +instance ToValue a => ToValue [a] where toValue = Array . fmap toValue -instance ToJSValue a => ToJSValue (Maybe a) where toJSValue = maybe Null toJSValue +instance ToValue a => ToValue (Maybe a) where toValue = maybe Null toValue -instance (ToJSValue a, ToJSValue b) => ToJSValue (a, b) where - toJSValue (a, b) = toJSValue [toJSValue a, toJSValue b] +instance (ToValue a, ToValue b) => ToValue (a, b) where + toValue (a, b) = toValue [toValue a, toValue b] -instance (ToJSValue a, ToJSValue b, ToJSValue c) => ToJSValue (a, b, c) where - toJSValue (a, b, c) = toJSValue [toJSValue a, toJSValue b, toJSValue c] +instance (ToValue a, ToValue b, ToValue c) => ToValue (a, b, c) where + toValue (a, b, c) = toValue [toValue a, toValue b, toValue c] -------------------------------------------------------------------------------- -class FromJSValue a where - fromJSValue :: Value -> Maybe a - default fromJSValue :: (Generic a, GFromJSValue (Rep a)) => Value -> Maybe a - fromJSValue = fmap G.to . gFromJSValue +class FromValue a where + fromValue :: Value -> Maybe a + default fromValue :: (Generic a, GFromValue (Rep a)) => Value -> Maybe a + fromValue = fmap G.to . gFromValue -instance FromJSValue Value where fromJSValue = pure +instance FromValue Value where fromValue = pure -instance FromJSValue Bool where - fromJSValue = \case Bool a -> Just a; _ -> Nothing +instance FromValue Bool where + fromValue = \case Bool a -> Just a; _ -> Nothing -instance FromJSValue Int64 where - fromJSValue = \case +instance FromValue Int64 where + fromValue = \case I64 j -> Just j F64 j -> Just $ floor j _ -> Nothing -instance FromJSValue Double where - fromJSValue = \case +instance FromValue Double where + fromValue = \case I64 j -> Just $ fromIntegral j F64 j -> Just j _ -> Nothing -instance FromJSValue Char where - fromJSValue = \case +instance FromValue Char where + fromValue = \case String a | Just (c, _) <- Text.uncons a -> Just c | otherwise -> Nothing _ -> Nothing -instance FromJSValue Text where - fromJSValue = \case String a -> Just a; _ -> Nothing +instance FromValue Text where + fromValue = \case String a -> Just a; _ -> Nothing -instance FromJSValue a => FromJSValue [a] where - fromJSValue = \case - Array xs -> Just (mapMaybe fromJSValue xs) +instance FromValue a => FromValue [a] where + fromValue = \case + Array xs -> Just (mapMaybe fromValue xs) _ -> Nothing -instance FromJSValue a => FromJSValue (Maybe a) where - fromJSValue = fmap Just . fromJSValue @a +instance FromValue a => FromValue (Maybe a) where + fromValue = fmap Just . fromValue @a -instance (FromJSValue a, FromJSValue b) => FromJSValue (a, b) where - fromJSValue j = fromJSValue j >>= \case - Just (a:b:_) -> (,) <$> fromJSValue a <*> fromJSValue b +instance (FromValue a, FromValue b) => FromValue (a, b) where + fromValue j = fromValue j >>= \case + Just (a:b:_) -> (,) <$> fromValue a <*> fromValue b _ -> Nothing -instance (FromJSValue a, FromJSValue b, FromJSValue c) => FromJSValue (a, b, c) where - fromJSValue j = fromJSValue j >>= \case - Just (a:b:c:_) -> (,,) <$> fromJSValue a <*> fromJSValue b <*> fromJSValue c +instance (FromValue a, FromValue b, FromValue c) => FromValue (a, b, c) where + fromValue j = fromValue j >>= \case + Just (a:b:c:_) -> (,,) <$> fromValue a <*> fromValue b <*> fromValue c _ -> Nothing -------------------------------------------------------------------------------- -class GFromJSValue (f :: Type -> Type) where - gFromJSValue :: Value -> Maybe (f a) +class GFromValue (f :: Type -> Type) where + gFromValue :: Value -> Maybe (f a) -instance GFromJSValue f => GFromJSValue (M1 m c f) where - gFromJSValue = fmap M1 . gFromJSValue @f +instance GFromValue f => GFromValue (M1 m c f) where + gFromValue = fmap M1 . gFromValue @f -instance GFromJSObject (x :*: y) => GFromJSValue (x :*: y) where - gFromJSValue (Object kvs) = gFromJSObject kvs - gFromJSValue _ = Nothing +instance GFromJSObject (x :*: y) => GFromValue (x :*: y) where + gFromValue (Object kvs) = gFromJSObject kvs + gFromValue _ = Nothing -instance {-# OVERLAPPING #-} FromJSValue a => GFromJSValue (S1 s (Rec0 a)) where - gFromJSValue = fmap (M1 . K1) . fromJSValue @a +instance {-# OVERLAPPING #-} FromValue a => GFromValue (S1 s (Rec0 a)) where + gFromValue = fmap (M1 . K1) . fromValue @a -------------------------------------------------------------------------------- -class GToJSValue (f :: Type -> Type) where - gToJSValue :: f x -> Value +class GToValue (f :: Type -> Type) where + gToValue :: f x -> Value -instance GToJSValue f => GToJSValue (M1 m c f) where - gToJSValue (M1 f) = gToJSValue f +instance GToValue f => GToValue (M1 m c f) where + gToValue (M1 f) = gToValue f -instance GToJSObject (x :*: y) => GToJSValue (x :*: y) where - gToJSValue (x :*: y) = Object $ gToJSObject (x :*: y) +instance GToJSObject (x :*: y) => GToValue (x :*: y) where + gToValue (x :*: y) = Object $ gToJSObject (x :*: y) -instance {-# OVERLAPPING #-} (ToJSValue a) => GToJSValue (S1 s (Rec0 a)) where - gToJSValue (M1 (K1 a)) = toJSValue a +instance {-# OVERLAPPING #-} (ToValue a) => GToValue (S1 s (Rec0 a)) where + gToValue (M1 (K1 a)) = toValue a -------------------------------------------------------------------------------- class GToJSObject (f :: Type -> Type) where @@ -137,8 +137,8 @@ instance (GToJSObject x, GToJSObject y) => GToJSObject (x :*: y) where instance (GToJSObject f) => GToJSObject (M1 m c f) where gToJSObject (M1 a) = gToJSObject a -instance {-# OVERLAPPING #-} (ToJSValue a, Selector s) => GToJSObject (S1 s (Rec0 a)) where - gToJSObject (M1 (K1 a)) = [(key, toJSValue a)] +instance {-# OVERLAPPING #-} (ToValue a, Selector s) => GToJSObject (S1 s (Rec0 a)) where + gToJSObject (M1 (K1 a)) = [(key, toValue a)] where key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) -------------------------------------------------------------------------------- @@ -152,7 +152,7 @@ instance (GFromJSObject x, GFromJSObject y) => GFromJSObject (x :*: y) where instance (GFromJSObject f) => GFromJSObject (M1 m c f) where gFromJSObject = fmap M1 . gFromJSObject -instance {-# OVERLAPPING #-} (FromJSValue a, Selector s) => GFromJSObject (S1 s (Rec0 a)) where - gFromJSObject kvs = List.lookup key kvs >>= fmap (M1 . K1) . fromJSValue +instance {-# OVERLAPPING #-} (FromValue a, Selector s) => GFromJSObject (S1 s (Rec0 a)) where + gFromJSObject kvs = List.lookup key kvs >>= fmap (M1 . K1) . fromValue where key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index 055d527..adb8190 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -25,6 +25,7 @@ data DynVal a where ConstVal :: a -> DynVal a FromVar :: DynVar a -> DynVal a MapVal :: DynVal a -> (a -> b) -> DynVal b + MapHoldVal :: DynVal a -> (a -> b) -> SourceId -> IORef b -> DynVal b SplatVal :: DynVal (a -> b) -> DynVal a -> DynVal b instance Functor DynVal where fmap = flip MapVal From b2de9b639591c5be563dd45e4106662cdd2fdfde Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 9 Apr 2024 02:05:14 +0400 Subject: [PATCH 27/64] WIP --- htmlt.cabal | 4 +- src/Clickable/Core.hs | 77 ++++++++++++++++++++++++++---------- src/Clickable/Internal.hs | 82 +++++++++++++++++++++++---------------- src/Clickable/Property.hs | 32 +++++++-------- src/Clickable/Protocol.hs | 3 ++ src/Clickable/Types.hs | 6 +++ 6 files changed, 133 insertions(+), 71 deletions(-) diff --git a/htmlt.cabal b/htmlt.cabal index 060d3bd..e36d56a 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -78,6 +78,9 @@ common htmlt-common library import: htmlt-common + ghc-options: + -Wall -Wno-missing-signatures -Wno-name-shadowing -Wno-unused-matches + -Wno-unused-do-bind hs-source-dirs: src ./examples/charts ./examples/todomvc exposed-modules: Clickable @@ -92,7 +95,6 @@ library Clickable.Protocol.Value Clickable.FFI Wasm.Compat.Prim - other-modules: Paths_htmlt build-depends: base, diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 73a553f..ba7e6bb 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -19,7 +19,7 @@ import Clickable.Internal (reactive, reactive_) import Clickable.Internal qualified as Internal import Clickable.Types import Clickable.Protocol -import Clickable.Protocol.Value (Value) +import Clickable.Protocol.Value (Value, ToValue(..)) import Clickable.Protocol.Value qualified as Value --------------------------------------- @@ -61,7 +61,7 @@ writeVar :: DynVar s -> s -> ClickM () writeVar var s = modifyVar_ var $ const s subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () -subscribe val k = reactive_ $ Internal.subscribe val k +subscribe = Internal.subscribe modifyVarQuiet :: DynVar s -> (s -> (s, a)) -> ClickM a modifyVarQuiet var@(SourceVar varId ref) f = do @@ -76,6 +76,15 @@ modifyVarQuiet (LensMap l var) f = modifyVarQuiet var (swap . l (swap . f)) modifyVarQuiet_ :: DynVar s -> (s -> s) -> ClickM () modifyVarQuiet_ var f = modifyVarQuiet var ((,()) . f) +-- todo: needs redesign +holdUniqDyn :: Eq a => DynVal a -> DynVal a +holdUniqDyn a = flip OverrideSub a \next k -> do + old <- readVal a + oldRef <- liftIO $ newIORef old + next \new -> do + old <- liftIO $ atomicModifyIORef' oldRef (new,) + unless (old == new) $ k new + -------------------------------------- -- OPERATIONS OVER evaluation_queue -- -------------------------------------- @@ -123,15 +132,13 @@ newCallback k = reactive $ Internal.newCallback k el :: Text -> HtmlM a -> HtmlM a el t ch = lift $ htmlBuilder (CreateElement t) $ evalStateT ch.unHtmlT Nothing -property :: Text -> Text -> HtmlM () -property k v = lift $ modify f where - f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = ElementProp (Arg 0 0) k (String v) +elns :: Text -> Text -> HtmlM a -> HtmlM a +elns ns t ch = lift $ htmlBuilder (CreateElementNS ns t) $ evalStateT ch.unHtmlT Nothing -boolProperty :: Text -> Bool -> HtmlM () -boolProperty k v = lift $ modify f where +property :: ToValue a => Text -> a -> HtmlM () +property k v = lift $ modify f where f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = ElementProp (Arg 0 0) k (Boolean v) + expr = ElementProp (Arg 0 0) k (toExpr v) attribute :: Text -> Text -> HtmlM () attribute k v = lift $ modify f where @@ -145,7 +152,6 @@ text t = lift $ modify f where dynText :: DynVal Text -> HtmlM () dynText val = do - scope <- lift $ asks (.scope) t <- lift $ readVal val v <- lift $ newVarId lift $ modify $ f v t @@ -154,27 +160,25 @@ dynText val = do f v t s = s {evaluation_queue = expr v t : s.evaluation_queue } expr v t = InsertNode (Arg 0 0) $ AssignVar v $ CreateTextNode t -dynProp :: Text -> DynVal Text -> HtmlM () +dynProp :: ToValue a => Text -> DynVal a -> HtmlM () dynProp k val = do - scope <- lift $ asks (.scope) t <- lift $ readVal val v <- saveCurrentNode lift $ modify $ f t - lift $ subscribe val $ enqueueExpr . ElementProp (Var v) k . String + lift $ subscribe val $ enqueueExpr . ElementProp (Var v) k . toExpr where f v s = s {evaluation_queue = expr v : s.evaluation_queue } - expr v = ElementProp (Arg 0 0) k (String v) + expr v = ElementProp (Arg 0 0) k (toExpr v) -dynBoolProp :: Text -> DynVal Bool -> HtmlM () -dynBoolProp k val = do - scope <- lift $ asks (.scope) +dynAttr :: Text -> DynVal Text -> HtmlM () +dynAttr k val = do t <- lift $ readVal val v <- saveCurrentNode lift $ modify $ f t - lift $ subscribe val $ enqueueExpr . ElementProp (Var v) k . Boolean + lift $ subscribe val $ enqueueExpr . ElementAttr (Var v) k where f v s = s {evaluation_queue = expr v : s.evaluation_queue } - expr v = ElementProp (Arg 0 0) k (Boolean v) + expr v = ElementAttr (Arg 0 0) k v toggleClass :: Text -> DynVal Bool -> HtmlM () toggleClass className val = do @@ -189,6 +193,37 @@ toggleClass className val = do lift $ modify \s -> s {evaluation_queue = initCmd v s.evaluation_queue} lift $ subscribe val $ enqueueExpr . updateCmd +dynClassList :: DynVal [Text] -> HtmlM () +dynClassList dynList = undefined -- do + -- reactiveScope <- ask + -- currentNodeVar <- saveCurrentNode + -- initVal <- liftIO dynList.sample + -- let + -- compareList as bs = + -- (diffList as bs, diffList bs as) + -- diffList as bs = List.foldl' + -- (\xs k -> if List.elem k as then xs else k:xs) [] bs + -- f newList (_, _, oldList) = + -- let + -- (added, removed) = compareList oldList newList + -- in + -- Just (added, removed, newList) + -- lift do + -- dynListDiff <- foldDynMaybe f ([], [], []) dynList + -- let + -- initCmd = InsertClassList (Arg 0 0) initVal + -- updateCmd ([], [], _) queue = queue + -- updateCmd (added, [], _) queue = InsertClassList (Var currentNodeVar) added : queue + -- updateCmd ([], removed, _) queue = RemoveClassList (Var currentNodeVar) removed : queue + -- updateCmd (added, removed, _) queue = RemoveClassList (Var currentNodeVar) removed : InsertClassList (Var currentNodeVar) added : queue + -- modQueueIfAlive f = modify \s -> s + -- { evaluation_queue = + -- if Map.member reactiveScope s.finalizers + -- then f s.evaluation_queue else s.evaluation_queue + -- } + -- modify \s -> s {evaluation_queue = initCmd : s.evaluation_queue} + -- dynListDiff.updates.subscribe $ modQueueIfAlive . updateCmd + --------------------- -- DYNAMIC CONTENT -- --------------------- @@ -318,8 +353,8 @@ destroyBoundary boundary = enqueueExpr (ClearBoundary (Var boundary) True) attachHtml :: Expr -> HtmlM a -> ClickM a attachHtml rootElm contents = do savedQueue <- state saveQueue - evalStateT contents.unHtmlT Nothing - <* modify (enqueueHtml savedQueue) + evalStateT contents.unHtmlT Nothing <* + modify (enqueueHtml savedQueue) where enqueueHtml saved s = s {evaluation_queue = e : saved} where e = Lam (RevSeq (Arg 0 0 : s.evaluation_queue)) `Apply` [rootElm] diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 8f99896..60bf423 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -66,39 +66,37 @@ installFinalizer :: ClickM () -> ResourceScope -> InternalState -> InternalState installFinalizer k scope s = s {finalizers = (scope, CustomFinalizer k) : s.finalizers} -subscribe :: - DynVal a -> - (a -> ClickM ()) -> - ResourceScope -> - InternalState -> InternalState -subscribe (ConstVal _) _ _ s = s -subscribe (FromVar (SourceVar srcId _)) fn scope s = s {subscriptions} - where - subscriptions = newSub : s.subscriptions - newSub = (scope, srcId, fn . unsafeCoerce) -subscribe (FromVar (OverrideVar _ var)) fn scope s = - subscribe (FromVar var) fn scope s -subscribe (FromVar (LensMap l var)) fn scope s = - subscribe (FromVar var) (fn . getConst . l Const) scope s -subscribe (MapVal v f) fn scope s = subscribe v (fn . f) scope s -subscribe (MapHoldVal _ _ srcId ref) fn scope s = s {subscriptions} - where - subscriptions = newSub : s.subscriptions - newSub = (scope, srcId, fn . unsafeCoerce) -subscribe (SplatVal fv av) fn scope s = - subscribe av g scope $ subscribe fv f scope $ attachCb s +subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () +subscribe (ConstVal _) _ = return () +subscribe (FromVar (SourceVar srcid _)) k = reactive_ g where + g scope s = s {subscriptions = (scope, srcid, k . unsafeCoerce) : s.subscriptions } +subscribe (FromVar (OverrideVar _ var)) k = + subscribe (FromVar var) k +subscribe (FromVar (LensMap l var)) k = + subscribe (FromVar var) (k . getConst . l Const) +subscribe (MapVal v f) k = subscribe v (k . f) +subscribe (MapHoldVal _ _ srcid ref) k = reactive_ g where + g scope s = s {subscriptions = (scope, srcid, k . unsafeCoerce) : s.subscriptions } +subscribe (SplatVal fv av) k = do + src <- reactive h + subscribe fv $ f src + subscribe av $ g src where - f fv' = do + h scope s = (s', SourceId s.next_id) where + s' = s + { subscriptions = newsub : s.subscriptions + , next_id = s.next_id + 1 + } + newsub = (scope, SourceId s.next_id, k . unsafeCoerce) + f src fv' = do av' <- readVal av - modify $ unsafeTrigger varid $ fv' av' - g av' = do + modify $ unsafeTrigger src $ fv' av' + g src av' = do fv' <- readVal fv - modify $ unsafeTrigger varid $ fv' av' - attachCb s = s - { subscriptions = (scope, varid, fn . unsafeCoerce) : s.subscriptions - , next_id = s.next_id + 1 - } - varid = SourceId s.next_id + modify $ unsafeTrigger src $ fv' av' +subscribe (OverrideSub f a) k = f (subscribe a) k +subscribe (FoldVal f a b srcid ref) k = reactive_ g where + g scope s = s {subscriptions = (scope, srcid, k . unsafeCoerce) : s.subscriptions } readVal :: DynVal a -> ClickM a readVal (ConstVal a) = pure a @@ -106,6 +104,8 @@ readVal (FromVar var) = readVar var readVal (MapVal val f) = fmap f $ readVal val readVal (MapHoldVal _ _ _ ref) = liftIO $ readIORef ref readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) +readVal (OverrideSub _ a) = readVal a +readVal (FoldVal _ _ _ _ ref) = liftIO $ readIORef ref readVar :: DynVar a -> ClickM a readVar (SourceVar _ ref) = liftIO $ readIORef ref @@ -173,8 +173,8 @@ data ClientMessage -- devserver) mapHoldVal :: (a -> b) -> DynVal a -> ClickM (DynVal b) -mapHoldVal f a = do - a <- readVal a +mapHoldVal f da = do + a <- readVal da ref <- liftIO $ newIORef $ f a reactive $ g ref where @@ -186,4 +186,20 @@ mapHoldVal f a = do liftIO $ writeIORef ref b modify $ unsafeTrigger srcId b s' = s {subscriptions = newSub : s.subscriptions, next_id = succ s.next_id} - val = MapHoldVal a f srcId ref + val = MapHoldVal da f srcId ref + +foldVal :: (a -> b -> b) -> b -> DynVal a -> ClickM (DynVal b) +foldVal f b da = do + ref <- liftIO $ newIORef b + reactive $ g ref + where + g ref scope s = (s', val) where + srcId = SourceId s.next_id + newSub = (scope, srcId, k . unsafeCoerce) + k a = do + b <- liftIO $ readIORef ref + let b' = f a b + liftIO $ writeIORef ref b' + modify $ unsafeTrigger srcId b' + s' = s {subscriptions = newSub : s.subscriptions, next_id = succ s.next_id} + val = FoldVal f b da srcId ref diff --git a/src/Clickable/Property.hs b/src/Clickable/Property.hs index 1e20ccf..dd8c205 100644 --- a/src/Clickable/Property.hs +++ b/src/Clickable/Property.hs @@ -26,11 +26,11 @@ dynClass = dynProp "className" {-# INLINE dynClass #-} dynChecked :: DynVal Bool -> HtmlM () -dynChecked = dynBoolProp "checked" +dynChecked = dynProp "checked" {-# INLINE dynChecked #-} dynDisabled :: DynVal Bool -> HtmlM () -dynDisabled = dynBoolProp "disabled" +dynDisabled = dynProp "disabled" {-# INLINE dynDisabled #-} title_ :: Text -> HtmlM () @@ -38,11 +38,11 @@ title_ = property "title" {-# INLINE title_ #-} selected_ :: Bool -> HtmlM () -selected_ = boolProperty "selected" +selected_ = property "selected" {-# INLINE selected_ #-} hidden_ :: Bool -> HtmlM () -hidden_ = boolProperty "hidden" +hidden_ = property "hidden" {-# INLINE hidden_ #-} value_ :: Text -> HtmlM () @@ -66,7 +66,7 @@ action_ = property "action" {-# INLINE action_ #-} autocomplete_ :: Bool -> HtmlM () -autocomplete_ b = property "autocomplete" (if b then "on" else "off") +autocomplete_ b = property @Text "autocomplete" (if b then "on" else "off") {-# INLINE autocomplete_ #-} autosave_ :: Text -> HtmlM () @@ -74,7 +74,7 @@ autosave_ = property "autosave" {-# INLINE autosave_ #-} disabled_ :: Bool -> HtmlM () -disabled_ = boolProperty "disabled" +disabled_ = property "disabled" {-# INLINE disabled_ #-} enctype_ :: Text -> HtmlM () @@ -102,11 +102,11 @@ method_ = property "method" {-# INLINE method_ #-} multiple_ :: Bool -> HtmlM () -multiple_ = boolProperty "multiple" +multiple_ = property "multiple" {-# INLINE multiple_ #-} novalidate_ :: Bool -> HtmlM () -novalidate_ = boolProperty "noValidate" +novalidate_ = property "noValidate" {-# INLINE novalidate_ #-} pattern_ :: Text -> HtmlM () @@ -114,11 +114,11 @@ pattern_ = property "pattern" {-# INLINE pattern_ #-} readonly_ :: Bool -> HtmlM () -readonly_ = boolProperty "readOnly" +readonly_ = property "readOnly" {-# INLINE readonly_ #-} required_ :: Bool -> HtmlM () -required_ = boolProperty "required" +required_ = property "required" {-# INLINE required_ #-} size_ :: Text -> HtmlM () @@ -222,15 +222,15 @@ alt_ = property "alt" {-# INLINE alt_ #-} autoplay_ :: Bool -> HtmlM () -autoplay_ = boolProperty "autoplay" +autoplay_ = property "autoplay" {-# INLINE autoplay_ #-} controls_ :: Bool -> HtmlM () -controls_ = boolProperty "controls" +controls_ = property "controls" {-# INLINE controls_ #-} loop_ :: Bool -> HtmlM () -loop_ = boolProperty "loop" +loop_ = property "loop" {-# INLINE loop_ #-} preload_ :: Text -> HtmlM () @@ -242,7 +242,7 @@ poster_ = property "poster" {-# INLINE poster_ #-} default_ :: Bool -> HtmlM () -default_ = boolProperty "default" +default_ = property "default" {-# INLINE default_ #-} kind_ :: Text -> HtmlM () @@ -342,11 +342,11 @@ placeholder_ = property "placeholder" {-# INLINE placeholder_ #-} checked_ :: Bool -> HtmlM () -checked_ = boolProperty "checked" +checked_ = property "checked" {-# INLINE checked_ #-} autofocus_ :: Bool -> HtmlM () -autofocus_ = boolProperty "autofocus" +autofocus_ = property "autofocus" {-# INLINE autofocus_ #-} class_ :: Text -> HtmlM () diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index ab99367..e09d831 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -162,6 +162,9 @@ valueToExpr = \case Value.Object kv -> Object $ fmap (\(k, v) -> (k, valueToExpr v)) kv Value.Uint8Array a -> Uint8Array a +toExpr :: Value.ToValue a => a -> Expr +toExpr = valueToExpr . Value.toValue + data VarId = VarId ResourceScope Int64 deriving stock (Generic, Show, Ord, Eq) deriving anyclass (Binary) diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index adb8190..bf002bd 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -25,8 +25,14 @@ data DynVal a where ConstVal :: a -> DynVal a FromVar :: DynVar a -> DynVal a MapVal :: DynVal a -> (a -> b) -> DynVal b + FoldVal :: (a -> b -> b) -> b -> DynVal a -> SourceId -> IORef b -> DynVal b + -- ^ @DynVal a@ should really be @Event a@ MapHoldVal :: DynVal a -> (a -> b) -> SourceId -> IORef b -> DynVal b + -- ^ todo: need redesign SplatVal :: DynVal (a -> b) -> DynVal a -> DynVal b + OverrideSub :: (SubscribeFn a -> SubscribeFn a) -> DynVal a -> DynVal a + +type SubscribeFn a = (a -> ClickM ()) -> ClickM () instance Functor DynVal where fmap = flip MapVal From 5dc53880cd5210c885baa245f92e3c1e8d9e9034 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 10 Apr 2024 23:50:24 +0400 Subject: [PATCH 28/64] dynClassList --- src/Clickable/Core.hs | 64 ++++++++++++++++++++------------------- src/Clickable/DOM.hs | 39 ++++++++++++++++++++++++ src/Clickable/Internal.hs | 4 +-- 3 files changed, 74 insertions(+), 33 deletions(-) diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index ba7e6bb..e2f98c1 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -13,6 +13,7 @@ import Data.IORef import Data.String import Data.Text (Text) import Data.Text qualified as Text +import Data.List qualified as List import Data.Tuple import Clickable.Internal (reactive, reactive_) @@ -34,13 +35,16 @@ newVar a = do overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a overrideVar = OverrideVar +lensMap :: Lens' s a -> DynVar s -> DynVar a +lensMap = LensMap + mapHoldVal :: (a -> b) -> DynVal a -> ClickM (DynVal b) mapHoldVal = Internal.mapHoldVal -readVal :: DynVal a -> ClickM a +readVal :: MonadIO m => DynVal a -> m a readVal = Internal.readVal -readVar :: DynVar a -> ClickM a +readVar :: MonadIO m => DynVar a -> m a readVar = Internal.readVar modifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a @@ -194,35 +198,33 @@ toggleClass className val = do lift $ subscribe val $ enqueueExpr . updateCmd dynClassList :: DynVal [Text] -> HtmlM () -dynClassList dynList = undefined -- do - -- reactiveScope <- ask - -- currentNodeVar <- saveCurrentNode - -- initVal <- liftIO dynList.sample - -- let - -- compareList as bs = - -- (diffList as bs, diffList bs as) - -- diffList as bs = List.foldl' - -- (\xs k -> if List.elem k as then xs else k:xs) [] bs - -- f newList (_, _, oldList) = - -- let - -- (added, removed) = compareList oldList newList - -- in - -- Just (added, removed, newList) - -- lift do - -- dynListDiff <- foldDynMaybe f ([], [], []) dynList - -- let - -- initCmd = InsertClassList (Arg 0 0) initVal - -- updateCmd ([], [], _) queue = queue - -- updateCmd (added, [], _) queue = InsertClassList (Var currentNodeVar) added : queue - -- updateCmd ([], removed, _) queue = RemoveClassList (Var currentNodeVar) removed : queue - -- updateCmd (added, removed, _) queue = RemoveClassList (Var currentNodeVar) removed : InsertClassList (Var currentNodeVar) added : queue - -- modQueueIfAlive f = modify \s -> s - -- { evaluation_queue = - -- if Map.member reactiveScope s.finalizers - -- then f s.evaluation_queue else s.evaluation_queue - -- } - -- modify \s -> s {evaluation_queue = initCmd : s.evaluation_queue} - -- dynListDiff.updates.subscribe $ modQueueIfAlive . updateCmd +dynClassList dynList = do + scope <- lift $ asks (.scope) + n <- saveCurrentNode + initVal <- lift $ readVal dynList + let + compareList as bs = + (diffList as bs, diffList bs as) + diffList as bs = List.foldl' + (\xs k -> if List.elem k as then xs else k:xs) [] bs + f newList (_, _, oldList) = + let + (added, removed) = compareList oldList newList + in + (added, removed, newList) + lift do + dynListDiff <- Internal.foldVal f ([], [], []) dynList + let + initCmd = InsertClassList (Arg 0 0) initVal + updateCmd ([], [], _) queue = queue + updateCmd (added, [], _) queue = InsertClassList (Var n) added : queue + updateCmd ([], removed, _) queue = RemoveClassList (Var n) removed : queue + updateCmd (added, removed, _) queue = RemoveClassList (Var n) removed : InsertClassList (Var n) added : queue + modQueue f = modify \s -> s + { evaluation_queue = f s.evaluation_queue + } + modify \s -> s {evaluation_queue = initCmd : s.evaluation_queue} + subscribe dynListDiff $ modQueue . updateCmd --------------------- -- DYNAMIC CONTENT -- diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index 0ce0995..a74e705 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -114,6 +114,10 @@ instance IsEventName "select/change" where type EventListenerCb "select/change" = Text -> ClickM () addEventListenerArgs = selectChangeConnectArgs +instance IsEventName "mousewheel" where + type EventListenerCb "mousewheel" = MouseWheel -> ClickM () + addEventListenerArgs = mouseWheelConnectArgs + eventListenerOptions :: Text -> Bool -> Bool -> ConnectResourceArgs (ClickM ()) eventListenerOptions eventName preventDef stopProp = ConnectResourceArgs { aquire_resource = \scope sourceId -> @@ -266,3 +270,38 @@ popstateConnectArgs = ConnectResourceArgs \})" `Apply` [Id "window", Lam (TriggerCallback sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromValue event) k } + +-- | Collection of deltaX, deltaY and deltaZ properties from WheelEvent +-- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent +data MouseWheel = MouseWheel + { mw_delta_x :: Int64 + , mw_delta_y :: Int64 + , mw_delta_z :: Int64 + , mw_alt_key :: Bool + , mw_ctrl_key :: Bool + , mw_meta_key :: Bool + , mw_shift_key :: Bool + } deriving stock (Eq, Show, Generic) + deriving anyclass (FromValue, ToValue) + +-- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent +mouseWheelConnectArgs :: ConnectResourceArgs (MouseWheel -> ClickM ()) +mouseWheelConnectArgs = ConnectResourceArgs + { mk_callback = \k j -> forM_ (fromValue j) k + , aquire_resource = \scope sourceId -> Eval + "(function(target, haskellCb){\n\ + \ function listener(event){\n\ + \ haskellCb({\n\ + \ mw_delta_x: event.deltaX,\n\ + \ mw_delta_y: event.deltaY,\n\ + \ mw_delta_z: event.deltaZ,\n\ + \ mw_alt_key: event.altKey,\n\ + \ mw_ctrl_key: event.ctrlKey,\n\ + \ mw_meta_key: event.metaKey,\n\ + \ mw_shift_key: event.shiftKey\n\ + \ });\n\ + \ }\n\ + \ target.addEventListener('popstate', listener);\n\ + \ return () => target.removeEventListener('popstate', listener);\n\ + \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + } diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 60bf423..be07c54 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -98,7 +98,7 @@ subscribe (OverrideSub f a) k = f (subscribe a) k subscribe (FoldVal f a b srcid ref) k = reactive_ g where g scope s = s {subscriptions = (scope, srcid, k . unsafeCoerce) : s.subscriptions } -readVal :: DynVal a -> ClickM a +readVal :: MonadIO m => DynVal a -> m a readVal (ConstVal a) = pure a readVal (FromVar var) = readVar var readVal (MapVal val f) = fmap f $ readVal val @@ -107,7 +107,7 @@ readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) readVal (OverrideSub _ a) = readVal a readVal (FoldVal _ _ _ _ ref) = liftIO $ readIORef ref -readVar :: DynVar a -> ClickM a +readVar :: MonadIO m => DynVar a -> m a readVar (SourceVar _ ref) = liftIO $ readIORef ref readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var readVar (OverrideVar _ var) = readVar var From 88ff1594ccbdb7ab16b37635e96b46e0d6e977e6 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 11 Apr 2024 19:00:35 +0400 Subject: [PATCH 29/64] IEEE-754 format for floating point numbers --- jsbits/binary.ts | 24 ++++++------------------ jsbits/protocol.ts | 8 ++++---- src/Clickable/Main/Dev.hs | 2 +- src/Clickable/Protocol.hs | 4 ++-- src/Clickable/Protocol/Value.hs | 15 ++++++++++++--- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/jsbits/binary.ts b/jsbits/binary.ts index 3f355ac..0576114 100644 --- a/jsbits/binary.ts +++ b/jsbits/binary.ts @@ -146,23 +146,9 @@ export function runDecoder
( return [val as any as A, ptr + 8]; } if (decoder instanceof Float64Decoder) { - // FFS: Data.Binary represents a Double as a tuple (Integer, Int) - // which is 25 bytes long! - - // const buffer = new ArrayBuffer(8); - // const uint8View = new Uint8Array(buffer); - // uint8View[0] = mem[ptr]; - // uint8View[1] = mem[ptr + 1]; - // uint8View[2] = mem[ptr + 2]; - // uint8View[3] = mem[ptr + 3]; - // uint8View[4] = mem[ptr + 4]; - // uint8View[5] = mem[ptr + 5]; - // uint8View[6] = mem[ptr + 6]; - // uint8View[7] = mem[ptr + 7]; - // const float64View = new Float64Array(buffer); - // const val = float64View[0]; - // return [val as any as A, ptr + 8]; - throw new Error("Unimplemented"); + const view = new DataView(mem.buffer); + const value = view.getFloat64(ptr, true) as any; + return [value, ptr + 8]; } if (decoder instanceof StringDecoder) { const len = mem[ptr + 7] + @@ -263,7 +249,9 @@ export function runEncoder( return ptr + 8; } if (decoder instanceof Float64Decoder) { - throw new Error("Unimplemented"); + const view = new DataView(mem.buffer); + view.setFloat64(ptr, value as number, true); + return ptr + 8; } if (decoder instanceof StringDecoder) { const str = value as any as string; diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index a96ad79..b5c7e99 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -66,7 +66,7 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc const rhs: any = evalExpr(hscb, idenScope, argScope, exp.exp); return rhs[exp.ix]; } - case ExprTag.Add: { + case ExprTag.Plus: { const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as number; const rhs = evalExpr(hscb, idenScope, argScope, exp[1]) as number; return lhs + rhs; @@ -346,7 +346,7 @@ export enum ExprTag { SetProp, Ix, - Add, + Plus, Subtract, Multiply, Divide, @@ -399,7 +399,7 @@ export type Expr = | { tag: ExprTag.SetProp, 0: Expr, 1: string, 2: Expr } | { tag: ExprTag.Ix, exp: Expr, ix: number } - | { tag: ExprTag.Add, 0: Expr, 1: Expr } + | { tag: ExprTag.Plus, 0: Expr, 1: Expr } | { tag: ExprTag.Subtract, 0: Expr, 1: Expr } | { tag: ExprTag.Multiply, 0: Expr, 1: Expr } | { tag: ExprTag.Divide, 0: Expr, 1: Expr } @@ -451,7 +451,7 @@ export const expr = b.recursive(self => b.discriminate({ [ExprTag.SetProp]: b.record({ 0: self, 1: b.string, 2: self }), [ExprTag.Ix]: b.record({ exp: self, ix: b.int64 }), - [ExprTag.Add]: b.record({ 0: self, 1: self }), + [ExprTag.Plus]: b.record({ 0: self, 1: self }), [ExprTag.Subtract]: b.record({ 0: self, 1: self }), [ExprTag.Multiply]: b.record({ 0: self, 1: self }), [ExprTag.Divide]: b.record({ 0: self, 1: self }), diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 27ce015..2b428af 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -305,4 +305,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>m,Gk:()=>x,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>T,b9:()=>D,g1:()=>O,tB:()=>U});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class d extends _{constructor(e){super(),this._self=e}}class f extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return y(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof d)return E(e._self,t);if(e instanceof f){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=y(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof d)return g(e._self,t,r);if(e instanceof f){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)throw new Error(\"Unimplemented\");if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function y(e){return Math.ceil(Math.log2(e)/8)}const h=new a,x=new s,m=new i,T=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new f(e)}function U(e){const t=new d(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Add:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Add=11]=\"Add\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Add]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const d=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(d);const{ret:f,fd_obj:E}=o.fds[e].path_open(t,d,_,a,i,c);if(0!=f)return f;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class d{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class f{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new f;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new d;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};var h=__webpack_require__(366);function x(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,m,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}const m=[window,null];function T(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(y)});Object.assign(y,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(y,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(y,t);y.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield T(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield x(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield T(t.data);x(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,Gk:()=>x,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>m,b9:()=>D,g1:()=>O,tB:()=>U});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return y(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=y(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function y(e){return Math.ceil(Math.log2(e)/8)}const h=new a,x=new s,T=new i,m=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function U(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,a,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class d{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new d;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};var h=__webpack_require__(366);function x(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,T,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}const T=[window,null];function m(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(y)});Object.assign(y,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(y,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(y,t);y.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield m(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield x(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield m(t.data);x(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index e09d831..263c7a7 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -44,7 +44,7 @@ data Expr -- ^ JavaScript boolean value | I64 Int64 -- ^ JavaScript integer number - | F64 Double + | F64 Value.Float64 -- ^ JavaScript floating point number | String Text -- ^ JavaScript string @@ -67,7 +67,7 @@ data Expr -- ^ Read value from an integer index of an object. @(Ix (Id -- "foo") 0)@ is equivalent to @foo[0]@ JavaScript expression - | Add Expr Expr + | Plus Expr Expr -- ^ Binary addition @(Add 256 5647)@ is equivalent to @256 + 5647@ | Subtract Expr Expr -- ^ Binary substraction @(Subtract 256 5647)@ is equivalent to @256 - 5647@ diff --git a/src/Clickable/Protocol/Value.hs b/src/Clickable/Protocol/Value.hs index c939e4a..3ca8531 100644 --- a/src/Clickable/Protocol/Value.hs +++ b/src/Clickable/Protocol/Value.hs @@ -1,6 +1,8 @@ module Clickable.Protocol.Value where import Data.Binary +import Data.Binary.Put +import Data.Binary.Get import Data.ByteString import Data.Kind import Data.List qualified as List @@ -14,7 +16,7 @@ data Value = Null | Bool Bool | I64 Int64 - | F64 Double + | F64 Float64 | String Text | Array [Value] | Object [(Text, Value)] @@ -22,6 +24,13 @@ data Value deriving stock (Generic, Show) deriving anyclass (Binary) +newtype Float64 = Float64 {unFloat64 :: Double} + deriving newtype (Show, Ord, Eq, Floating, RealFloat, Fractional, Num, RealFrac, Real) + +instance Binary Float64 where + put = putDoublele . unFloat64 + get = fmap Float64 getDoublele + class ToValue a where toValue :: a -> Value default toValue :: (Generic a, GToValue (Rep a)) => a -> Value @@ -33,7 +42,7 @@ instance ToValue Bool where toValue = Bool instance ToValue Int64 where toValue = I64 -instance ToValue Double where toValue = F64 +instance ToValue Double where toValue = F64 . Float64 instance ToValue Char where toValue c = String $ Text.cons c Text.empty @@ -70,7 +79,7 @@ instance FromValue Int64 where instance FromValue Double where fromValue = \case I64 j -> Just $ fromIntegral j - F64 j -> Just j + F64 (Float64 j) -> Just j _ -> Nothing instance FromValue Char where From 7ea7ddf96df35f502b58b7081f1eb6b7f60abda1 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sat, 13 Apr 2024 20:35:44 +0400 Subject: [PATCH 30/64] Int32Le --- jsbits/binary.ts | 41 +++++++++++---------------------- jsbits/protocol.ts | 38 +++++++++++++++--------------- src/Clickable/DOM.hs | 12 +++++----- src/Clickable/Main/Dev.hs | 2 +- src/Clickable/Protocol.hs | 18 +++++++-------- src/Clickable/Protocol/Value.hs | 17 ++++++++++---- src/Clickable/Types.hs | 3 ++- 7 files changed, 62 insertions(+), 69 deletions(-) diff --git a/jsbits/binary.ts b/jsbits/binary.ts index 0576114..70ed1b0 100644 --- a/jsbits/binary.ts +++ b/jsbits/binary.ts @@ -26,7 +26,7 @@ export class DecoderBase { export type Decoder = | Int8Decoder - | Int64Decoder + | Int32Decoder | Float64Decoder | Uint8ArrayDecoder | StringDecoder @@ -39,7 +39,7 @@ export type Decoder = export class Int8Decoder extends DecoderBase { } -export class Int64Decoder extends DecoderBase { +export class Int32Decoder extends DecoderBase { } export class Float64Decoder extends DecoderBase { } @@ -79,8 +79,8 @@ export function computeSize( if (decoder instanceof Int8Decoder) { return 1; } - if (decoder instanceof Int64Decoder) { - return 8; + if (decoder instanceof Int32Decoder) { + return 4; } if (decoder instanceof Float64Decoder) { return 8; @@ -132,18 +132,10 @@ export function runDecoder( const result = mem[ptr] as any as A; return [result, ptr + 1]; } - if (decoder instanceof Int64Decoder) { - // Data.Binary encodes the integers with Big Endian encoding, what - // the heck? - const val = mem[ptr + 7] + - (mem[ptr + 6] << 8) + - (mem[ptr + 5] << 16) + - (mem[ptr + 4] << 24) + - (mem[ptr + 3] << 32) + - (mem[ptr + 2] << 40) + - (mem[ptr + 1] << 48) + - (mem[ptr] << 56); - return [val as any as A, ptr + 8]; + if (decoder instanceof Int32Decoder) { + const view = new DataView(mem.buffer); + const value = view.getInt32(ptr, true) as any; + return [value as any as A, ptr + 4]; } if (decoder instanceof Float64Decoder) { const view = new DataView(mem.buffer); @@ -236,17 +228,10 @@ export function runEncoder( mem[ptr] = value as any as number; return ptr + 1; } - if (decoder instanceof Int64Decoder) { - const val = value as any as number; - mem[ptr + 7] = val & 0xFF; - mem[ptr + 6] = (val >> 8) & 0xFF; - mem[ptr + 5] = (val >> 16) & 0xFF; - mem[ptr + 4] = (val >> 24) & 0xFF; - // mem[ptr + 3] = (val >> 32) & 0xFF; - // mem[ptr + 2] = (val >> 40) & 0xFF; - // mem[ptr + 1] = (val >> 48) & 0xFF; - // mem[ptr] = (val >> 56) & 0xFF; - return ptr + 8; + if (decoder instanceof Int32Decoder) { + const view = new DataView(mem.buffer); + view.setInt32(ptr, value as number, true); + return ptr + 4; } if (decoder instanceof Float64Decoder) { const view = new DataView(mem.buffer); @@ -342,7 +327,7 @@ function readDiscriminator(dscrSize: number, mem: Uint8Array, ix: HaskellPointer export const int8 = new Int8Decoder(); -export const int64 = new Int64Decoder(); +export const int32 = new Int32Decoder(); export const float64 = new Float64Decoder(); diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index b5c7e99..76b839a 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -34,7 +34,7 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc case ExprTag.Boolean: { return exp[0] != 0; } - case ExprTag.I64: { + case ExprTag.I32: { return exp[0]; } case ExprTag.F64: { @@ -274,7 +274,7 @@ export function unknownToValue(inp: unknown): Value { } if (typeof(inp) === 'number') { if (Number.isInteger(inp)) { - return { tag: ValueTag.I64, 0: inp }; + return { tag: ValueTag.I32, 0: inp }; } else { return { tag: ValueTag.F64, 0: inp }; } @@ -302,7 +302,7 @@ export function unknownToValue(inp: unknown): Value { export enum ValueTag { Null, Boolean, - I64, + I32, F64, String, Array, @@ -313,7 +313,7 @@ export enum ValueTag { export type Value = | { tag: ValueTag.Null } | { tag: ValueTag.Boolean, 0: number } - | { tag: ValueTag.I64, 0: number } + | { tag: ValueTag.I32, 0: number } | { tag: ValueTag.F64, 0: number } | { tag: ValueTag.String, 0: string } | { tag: ValueTag.Array, 0: Value[] } @@ -324,7 +324,7 @@ export type Value = export const jvalue = b.recursive(self => b.discriminate({ [ValueTag.Null]: b.record({ }), [ValueTag.Boolean]: b.record({ 0: b.int8 }), - [ValueTag.I64]: b.record({ 0: b.int64 }), + [ValueTag.I32]: b.record({ 0: b.int32 }), [ValueTag.F64]: b.record({ 0: b.float64 }), [ValueTag.String]: b.record({ 0: b.string }), [ValueTag.Array]: b.record({ 0: b.array(self) }), @@ -335,7 +335,7 @@ export const jvalue = b.recursive(self => b.discriminate({ export enum ExprTag { Null, Boolean, - I64, + I32, F64, String, Array, @@ -388,7 +388,7 @@ export enum ExprTag { export type Expr = | { tag: ExprTag.Null } | { tag: ExprTag.Boolean, 0: number } - | { tag: ExprTag.I64, 0: number } + | { tag: ExprTag.I32, 0: number } | { tag: ExprTag.F64, 0: number } | { tag: ExprTag.String, 0: string } | { tag: ExprTag.Array, 0: Expr[] } @@ -441,7 +441,7 @@ export type Expr = export const expr = b.recursive(self => b.discriminate({ [ExprTag.Null]: b.record({}), [ExprTag.Boolean]: b.record({ 0: b.int8 }), - [ExprTag.I64]: b.record({ 0: b.int64 }), + [ExprTag.I32]: b.record({ 0: b.int32 }), [ExprTag.F64]: b.record({ 0: b.float64 }), [ExprTag.String]: b.record({ 0: b.string }), [ExprTag.Array]: b.record({ 0: b.array(self) }), @@ -449,7 +449,7 @@ export const expr = b.recursive(self => b.discriminate({ [ExprTag.Dot]: b.record({ 0: self, 1: b.string }), [ExprTag.SetProp]: b.record({ 0: self, 1: b.string, 2: self }), - [ExprTag.Ix]: b.record({ exp: self, ix: b.int64 }), + [ExprTag.Ix]: b.record({ exp: self, ix: b.int32 }), [ExprTag.Plus]: b.record({ 0: self, 1: self }), [ExprTag.Subtract]: b.record({ 0: self, 1: self }), @@ -462,10 +462,10 @@ export const expr = b.recursive(self => b.discriminate({ [ExprTag.Apply]: b.record({ 0: self, 1: b.array(self) }), [ExprTag.Call]: b.record({ 0: self, 1: b.string, 2: b.array(self) }), - [ExprTag.AssignVar]: b.record({ scopeId: b.int64, varId: b.int64, rhs: self }), - [ExprTag.FreeVar]: b.record({ scopeId: b.int64, varId: b.int64 }), - [ExprTag.Var]: b.record({ scopeId: b.int64, varId: b.int64 }), - [ExprTag.FreeScope]: b.record({ scopeId: b.int64 }), + [ExprTag.AssignVar]: b.record({ scopeId: b.int32, varId: b.int32, rhs: self }), + [ExprTag.FreeVar]: b.record({ scopeId: b.int32, varId: b.int32 }), + [ExprTag.Var]: b.record({ scopeId: b.int32, varId: b.int32 }), + [ExprTag.FreeScope]: b.record({ scopeId: b.int32 }), [ExprTag.InsertNode]: b.record({ parent: self, child: self }), [ExprTag.CreateElement]: b.record({ tagName: b.string }), @@ -479,14 +479,14 @@ export const expr = b.recursive(self => b.discriminate({ [ExprTag.InsertBoundary]: b.record({ parent: self }), [ExprTag.ClearBoundary]: b.record({ boundary: self, detach: b.int8 }), - [ExprTag.AddEventListener]: b.record({ reactiveScope: b.int64, target: self, eventName: self, listener: self }), - [ExprTag.ConnectResource]: b.record({ reactiveScope: b.int64, aquire: self }), - [ExprTag.SetTimeout]: b.record({ reactiveScope: b.int64, callback: self, timeout: b.int64 }), - [ExprTag.ApplyFinalizer]: b.record({ reactiveScope: b.int64, finalizerId: self }), + [ExprTag.AddEventListener]: b.record({ reactiveScope: b.int32, target: self, eventName: self, listener: self }), + [ExprTag.ConnectResource]: b.record({ reactiveScope: b.int32, aquire: self }), + [ExprTag.SetTimeout]: b.record({ reactiveScope: b.int32, callback: self, timeout: b.int32 }), + [ExprTag.ApplyFinalizer]: b.record({ reactiveScope: b.int32, finalizerId: self }), [ExprTag.RevSeq]: b.record({ exprs: b.array(self) }), [ExprTag.Eval]: b.record({ rawJavaScript: b.string }), - [ExprTag.TriggerCallback]: b.record({ callbackId: b.int64, arg: self }), + [ExprTag.TriggerCallback]: b.record({ callbackId: b.int32, arg: self }), [ExprTag.UncaughtException]: b.record({ message: b.string }), })); @@ -512,7 +512,7 @@ export enum JavaScriptMessageTag { export const javascriptMessage = b.discriminate({ [JavaScriptMessageTag.Start]: b.record({ 0: jvalue }), [JavaScriptMessageTag.Return]: b.record({ 0: jvalue }), - [JavaScriptMessageTag.TriggerCallback]: b.record({ arg: jvalue, callbackId: b.int64 }), + [JavaScriptMessageTag.TriggerCallback]: b.record({ arg: jvalue, callbackId: b.int32 }), [JavaScriptMessageTag.BeforeUnload]: b.record({}), }); diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index a74e705..8f02b06 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -83,11 +83,11 @@ instance IsEventName "input" where addEventListenerArgs = inputConnectArgs "input" instance IsEventName "keydown" where - type EventListenerCb "keydown" = Int64 -> ClickM () + type EventListenerCb "keydown" = Int32 -> ClickM () addEventListenerArgs = keyboardConnectArgs "keydown" instance IsEventName "keyup" where - type EventListenerCb "keyup" = Int64 -> ClickM () + type EventListenerCb "keyup" = Int32 -> ClickM () addEventListenerArgs = keyboardConnectArgs "keyup" instance IsEventName "focus" where @@ -162,7 +162,7 @@ inputConnectArgs eventName = ConnectResourceArgs -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardConnectArgs :: Text -> ConnectResourceArgs (Int64 -> ClickM ()) +keyboardConnectArgs :: Text -> ConnectResourceArgs (Int32 -> ClickM ()) keyboardConnectArgs eventName = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval ( "(function(target, haskellCb){\n\ @@ -274,9 +274,9 @@ popstateConnectArgs = ConnectResourceArgs -- | Collection of deltaX, deltaY and deltaZ properties from WheelEvent -- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent data MouseWheel = MouseWheel - { mw_delta_x :: Int64 - , mw_delta_y :: Int64 - , mw_delta_z :: Int64 + { mw_delta_x :: Int32 + , mw_delta_y :: Int32 + , mw_delta_z :: Int32 , mw_alt_key :: Bool , mw_ctrl_key :: Bool , mw_meta_key :: Bool diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 2b428af..5ffffbf 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -305,4 +305,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,Gk:()=>x,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>m,b9:()=>D,g1:()=>O,tB:()=>U});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 8;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return y(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),r+8];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=y(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s){const e=_;return t[r+7]=255&e,t[r+6]=e>>8&255,t[r+5]=e>>16&255,t[r+4]=e>>24&255,r+8}if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function y(e){return Math.ceil(Math.log2(e)/8)}const h=new a,x=new s,T=new i,m=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function U(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I64:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I64,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I64=2]=\"I64\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,a,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class d{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new d;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};var h=__webpack_require__(366);function x(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,T,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}const T=[window,null];function m(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(y)});Object.assign(y,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(y,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(y,t);y.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield m(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield x(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield m(t.data);x(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,HA:()=>x,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>m,b9:()=>D,g1:()=>O,tB:()=>A});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 4;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return y(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[new DataView(t.buffer).getInt32(r,!0),r+4];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=y(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s)return new DataView(t.buffer).setInt32(r,_,!0),r+4;if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function y(e){return Math.ceil(Math.log2(e)/8)}const h=new a,x=new s,T=new i,m=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function A(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,a,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class d{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new d;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};var h=__webpack_require__(366);function x(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,T,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}const T=[window,null];function m(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(y)});Object.assign(y,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(y,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(y,t);y.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield m(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield x(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield m(t.data);x(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index 263c7a7..7c4fb27 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -42,7 +42,7 @@ data Expr -- ^ Represents null or undefined values | Boolean Bool -- ^ JavaScript boolean value - | I64 Int64 + | I32 Value.Int32Le -- ^ JavaScript integer number | F64 Value.Float64 -- ^ JavaScript floating point number @@ -155,7 +155,7 @@ valueToExpr :: Value.Value -> Expr valueToExpr = \case Value.Null -> Null Value.Bool a -> Boolean a - Value.I64 a -> I64 a + Value.I32 a -> I32 a Value.F64 a -> F64 a Value.String a -> String a Value.Array xs -> Array $ fmap valueToExpr xs @@ -165,18 +165,18 @@ valueToExpr = \case toExpr :: Value.ToValue a => a -> Expr toExpr = valueToExpr . Value.toValue -data VarId = VarId ResourceScope Int64 +data VarId = VarId ResourceScope Value.Int32Le deriving stock (Generic, Show, Ord, Eq) deriving anyclass (Binary) -newtype FinalizerId = FinalizerId { unFinalizerId :: Int64 } - deriving newtype (Show, Num, Binary, Ord, Eq) +newtype FinalizerId = FinalizerId { unFinalizerId :: Value.Int32Le } + deriving newtype (Show, Num, Ord, Eq, Binary) -newtype ResourceScope = ResourceScope {unResourceScope :: Int64} - deriving newtype (Show, Num, Binary, Ord, Eq) +newtype ResourceScope = ResourceScope {unResourceScope :: Value.Int32Le} + deriving newtype (Show, Num, Ord, Eq, Binary) -newtype SourceId = SourceId {unSourceId :: Int64} - deriving newtype (Show, Num, Binary, Ord, Eq) +newtype SourceId = SourceId {unSourceId :: Value.Int32Le} + deriving newtype (Show, Num, Ord, Eq, Binary) newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} deriving newtype (IsString, Show, Semigroup, Monoid, Binary) diff --git a/src/Clickable/Protocol/Value.hs b/src/Clickable/Protocol/Value.hs index 3ca8531..ff05022 100644 --- a/src/Clickable/Protocol/Value.hs +++ b/src/Clickable/Protocol/Value.hs @@ -15,7 +15,7 @@ import GHC.Int data Value = Null | Bool Bool - | I64 Int64 + | I32 Int32Le | F64 Float64 | String Text | Array [Value] @@ -31,6 +31,13 @@ instance Binary Float64 where put = putDoublele . unFloat64 get = fmap Float64 getDoublele +newtype Int32Le = Int32Le {unInt32Le :: Int32} + deriving newtype (Show, Ord, Eq, Num, Real, Integral, Enum, Bounded) + +instance Binary Int32Le where + put = putInt32le . unInt32Le + get = fmap Int32Le getInt32le + class ToValue a where toValue :: a -> Value default toValue :: (Generic a, GToValue (Rep a)) => a -> Value @@ -40,7 +47,7 @@ instance ToValue Value where toValue = Prelude.id instance ToValue Bool where toValue = Bool -instance ToValue Int64 where toValue = I64 +instance ToValue Int32 where toValue = I32 . Int32Le instance ToValue Double where toValue = F64 . Float64 @@ -70,15 +77,15 @@ instance FromValue Value where fromValue = pure instance FromValue Bool where fromValue = \case Bool a -> Just a; _ -> Nothing -instance FromValue Int64 where +instance FromValue Int32 where fromValue = \case - I64 j -> Just j + I32 (Int32Le j) -> Just j F64 j -> Just $ floor j _ -> Nothing instance FromValue Double where fromValue = \case - I64 j -> Just $ fromIntegral j + I32 j -> Just $ fromIntegral j F64 (Float64 j) -> Just j _ -> Nothing diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index bf002bd..99386a8 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -11,6 +11,7 @@ import GHC.Generics import GHC.Exts import Clickable.Protocol +import Clickable.Protocol.Value (Int32Le) data DynVar a where SourceVar :: SourceId -> IORef a -> DynVar a @@ -64,7 +65,7 @@ data InternalState = InternalState , finalizers :: [(ResourceScope, FinalizerVal)] , transaction_queue :: Map SourceId (ClickM ()) , evaluation_queue :: [Expr] - , next_id :: Int64 + , next_id :: Int32Le } deriving (Generic) data FinalizerVal From c6e77228045d2532da436281504790517cb1378b Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sun, 14 Apr 2024 03:53:15 +0400 Subject: [PATCH 31/64] Fix a leak in WebSocket handler --- jsbits/dev.ts | 4 ++-- src/Clickable/Internal.hs | 6 ++++-- src/Clickable/Main/Dev.hs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/jsbits/dev.ts b/jsbits/dev.ts index 9839f22..46e4f17 100644 --- a/jsbits/dev.ts +++ b/jsbits/dev.ts @@ -7,8 +7,8 @@ export function startDev(devSocketUri: string, startFlags: unknown = null) { const sendToHaskell = async (jsMsg: JavaScriptMessage, argScope: List) => { websocket.send(p.javascriptMessage.encode(jsMsg)); - const haskMsg = await awaitWebsocketMessage(); - await haskellApp(haskMsg, argScope, sendToHaskell); + // const haskMsg = await awaitWebsocketMessage(); + // await haskellApp(haskMsg, argScope, sendToHaskell); }; websocket.onopen = (_event) => { diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index be07c54..7deeee1 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -1,6 +1,7 @@ module Clickable.Internal where import Control.Applicative +import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.Foldable @@ -155,8 +156,9 @@ syncPoint :: ClickM () syncPoint = do send_message <- asks (.send_message) queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - liftIO $ send_message $ EvalExpr $ RevSeq queue - return () + unless (List.null queue) do + liftIO $ send_message $ EvalExpr $ RevSeq queue + return () reactive :: (ResourceScope -> InternalState -> (InternalState, a)) -> ClickM a reactive f = ClickT $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ f e.scope diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 5ffffbf..b311265 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -305,4 +305,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,HA:()=>x,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>m,b9:()=>D,g1:()=>O,tB:()=>A});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 4;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return y(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[new DataView(t.buffer).getInt32(r,!0),r+4];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=y(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s)return new DataView(t.buffer).setInt32(r,_,!0),r+4;if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function y(e){return Math.ceil(Math.log2(e)/8)}const h=new a,x=new s,T=new i,m=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function A(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,a,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class d{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new d;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};var h=__webpack_require__(366);function x(t,r,n){return e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,T,r,t.expr),_=g.bp(e);return n({tag:g.dB.Return,0:_},r)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}const T=[window,null];function m(e){return new Promise(((t,r)=>{const n=new FileReader;n.onload=()=>{const e=n.result,r=new Uint8Array(e);t(r)},n.onerror=e=>{r(e)},n.readAsArrayBuffer(e)}))}window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(y)});Object.assign(y,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(y,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(y,t);y.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t));const a=yield function(){return new Promise(((t,r)=>{const _=n.onmessage;n.onmessage=a=>e(this,void 0,void 0,(function*(){n.onmessage=_;try{const e=yield m(a.data),r=g.sy.decode(e);t(r)}catch(e){r(e)}}))}))}();yield x(a,r,_)}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const e=yield m(t.data);x(g.sy.decode(e),null,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,HA:()=>y,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>m,b9:()=>D,g1:()=>O,tB:()=>A});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 4;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return x(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[new DataView(t.buffer).getInt32(r,!0),r+4];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=x(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s)return new DataView(t.buffer).setInt32(r,_,!0),r+4;if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function x(e){return Math.ceil(Math.log2(e)/8)}const h=new a,y=new s,T=new i,m=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function A(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,a,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class d{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new d;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let x={};var h=__webpack_require__(366);const y=[window,null];window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(x)});Object.assign(x,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(x,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(x,t);x.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t))}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const r=yield(n=t.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(n)})));var n;!function(t,r,n){e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,y,null,t.expr),r=g.bp(e);return n({tag:g.dB.Return,0:r},null)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}(g.sy.decode(r),0,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" From 664b50bc2144c133d3c2bf00234a38747073b723 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sun, 14 Apr 2024 18:39:53 +0400 Subject: [PATCH 32/64] Recover broken TodoMVC --- examples/todomvc/TodoItem.hs | 20 +++++++++---------- examples/todomvc/TodoList.hs | 2 +- src/Clickable/Types.hs | 38 ++++++++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index 28d957d..5c4b678 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -6,7 +6,7 @@ import Data.Text (Text) import GHC.Int import Clickable import Clickable.Protocol (VarId) -import Clickable.Protocol.Value +import Clickable.Protocol.Value qualified as Value import "this" Utils @@ -28,7 +28,7 @@ data TodoItemAction a where InputAction :: Text -> TodoItemAction () DoubleClickAction :: VarId -> TodoItemAction () CheckedAction :: Bool -> TodoItemAction () - KeydownAction :: Int64 -> TodoItemAction () + KeydownAction :: Int32 -> TodoItemAction () emptyState :: TodoItemState emptyState = TodoItemState "" False Nothing @@ -85,15 +85,15 @@ html cfg = li_ mdo saveCurrentNode return () -instance ToValue TodoItemState where - toValue s = Object - [ ("title", toValue s.title) - , ("completed", toValue s.completed) +instance Value.ToValue TodoItemState where + toValue s = Value.Object + [ ("title", Value.toValue s.title) + , ("completed", Value.toValue s.completed) ] -instance FromValue TodoItemState where - fromValue (Object kv) = do - title <- fromValue =<< List.lookup "title" kv - completed <- fromValue =<< List.lookup "completed" kv +instance Value.FromValue TodoItemState where + fromValue (Value.Object kv) = do + title <- Value.fromValue =<< List.lookup "title" kv + completed <- Value.fromValue =<< List.lookup "completed" kv return TodoItemState {editing=Nothing, ..} fromValue _ = Nothing diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index c91353c..ae7ce72 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -28,7 +28,7 @@ data TodoListAction a where ToggleAllAction :: Bool -> TodoListAction () InputAction :: Text -> TodoListAction () CommitAction :: TodoListAction () - KeydownAction :: Int64 -> TodoListAction () + KeydownAction :: Int32 -> TodoListAction () DeleteItemAction :: Int -> TodoListAction () ClearCompletedAction :: TodoListAction () diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index 99386a8..a0d80fb 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -4,7 +4,6 @@ import Control.Monad.Reader import Control.Monad.Fix import Control.Monad.State import Data.IORef -import Data.Int import Data.Tuple import Data.Map (Map) import GHC.Generics @@ -61,13 +60,40 @@ data InternalEnv = InternalEnv } deriving (Generic) data InternalState = InternalState - { subscriptions :: [(ResourceScope, SourceId, Any -> ClickM ())] - , finalizers :: [(ResourceScope, FinalizerVal)] + { subscriptions :: [Subscription Any] + , finalizers :: [Finalizer] , transaction_queue :: Map SourceId (ClickM ()) , evaluation_queue :: [Expr] , next_id :: Int32Le } deriving (Generic) -data FinalizerVal - = CustomFinalizer (ClickM ()) - | ScopeFinalizer ResourceScope +data Subscription a + = SubscriptionSimple + { ss_scope :: ResourceScope + , ss_event_id :: SourceId + , ss_callback :: a -> ClickM () + } + | forall b. SubscriptionAccum + { sa_resource_scope :: ResourceScope + , sa_event_id :: SourceId + , sa_callback :: a -> b -> ClickM b + , sa_accum_ref :: IORef b + } + +data Finalizer + = CustomFinalizer + { cf_resource_scope :: ResourceScope + , cf_callback :: ClickM () + } + | ScopeFinalizer + { sf_resource_scope :: ResourceScope + , sf_linked_scope :: ResourceScope + } + +finalizerScope :: Finalizer -> ResourceScope +finalizerScope CustomFinalizer {cf_resource_scope} = cf_resource_scope +finalizerScope ScopeFinalizer {sf_resource_scope} = sf_resource_scope + +subscriptionScope :: Subscription a -> ResourceScope +subscriptionScope SubscriptionSimple {ss_scope} = ss_scope +subscriptionScope SubscriptionAccum {sa_resource_scope} = sa_resource_scope From 3fa2fb459e70a14d3725cf451752bf6f318996eb Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 15 Apr 2024 00:00:12 +0400 Subject: [PATCH 33/64] subscribeAccum --- src/Clickable/Core.hs | 53 +++++++++---------- src/Clickable/DOM.hs | 8 +-- src/Clickable/Internal.hs | 105 ++++++++++++++++++++++++-------------- src/Clickable/Types.hs | 6 +-- 4 files changed, 97 insertions(+), 75 deletions(-) diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index e2f98c1..2cad804 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -81,13 +81,15 @@ modifyVarQuiet_ :: DynVar s -> (s -> s) -> ClickM () modifyVarQuiet_ var f = modifyVarQuiet var ((,()) . f) -- todo: needs redesign -holdUniqDyn :: Eq a => DynVal a -> DynVal a -holdUniqDyn a = flip OverrideSub a \next k -> do - old <- readVal a - oldRef <- liftIO $ newIORef old - next \new -> do - old <- liftIO $ atomicModifyIORef' oldRef (new,) - unless (old == new) $ k new +holdUniqDyn :: forall a. Eq a => DynVal a -> DynVal a +holdUniqDyn a = OverrideSub g a where + g :: forall b. SubscribeFn a b -> SubscribeFn a b + g next k = do + old <- readVal a + oldRef <- liftIO $ newIORef old + next \new acc -> do + old <- liftIO $ atomicModifyIORef' oldRef (new,) + if (old /= new) then k new acc else return acc -------------------------------------- -- OPERATIONS OVER evaluation_queue -- @@ -117,8 +119,8 @@ freeScope unlink s = reactive (const (Internal.freeScope unlink s)) >>= applyFin where applyFin [] = enqueueExpr $ FreeScope s - applyFin ((_, ScopeFinalizer s'):xs) = freeScope True s' >> applyFin xs - applyFin ((_, CustomFinalizer x):xs) = x >> applyFin xs + applyFin (ScopeFinalizer{sf_linked_scope}:xs) = freeScope True sf_linked_scope >> applyFin xs + applyFin (CustomFinalizer{cf_callback}:xs) = cf_callback >> applyFin xs installFinalizer :: ClickM () -> ClickM () installFinalizer k = reactive_ $ Internal.installFinalizer k @@ -199,32 +201,27 @@ toggleClass className val = do dynClassList :: DynVal [Text] -> HtmlM () dynClassList dynList = do - scope <- lift $ asks (.scope) n <- saveCurrentNode + scope <- lift $ asks (.scope) initVal <- lift $ readVal dynList let compareList as bs = (diffList as bs, diffList bs as) diffList as bs = List.foldl' (\xs k -> if List.elem k as then xs else k:xs) [] bs - f newList (_, _, oldList) = - let - (added, removed) = compareList oldList newList - in - (added, removed, newList) - lift do - dynListDiff <- Internal.foldVal f ([], [], []) dynList - let - initCmd = InsertClassList (Arg 0 0) initVal - updateCmd ([], [], _) queue = queue - updateCmd (added, [], _) queue = InsertClassList (Var n) added : queue - updateCmd ([], removed, _) queue = RemoveClassList (Var n) removed : queue - updateCmd (added, removed, _) queue = RemoveClassList (Var n) removed : InsertClassList (Var n) added : queue - modQueue f = modify \s -> s - { evaluation_queue = f s.evaluation_queue - } - modify \s -> s {evaluation_queue = initCmd : s.evaluation_queue} - subscribe dynListDiff $ modQueue . updateCmd + k newList (_, _, oldList) = do + let (added, removed) = compareList oldList newList + modQueue $ updateCmd (added, removed, newList) + return (added, removed, newList) + updateCmd ([], [], _) queue = queue + updateCmd (added, [], _) queue = InsertClassList (Var n) added : queue + updateCmd ([], removed, _) queue = RemoveClassList (Var n) removed : queue + updateCmd (added, removed, _) queue = RemoveClassList (Var n) removed : InsertClassList (Var n) added : queue + modQueue f = modify \s -> s + { evaluation_queue = f s.evaluation_queue + } + lift $ enqueueExpr $ InsertClassList (Arg 0 0) initVal + lift $ Internal.subscribeAccum dynList k ([], [], initVal) --------------------- -- DYNAMIC CONTENT -- diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index 8f02b06..1e9e668 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -40,10 +40,10 @@ data ConnectResourceArgs callback = ConnectResourceArgs connectResource :: ConnectResourceArgs callback -> callback -> ClickM () connectResource args k = reactive_ \scope s -> let - callback :: Value -> ClickM () - callback = local (\e -> e {scope}) . args.mk_callback k + k' :: Value -> ClickM () + k' = local (\e -> e {scope}) . args.mk_callback k sourceId = SourceId s.next_id - newSub = (scope, sourceId, callback . unsafeCoerce) + newSub = SubscriptionSimple scope sourceId (k' . unsafeCoerce) connectExpr = ConnectResource scope $ args.aquire_resource scope sourceId in s { evaluation_queue = connectExpr : s.evaluation_queue @@ -167,7 +167,7 @@ keyboardConnectArgs eventName = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval ( "(function(target, haskellCb){\n\ \ function listener(event){\n\ - \ haskellCb(event.target.keyCode);\n\ + \ haskellCb(event.keyCode);\n\ \ }\n\ \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 7deeee1..2a07dab 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -4,11 +4,11 @@ import Control.Applicative import Control.Monad import Control.Monad.Reader import Control.Monad.State -import Data.Foldable import Data.IORef import Data.List qualified as List import Data.Map qualified as Map import Unsafe.Coerce +import GHC.Exts import Clickable.Protocol import Clickable.Protocol.Value (Value) @@ -30,54 +30,61 @@ unsafeTrigger sourceId a = defer sourceId $ gets (.subscriptions) >>= notify where notify [] = return () - notify ((_, s, cb) : xs) - | s == sourceId = cb (unsafeCoerce a) >> notify xs + notify (SubscriptionSimple {ss_event_id, ss_callback} : xs) + | ss_event_id == sourceId = ss_callback (unsafeCoerce a) >> notify xs | otherwise = notify xs + notify (SubscriptionAccum {sa_event_id, sa_callback, sa_accum_ref} : xs) + | sa_event_id == sourceId = notifyAcc sa_callback sa_accum_ref >> notify xs + | otherwise = notify xs + notifyAcc :: forall b. (Any -> b -> ClickM b) -> IORef b -> ClickM () + notifyAcc k ref = do + acc <- liftIO $ readIORef ref + acc' <- k (unsafeCoerce a) acc + liftIO $ writeIORef ref acc' defer k act s = s {transaction_queue = Map.insert k act s.transaction_queue} newScope :: ResourceScope -> InternalState -> (InternalState, ResourceScope) newScope p s = let scopeId = ResourceScope s.next_id - finalizers = (p, ScopeFinalizer scopeId) : s.finalizers + finalizers = ScopeFinalizer p scopeId : s.finalizers s' = s {finalizers, next_id = s.next_id + 1} in (s', scopeId) newVarId :: ResourceScope -> InternalState -> (InternalState, VarId) -newVarId e s = - (s {next_id = s.next_id + 1}, VarId e s.next_id) +newVarId e s = (s {next_id = s.next_id + 1}, VarId e s.next_id) freeScope :: Bool -> ResourceScope -> - InternalState -> (InternalState, [(ResourceScope, FinalizerVal)]) + InternalState -> (InternalState, [Finalizer]) freeScope unlink rscope s = let - chkSub (s, _, _) = s /= rscope - chkFin True (s1, ScopeFinalizer s2) = s1 /= rscope && s2 /= rscope - chkFin True (s, _) = s /= rscope - chkFin False (s, _) = s /= rscope + chkSub s = subscriptionScope s /= rscope + chkFin True ScopeFinalizer{sf_resource_scope, sf_linked_scope} = + sf_resource_scope /= rscope && sf_linked_scope /= rscope + chkFin True CustomFinalizer{cf_resource_scope} = cf_resource_scope /= rscope + chkFin False f = finalizerScope f /= rscope (finalizers, scopeFns) = List.partition (chkFin unlink) s.finalizers subscriptions = List.filter chkSub s.subscriptions in (s {subscriptions, finalizers}, scopeFns) installFinalizer :: ClickM () -> ResourceScope -> InternalState -> InternalState -installFinalizer k scope s = s - {finalizers = (scope, CustomFinalizer k) : s.finalizers} +installFinalizer k scope s = s {finalizers = CustomFinalizer scope k : s.finalizers} -subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () +subscribe :: forall a. DynVal a -> (a -> ClickM ()) -> ClickM () subscribe (ConstVal _) _ = return () subscribe (FromVar (SourceVar srcid _)) k = reactive_ g where - g scope s = s {subscriptions = (scope, srcid, k . unsafeCoerce) : s.subscriptions } + g scope s = s {subscriptions = SubscriptionSimple scope srcid (k . unsafeCoerce) : s.subscriptions } subscribe (FromVar (OverrideVar _ var)) k = subscribe (FromVar var) k subscribe (FromVar (LensMap l var)) k = subscribe (FromVar var) (k . getConst . l Const) subscribe (MapVal v f) k = subscribe v (k . f) subscribe (MapHoldVal _ _ srcid ref) k = reactive_ g where - g scope s = s {subscriptions = (scope, srcid, k . unsafeCoerce) : s.subscriptions } + g scope s = s {subscriptions = SubscriptionSimple scope srcid (k . unsafeCoerce) : s.subscriptions } subscribe (SplatVal fv av) k = do src <- reactive h subscribe fv $ f src @@ -88,16 +95,53 @@ subscribe (SplatVal fv av) k = do { subscriptions = newsub : s.subscriptions , next_id = s.next_id + 1 } - newsub = (scope, SourceId s.next_id, k . unsafeCoerce) + newsub = SubscriptionSimple scope (SourceId s.next_id) (k . unsafeCoerce) + f src fv' = do + av' <- readVal av + modify $ unsafeTrigger src $ fv' av' + g src av' = do + fv' <- readVal fv + modify $ unsafeTrigger src $ fv' av' +subscribe (OverrideSub f d) k = f subscribe' k' where + k' a _ = k a + subscribe' k = subscribe d \a -> k a () + +subscribeAccum :: DynVal a -> (a -> b -> ClickM b) -> b -> ClickM () +subscribeAccum (ConstVal _) _ _ = return () +subscribeAccum (FromVar (SourceVar srcid _)) k b = do + ref <- liftIO $ newIORef b + let newSub scope = SubscriptionAccum scope srcid (k . unsafeCoerce) ref + let g scope s = s {subscriptions = newSub scope : s.subscriptions} + reactive_ g +subscribeAccum (FromVar (OverrideVar _ var)) k b = + subscribeAccum (FromVar var) k b +subscribeAccum (FromVar (LensMap l var)) k b = + subscribeAccum (FromVar var) (k . getConst . l Const) b +subscribeAccum (MapVal v f) k b = subscribeAccum v (k . f) b +subscribeAccum (MapHoldVal _ _ srcid ref) k b = do + ref <- liftIO $ newIORef b + let newSub scope = SubscriptionAccum scope srcid (k . unsafeCoerce) ref + let g scope s = s {subscriptions = newSub scope : s.subscriptions} + reactive_ g +subscribeAccum (SplatVal fv av) k b = do + ref <- liftIO $ newIORef b + let + h scope s = (s', SourceId s.next_id) where + s' = s + { subscriptions = newsub : s.subscriptions + , next_id = s.next_id + 1 + } + newsub = SubscriptionAccum scope (SourceId s.next_id) (k . unsafeCoerce) ref f src fv' = do av' <- readVal av modify $ unsafeTrigger src $ fv' av' g src av' = do fv' <- readVal fv modify $ unsafeTrigger src $ fv' av' -subscribe (OverrideSub f a) k = f (subscribe a) k -subscribe (FoldVal f a b srcid ref) k = reactive_ g where - g scope s = s {subscriptions = (scope, srcid, k . unsafeCoerce) : s.subscriptions } + src <- reactive h + subscribe fv $ f src + subscribe av $ g src +subscribeAccum (OverrideSub f a) k b = f (flip (subscribeAccum a) b) k readVal :: MonadIO m => DynVal a -> m a readVal (ConstVal a) = pure a @@ -106,7 +150,6 @@ readVal (MapVal val f) = fmap f $ readVal val readVal (MapHoldVal _ _ _ ref) = liftIO $ readIORef ref readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) readVal (OverrideSub _ a) = readVal a -readVal (FoldVal _ _ _ _ ref) = liftIO $ readIORef ref readVar :: MonadIO m => DynVar a -> m a readVar (SourceVar _ ref) = liftIO $ readIORef ref @@ -119,7 +162,7 @@ newCallback :: InternalState -> (InternalState, SourceId) newCallback k rscope s = let - new = (rscope, SourceId s.next_id, k . unsafeCoerce) + new = SubscriptionSimple rscope (SourceId s.next_id) (k . unsafeCoerce) subscriptions = new : s.subscriptions in (s { next_id = s.next_id + 1, subscriptions}, SourceId s.next_id) @@ -182,26 +225,10 @@ mapHoldVal f da = do where g ref scope s = (s', val) where srcId = SourceId s.next_id - newSub = (scope, srcId, k . unsafeCoerce) + newSub = SubscriptionSimple scope srcId (k . unsafeCoerce) k a = do let b = f a liftIO $ writeIORef ref b modify $ unsafeTrigger srcId b s' = s {subscriptions = newSub : s.subscriptions, next_id = succ s.next_id} val = MapHoldVal da f srcId ref - -foldVal :: (a -> b -> b) -> b -> DynVal a -> ClickM (DynVal b) -foldVal f b da = do - ref <- liftIO $ newIORef b - reactive $ g ref - where - g ref scope s = (s', val) where - srcId = SourceId s.next_id - newSub = (scope, srcId, k . unsafeCoerce) - k a = do - b <- liftIO $ readIORef ref - let b' = f a b - liftIO $ writeIORef ref b' - modify $ unsafeTrigger srcId b' - s' = s {subscriptions = newSub : s.subscriptions, next_id = succ s.next_id} - val = FoldVal f b da srcId ref diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index a0d80fb..c9cccad 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -25,14 +25,12 @@ data DynVal a where ConstVal :: a -> DynVal a FromVar :: DynVar a -> DynVal a MapVal :: DynVal a -> (a -> b) -> DynVal b - FoldVal :: (a -> b -> b) -> b -> DynVal a -> SourceId -> IORef b -> DynVal b - -- ^ @DynVal a@ should really be @Event a@ MapHoldVal :: DynVal a -> (a -> b) -> SourceId -> IORef b -> DynVal b -- ^ todo: need redesign SplatVal :: DynVal (a -> b) -> DynVal a -> DynVal b - OverrideSub :: (SubscribeFn a -> SubscribeFn a) -> DynVal a -> DynVal a + OverrideSub :: (forall b. SubscribeFn a b -> SubscribeFn a b) -> DynVal a -> DynVal a -type SubscribeFn a = (a -> ClickM ()) -> ClickM () +type SubscribeFn a b = (a -> b -> ClickM b) -> ClickM () instance Functor DynVal where fmap = flip MapVal From b9338c62e240c7822ac93e331ed4d9c657da5e26 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 16 Apr 2024 01:49:03 +0400 Subject: [PATCH 34/64] Change remaining 64 to 32 bit integer --- src/Clickable/Protocol.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index 7c4fb27..87f1353 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -130,7 +130,7 @@ data Expr -- will be freed with 'FreeScope' | ConnectResource ResourceScope Expr -- ^ Returns FinalizerId - | SetTimeout ResourceScope Expr Int64 + | SetTimeout ResourceScope Expr Value.Int32Le -- ^ Returns FinalizerId | ApplyFinalizer ResourceScope Expr -- ^ Actuate given finalizer before the ResourceScope is freed From a232778ebaac92e2c4343990166c88f5c102466c Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 23 Apr 2024 14:27:26 +0400 Subject: [PATCH 35/64] Use tryPutMvar to resolve a memory leak --- src/Clickable/Main/Dev.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index b311265..a2fbd2e 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -161,6 +161,9 @@ fallbackApp _ resp = \ \n\ \\n" +-- WebSocket server needs to be redesigned. Specifically I don't like +-- the use of MVar to transfer the result of evaluation from the +-- browser to haskell thread websocketApp :: DevInstance -> ServerApp websocketApp opt p = let @@ -192,7 +195,7 @@ websocketApp opt p = BrowserMessage (Start flags) -> void $ forkIO $ Internal.launchClickM conn.internal_env $ app.client_app conn flags - BrowserMessage (Return val) -> putMVar conn.return_mvar val + BrowserMessage (Return val) -> void $ tryPutMVar conn.return_mvar val BrowserMessage (TriggerCallbackMsg arg sourceId) -> void $ forkIO $ Internal.launchClickM conn.internal_env $ modify (Internal.unsafeTrigger sourceId arg) From 966d653518303bac3a2a6946e18b6809b26c38b6 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sun, 5 May 2024 19:42:32 +0400 Subject: [PATCH 36/64] MonadCatch, MonadMask, MonadThrow --- src/Clickable/Main/Dev.hs | 4 ++-- src/Clickable/Types.hs | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index a2fbd2e..0e7f945 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -106,8 +106,8 @@ runSettings settings cfg = do staticApp (defaultFileServerSettings docroot) {ss404Handler = Just (withStaticApp docroots next)} forkIfRepl action = do - isRepl <- (== "") <$> getProgName - if isRepl then void (forkIO action) else action + inRepl <- (== "") <$> getProgName + if inRepl then void (forkIO action) else action runDev :: (StartFlags -> ClickM ()) -> IO () runDev clientApp = runSettings diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index c9cccad..8f19507 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -1,6 +1,7 @@ module Clickable.Types where import Control.Monad.Reader +import Control.Monad.Catch import Control.Monad.Fix import Control.Monad.State import Data.IORef @@ -40,10 +41,16 @@ fromVar :: DynVar a -> DynVal a fromVar = FromVar newtype HtmlT m a = HtmlT {unHtmlT :: StateT (Maybe VarId) m a} - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadFix, MonadTrans) + deriving newtype ( + Functor, Applicative, Monad, MonadIO, MonadFix, MonadTrans, + MonadCatch, MonadMask, MonadThrow + ) newtype ClickT m a = ClickT {unClickT :: ReaderT InternalEnv m a} - deriving newtype (Functor, Applicative, Monad, MonadIO, MonadFix, MonadReader InternalEnv, MonadTrans) + deriving newtype ( + Functor, Applicative, Monad, MonadIO, MonadFix, MonadReader InternalEnv, + MonadTrans, MonadCatch, MonadMask, MonadThrow + ) type HtmlM = HtmlT ClickM type ClickM = ClickT IO From 4ffd643fb413fe61c9faf7ee78b56989b51d2ef6 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 9 May 2024 03:40:04 +0400 Subject: [PATCH 37/64] DevServer concurency improvements --- jsbits/dev.ts | 27 +++++++-------------------- jsbits/protocol.ts | 5 ++--- jsbits/wasm.ts | 16 ++++++---------- src/Clickable/Core.hs | 7 ++----- src/Clickable/Internal.hs | 10 +++++----- src/Clickable/Main/Dev.hs | 32 +++++++++++++++++++++----------- src/Clickable/Main/Wasm.hs | 30 +++++++++++++++++++----------- src/Clickable/Protocol.hs | 4 ++-- src/Clickable/Types.hs | 4 ++-- 9 files changed, 66 insertions(+), 69 deletions(-) diff --git a/jsbits/dev.ts b/jsbits/dev.ts index 46e4f17..4db6f1f 100644 --- a/jsbits/dev.ts +++ b/jsbits/dev.ts @@ -5,7 +5,7 @@ import { HaskellMessage, JavaScriptMessage, JavaScriptMessageTag, HaskellMessage export function startDev(devSocketUri: string, startFlags: unknown = null) { const websocket = new WebSocket(devSocketUri); - const sendToHaskell = async (jsMsg: JavaScriptMessage, argScope: List) => { + const sendToHaskell = async (jsMsg: JavaScriptMessage) => { websocket.send(p.javascriptMessage.encode(jsMsg)); // const haskMsg = await awaitWebsocketMessage(); // await haskellApp(haskMsg, argScope, sendToHaskell); @@ -36,34 +36,21 @@ export function startDev(devSocketUri: string, startFlags: unknown = null) { websocket.onclose = (event) => { console.log("WebSocket connection closed:", event); }; - - function awaitWebsocketMessage(): Promise { - return new Promise((resolve, reject) => { - const prevCallback = websocket.onmessage; - websocket.onmessage = async (event) => { - websocket.onmessage = prevCallback; - try { - const binaryDataReceived = await convertBlobToUint8Array(event.data); - const haskMsg = p.haskellMessage.decode(binaryDataReceived); - resolve(haskMsg); - } catch (e) { reject(e) } - }; - }) - } } export type HaskellAsyncCallback = (jsMsg: JavaScriptMessage, argScope: List) => Promise; export async function haskellApp ( - haskMsg: HaskellMessage, + hmsg: HaskellMessage, argScope: List, send: HaskellAsyncCallback ): Promise { - switch (haskMsg.tag) { + switch (hmsg.tag) { case HaskellMessageTag.EvalExpr: { - const result = p.evalExpr(send, globalContext, argScope, haskMsg.expr); + const result = p.evalExpr(send, globalContext, argScope, hmsg.expr); const jvalue = p.unknownToValue(result); - return send({ tag: JavaScriptMessageTag.Return, 0: jvalue }, argScope); + const jmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, value: jvalue, threadId: hmsg.threadId }; + return send(jmsg, argScope); } case HaskellMessageTag.HotReload: { window.location.reload(); @@ -73,7 +60,7 @@ export async function haskellApp ( return; } } - absurd(haskMsg); + absurd(hmsg); } const globalContext: List = [window as any, null] diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index 76b839a..8dddc6d 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -1,5 +1,4 @@ import * as b from './binary'; -import { Maybe, MaybeTag } from './binary'; import { absurd, IntMap } from './lib'; export type JSFunctionName = string; @@ -497,7 +496,7 @@ export enum HaskellMessageTag { } export const haskellMessage = b.discriminate({ - [HaskellMessageTag.EvalExpr]: b.record({ expr: expr }), + [HaskellMessageTag.EvalExpr]: b.record({ threadId: b.int32, expr: expr }), [HaskellMessageTag.HotReload]: b.record({ }), [HaskellMessageTag.Halt]: b.record({ }), }); @@ -511,7 +510,7 @@ export enum JavaScriptMessageTag { export const javascriptMessage = b.discriminate({ [JavaScriptMessageTag.Start]: b.record({ 0: jvalue }), - [JavaScriptMessageTag.Return]: b.record({ 0: jvalue }), + [JavaScriptMessageTag.Return]: b.record({ threadId: b.int32, value: jvalue }), [JavaScriptMessageTag.TriggerCallback]: b.record({ arg: jvalue, callbackId: b.int32 }), [JavaScriptMessageTag.BeforeUnload]: b.record({}), }); diff --git a/jsbits/wasm.ts b/jsbits/wasm.ts index bad25cd..5803230 100644 --- a/jsbits/wasm.ts +++ b/jsbits/wasm.ts @@ -42,29 +42,25 @@ export function storeBuffer(exports: HaskellExports, u8array: Uint8Array): Haske export function evalMessage(exports: HaskellExports, ptr: HaskellPointer): HaskellPointer { const inbuf = loadBuffer(exports, ptr); - const haskMsg = p.haskellMessage.decode(inbuf); + const hmsg = p.haskellMessage.decode(inbuf); const jsCallback = (jsmsg: JavaScriptMessage, _argScope: List) => { const outbuf = p.javascriptMessage.encode(jsmsg); const ptr = storeBuffer(exports, outbuf); exports.wasm_app(ptr); }; - switch (haskMsg.tag) { + switch (hmsg.tag) { case HaskellMessageTag.EvalExpr: { - const result = p.evalExpr(jsCallback, [globalThis, null], null, haskMsg.expr); - const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, 0: p.unknownToValue(result) }; + const result = p.evalExpr(jsCallback, [globalThis, null], null, hmsg.expr); + const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, value: p.unknownToValue(result), threadId: hmsg.threadId }; const outbuf = p.javascriptMessage.encode(jsmsg); return storeBuffer(exports, outbuf); } case HaskellMessageTag.HotReload: { window.location.reload(); - const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, 0: p.unknownToValue(null) }; - const outbuf = p.javascriptMessage.encode(jsmsg); - return storeBuffer(exports, outbuf); + return 0; } case HaskellMessageTag.Halt: { - const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, 0: p.unknownToValue(null) }; - const outbuf = p.javascriptMessage.encode(jsmsg); - return storeBuffer(exports, outbuf); + return 0; } } } diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 2cad804..b12acf3 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -100,12 +100,9 @@ enqueueExpr e = modify \s -> s {evaluation_queue = e : s.evaluation_queue} evalExpr :: Expr -> ClickM Value evalExpr e = do - send_message <- asks (.send_message) + eval_expr <- asks (.eval_expr) queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - result <- liftIO $ send_message $ EvalExpr $ RevSeq $ e : queue - case result of - Return v -> return v - _ -> return Value.Null + liftIO $ eval_expr $ RevSeq $ e : queue ------------------------- -- RESOURCE MANAGEMENT -- diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 2a07dab..4e63b9f 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -17,11 +17,11 @@ import Clickable.Types emptyState :: InternalState emptyState = InternalState [] [] Map.empty [] 0 -newInternalEnv :: (HaskellMessage -> IO JavaScriptMessage) -> IO InternalEnv -newInternalEnv send_message = do +newInternalEnv :: (Expr -> IO Value) -> IO InternalEnv +newInternalEnv eval_expr = do let scope = ResourceScope emptyState.next_id internal_state_ref <- newIORef emptyState {next_id = emptyState.next_id + 1} - return InternalEnv {internal_state_ref, scope, send_message} + return InternalEnv {internal_state_ref, scope, eval_expr} -- | Unsafe because there is no gurantee that @a@ matches @a@ in -- correspoding @DynVar a@ where SourceId comes from @@ -197,10 +197,10 @@ trampoline act = loop0 act where syncPoint :: ClickM () syncPoint = do - send_message <- asks (.send_message) + eval_expr <- asks (.eval_expr) queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) unless (List.null queue) do - liftIO $ send_message $ EvalExpr $ RevSeq queue + liftIO $ eval_expr $ RevSeq queue return () reactive :: (ResourceScope -> InternalState -> (InternalState, a)) -> ClickM a diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 0e7f945..1592fc4 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -25,6 +25,9 @@ import Network.Wai.Handler.WebSockets import Network.WebSockets import System.Environment import System.IO +import Data.Tuple +import Data.Word +import GHC.Conc.Sync import "this" Clickable.Types import "this" Clickable.Protocol @@ -195,7 +198,11 @@ websocketApp opt p = BrowserMessage (Start flags) -> void $ forkIO $ Internal.launchClickM conn.internal_env $ app.client_app conn flags - BrowserMessage (Return val) -> void $ tryPutMVar conn.return_mvar val + BrowserMessage (Return tid val) -> do + mmvar <- atomicModifyIORef' conn.threads_ref $ + swap . Map.alterF (,Nothing) (fromIntegral tid) + forM_ mmvar \mvar -> + void $ tryPutMVar mvar val BrowserMessage (TriggerCallbackMsg arg sourceId) -> void $ forkIO $ Internal.launchClickM conn.internal_env $ modify (Internal.unsafeTrigger sourceId arg) @@ -206,8 +213,8 @@ websocketApp opt p = newConn connection = mdo command_chan <- newChan - return_mvar <- newEmptyMVar - internal_env <- newInternalEnv connection return_mvar + threads_ref <- newIORef Map.empty + internal_env <- newInternalEnv connection threads_ref connInfo <- atomicModifyIORef' opt.conn_state_ref \m -> let connection_id = Map.lookupMax m & maybe 0 (succ . fst) @@ -216,15 +223,18 @@ websocketApp opt p = , connection , command_chan , connection_id - , return_mvar } + , threads_ref } in (Map.insert connection_id connInfo m, connInfo) return connInfo - newInternalEnv :: Connection -> MVar Value -> IO InternalEnv - newInternalEnv conn resultMvar = - Internal.newInternalEnv \haskMessage -> do - sendDataMessage conn . Binary $ Binary.encode haskMessage - Return <$> takeMVar resultMvar + newInternalEnv :: Connection -> IORef (Map Word64 (MVar Value)) -> IO InternalEnv + newInternalEnv conn awaiting = + Internal.newInternalEnv \expr -> do + tid <- fmap fromThreadId myThreadId + sendDataMessage conn . Binary . Binary.encode $ EvalExpr (fromIntegral tid) expr + mvar <- newEmptyMVar + modifyIORef' awaiting $ Map.insert tid mvar + takeMVar mvar in bracket acceptConn dropConn \connInfo -> withPingThread connInfo.connection 30 (pure ()) $ loop connInfo @@ -287,7 +297,7 @@ data DevInstance = DevInstance data ConnectionInfo = ConnectionInfo { connection :: Connection - , return_mvar :: MVar Value + , threads_ref :: IORef (Map Word64 (MVar Value)) , internal_env :: InternalEnv , command_chan :: Chan (ClickM ()) -- ^ Writing to the Chan sends a command to the browser to execute @@ -308,4 +318,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,HA:()=>y,PV:()=>w,Tf:()=>P,YE:()=>h,YO:()=>M,Yj:()=>m,b9:()=>D,g1:()=>O,tB:()=>A});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 4;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return x(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[new DataView(t.buffer).getInt32(r,!0),r+4];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=x(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s)return new DataView(t.buffer).setInt32(r,_,!0),r+4;if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function x(e){return Math.ceil(Math.log2(e)/8)}const h=new a,y=new s,T=new i,m=new c,D=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function A(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,a,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class d{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new d;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,0:g.bp(t)},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:{window.location.reload();const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}case g.I4.Halt:{const t={tag:g.dB.Return,0:g.bp(null)},r=g.bR.encode(t);return b(e,r)}}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let x={};var h=__webpack_require__(366);const y=[window,null];window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(x)});Object.assign(x,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(x,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(x,t);x.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=(t,r)=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t))}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const r=yield(n=t.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(n)})));var n;!function(t,r,n){e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,y,null,t.expr),r=g.bp(e);return n({tag:g.dB.Return,0:r},null)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,h.G)(t)}))}(g.sy.decode(r),0,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,HA:()=>x,PV:()=>w,Tf:()=>P,YE:()=>y,YO:()=>M,Yj:()=>D,b9:()=>m,g1:()=>O,tB:()=>A});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 4;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return h(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[new DataView(t.buffer).getInt32(r,!0),r+4];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=h(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s)return new DataView(t.buffer).setInt32(r,_,!0),r+4;if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function h(e){return Math.ceil(Math.log2(e)/8)}const y=new a,x=new s,T=new i,D=new c,m=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function A(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,a,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class d{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new d;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,value:g.bp(t),threadId:n.threadId},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:return window.location.reload(),0;case g.I4.Halt:return 0}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let h={};var y=__webpack_require__(366);const x=[window,null];window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(h)});Object.assign(h,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(h,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(h,t);h.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=t=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t))}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const r=yield(n=t.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(n)})));var n;!function(t,r,n){e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,x,null,t.expr),r=g.bp(e),_={tag:g.dB.Return,value:r,threadId:t.threadId};return n(_,null)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,y.G)(t)}))}(g.sy.decode(r),0,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" diff --git a/src/Clickable/Main/Wasm.hs b/src/Clickable/Main/Wasm.hs index dc744ab..a5b28fc 100644 --- a/src/Clickable/Main/Wasm.hs +++ b/src/Clickable/Main/Wasm.hs @@ -15,6 +15,8 @@ import System.IO.Unsafe import Clickable.FFI qualified as FFI import Clickable.Protocol +import Clickable.Protocol.Value (Value) +import Clickable.Protocol.Value qualified as Value import Clickable.Core import Clickable.Internal qualified as Internal import Clickable.Types @@ -23,23 +25,27 @@ runWasm :: (StartFlags -> ClickM ()) -> Ptr Word8 -> IO () runWasm app p = mdo jmsg <- loadMessage p case jmsg of - Start flags -> - launchClickM internalEnv $ app flags <* syncPoint - Return _value -> return () - TriggerCallbackMsg arg sourceId -> + Just (Start flags) -> + launchClickM internalEnv $ app flags + Just (TriggerCallbackMsg arg sourceId) -> launchClickM internalEnv $ modify $ Internal.unsafeTrigger sourceId arg - BeforeUnload -> + Just BeforeUnload -> launchClickM internalEnv $ freeScope True $ ResourceScope Internal.emptyState.next_id + _ -> + return () internalEnv :: InternalEnv internalEnv = unsafePerformIO $ Internal.newInternalEnv sendMessage -sendMessage :: HaskellMessage -> IO JavaScriptMessage -sendMessage hmsg = do - hptr <- storeByteString $ BSL.toStrict $ Binary.encode hmsg +sendMessage :: Expr -> IO Value +sendMessage expr = do + hptr <- storeByteString $ BSL.toStrict $ Binary.encode $ EvalExpr 0 expr jptr <- FFI.js_evalMessage hptr Alloc.free hptr - loadMessage jptr + jmsg <- loadMessage jptr + case jmsg of + Just (Return _ v) -> return v + _ -> return Value.Null where storeByteString :: ByteString -> IO (Ptr a) storeByteString bs = do @@ -50,8 +56,10 @@ sendMessage hmsg = do copyBytes (dest `plusPtr` 8) src len return (castPtr dest) -loadMessage :: Binary msg => Ptr a -> IO msg -loadMessage = fmap (Binary.decode . BSL.fromStrict) . loadByteString +loadMessage :: Binary msg => Ptr a -> IO (Maybe msg) +loadMessage p + | nullPtr /= p = fmap (Just . Binary.decode . BSL.fromStrict) . loadByteString $ p + | otherwise = return Nothing where loadByteString :: Ptr a -> IO ByteString loadByteString ptr = do diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index 87f1353..d03f7f5 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -11,7 +11,7 @@ import GHC.Generics import "this" Clickable.Protocol.Value qualified as Value data HaskellMessage - = EvalExpr Expr + = EvalExpr Value.Int32Le Expr -- ^ Evaluate expression, expect the result to be returned by -- 'Return' message | HotReload @@ -23,7 +23,7 @@ data HaskellMessage data JavaScriptMessage = Start StartFlags - | Return Value.Value + | Return Value.Int32Le Value.Value | TriggerCallbackMsg Value.Value SourceId | BeforeUnload -- ^ Fired from addEventListener("beforeunload") listener. Won't diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index 8f19507..b79e699 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -11,7 +11,7 @@ import GHC.Generics import GHC.Exts import Clickable.Protocol -import Clickable.Protocol.Value (Int32Le) +import Clickable.Protocol.Value (Int32Le, Value) data DynVar a where SourceVar :: SourceId -> IORef a -> DynVar a @@ -61,7 +61,7 @@ instance MonadState InternalState ClickM where data InternalEnv = InternalEnv { scope :: ResourceScope , internal_state_ref :: IORef InternalState - , send_message :: HaskellMessage -> IO JavaScriptMessage + , eval_expr :: Expr -> IO Value } deriving (Generic) data InternalState = InternalState From 3c99feeb52c1afdfb4ca9b78914208173bf188d8 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 7 Jun 2024 17:25:06 +0400 Subject: [PATCH 38/64] unsafeHtml --- src/Clickable/Core.hs | 13 +++++++++++++ src/Clickable/Internal.hs | 17 +++++++++++++++++ src/Clickable/Main/Dev.hs | 3 --- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index b12acf3..0fd5566 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -363,5 +363,18 @@ attachToBody = attachHtml (Id "document" `Dot` "body") blank :: Applicative m => m () blank = pure () +-- | Parse given text as HTML and attach the resulting tree to +-- 'html_current_element'. This way you can create not only HTML but +-- anything that @innerHTML@ property can create (e.g. SVG) +-- +-- > -- Create a div with an SVG image inside that shows a black +-- > -- circle +-- > div_ [] do +-- > unsafeHtml "\ +-- > \\ +-- > \" +unsafeHtml :: Text -> HtmlM () +unsafeHtml rawHtml = lift $ enqueueExpr (Internal.unsafeInsertHtml rawHtml) + instance (a ~ ()) => IsString (HtmlM a) where fromString = text . Text.pack diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 4e63b9f..03fc3e8 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -5,6 +5,7 @@ import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.IORef +import Data.Text (Text) import Data.List qualified as List import Data.Map qualified as Map import Unsafe.Coerce @@ -232,3 +233,19 @@ mapHoldVal f da = do modify $ unsafeTrigger srcId b s' = s {subscriptions = newSub : s.subscriptions, next_id = succ s.next_id} val = MapHoldVal da f srcId ref + +unsafeInsertHtml :: Text -> Expr +unsafeInsertHtml rawHtml = Eval + "(function(builder, rawHtml){\ + \var div = document.createElement('div');\ + \div.innerHTML = rawHtml;\ + \var iter = div.childNodes[0];\ + \for (; iter; iter = div.childNodes[0]) {\ + \ div.removeChild(iter);\ + \ if (builder instanceof Comment) {\ + \ builder.parentElement.insertBefore(iter, builder);\ + \ } else{\ + \ builder.appendChild(iter);\ + \ }\ + \}\ + \})" `Apply` [Arg 0 0, String rawHtml] diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 1592fc4..2f757bb 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -164,9 +164,6 @@ fallbackApp _ resp = \ \n\ \\n" --- WebSocket server needs to be redesigned. Specifically I don't like --- the use of MVar to transfer the result of evaluation from the --- browser to haskell thread websocketApp :: DevInstance -> ServerApp websocketApp opt p = let From 578959a134f8ee164a00a8eb978ee102c4932e7e Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 19 Jun 2024 14:30:43 +0400 Subject: [PATCH 39/64] portal --- src/Clickable/Core.hs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 0fd5566..a774494 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -1,3 +1,4 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} module Clickable.Core ( module Clickable.Core , Internal.trampoline @@ -21,7 +22,6 @@ import Clickable.Internal qualified as Internal import Clickable.Types import Clickable.Protocol import Clickable.Protocol.Value (Value, ToValue(..)) -import Clickable.Protocol.Value qualified as Value --------------------------------------- -- OPERATIONS OVER DYNAMIC VARIABLES -- @@ -376,5 +376,18 @@ blank = pure () unsafeHtml :: Text -> HtmlM () unsafeHtml rawHtml = lift $ enqueueExpr (Internal.unsafeInsertHtml rawHtml) +-- | Attach resulting DOM to the given node instead of where it +-- supposed to go given the cotext it used in. Might be useful for +-- implementing modal dialogs, tooltips etc. Similar to what called +-- portals in React ecosystem +portal :: Expr -> HtmlM a -> HtmlM a +portal newRootEl html = + lift $ htmlBuilder1 newRootEl do + boundary <- insertBoundary + result <- htmlBuilder1 (Var boundary) $ + evalStateT html.unHtmlT Nothing + installFinalizer $ destroyBoundary boundary + return result + instance (a ~ ()) => IsString (HtmlM a) where fromString = text . Text.pack From 78031440b3867a4ca738d45b424450ac1340e501 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sun, 7 Jul 2024 13:38:52 +0400 Subject: [PATCH 40/64] Remove broken examples --- htmlt.cabal | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/htmlt.cabal b/htmlt.cabal index e36d56a..e810592 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -119,27 +119,3 @@ library wai-websockets, warp, websockets, - -executable htmlt-todomvc - import: htmlt-common - hs-source-dirs: ./examples/todomvc - if arch(wasm32) - ghc-options: - -no-hs-main -optl-mexec-model=reactor - -optl-Wl,--export=hs_init,--export=wasm_app,--export=malloc - main-is: wasm.hs - else - ghc-options: -threaded - main-is: dev.hs - other-modules: - App - TodoItem - TodoList - Utils - build-depends: - base, - htmlt, - text, - mtl, - if !flag(examples) - buildable: False From 22474e75bcd3fbd550d869a0bf2aa89e4cba6c04 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 16 Jul 2024 22:32:13 +0400 Subject: [PATCH 41/64] forDyn --- default.nix | 38 +++++++++++++++++--------------------- src/Clickable/Core.hs | 6 ++++++ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/default.nix b/default.nix index 1bfdae4..7b7d4c5 100644 --- a/default.nix +++ b/default.nix @@ -1,5 +1,5 @@ { pkgs ? import (builtins.fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/f4429fde23e1fb20ee27f264e74c28c619d2cebb.tar.gz"; + url = "https://github.com/NixOS/nixpkgs/archive/refs/tags/24.05.tar.gz"; }) {} }: @@ -11,33 +11,29 @@ let mkDerivation = args: super.mkDerivation ({ doCheck = false; doBenchmark = false; - doHoogle = true; - doHaddock = true; + doHoogle = false; + doHaddock = false; + jailbreak = true; enableLibraryProfiling = false; enableExecutableProfiling = false; } // args); htmlt = self.callCabal2nix "htmlt" ./. {}; + th-compat = self.callCabal2nix "th-compat" (builtins.fetchGit { + url = "https://github.com/haskell-compat/th-compat.git"; + rev = "eec1edb9e09eba14e7ba17be29a9674431c63c05"; + }) {}; - th-compat = self.callCabal2nix "th-compat" ../fullstack-app/packages/th-compat {}; - aeson = doJailbreak (self.callCabal2nix "aeson" ../fullstack-app/packages/aeson {}); - bifunctors = doJailbreak super.bifunctors; - free = doJailbreak super.free; - generic-deriving = doJailbreak super.generic-deriving; - invariant = doJailbreak super.invariant; - lens = doJailbreak super.lens; - semigroupoids = doJailbreak super.semigroupoids; - tagged = self.callCabal2nix "tagged" ../fullstack-app/packages/tagged {}; - text-short = self.callCabal2nix "text-short" ../fullstack-app/packages/text-short {}; - th-abstraction = self.callCabal2nix "th-abstraction" ../fullstack-app/packages/th-abstraction {}; - th-expand-syns = doJailbreak super.th-expand-syns; - th-lift = doJailbreak super.th-lift; - unordered-containers = self.callCabal2nix "unordered-containers" ../fullstack-app/packages/unordered-containers {}; - vector = self.callCabal2nix "vector" ../fullstack-app/packages/vector/vector {}; - vector-stream = self.callCabal2nix "vector-stream" ../fullstack-app/packages/vector/vector-stream {}; - websockets = doJailbreak super.websockets; - wuss = doJailbreak super.wuss; + th-abstraction = self.callCabal2nix "th-abstraction" (builtins.fetchGit { + url = "https://github.com/glguy/th-abstraction.git"; + rev = "1fb59d1651ac5462f44100c62e5806665d39b6c6"; + }) {}; + + aeson = doJailbreak (self.callCabal2nix "aeson" (builtins.fetchGit { + url = "https://github.com/haskell/aeson.git"; + rev = "0834ba7b081297d44c706914c92c31d264aef816"; + }) {}); }; }; diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index a774494..a04626f 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -67,6 +67,12 @@ writeVar var s = modifyVar_ var $ const s subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () subscribe = Internal.subscribe +forDyn :: DynVal a -> (a -> ClickM ()) -> ClickM () +forDyn dval action = readVal dval >>= action >> subscribe dval action + +forVar :: DynVar a -> (a -> ClickM ()) -> ClickM () +forVar = forDyn . fromVar + modifyVarQuiet :: DynVar s -> (s -> (s, a)) -> ClickM a modifyVarQuiet var@(SourceVar varId ref) f = do (newVal, a) <- liftIO $ atomicModifyIORef' ref g From f3bdaad15eba8b59f3ee4e9687c7c7fc660ca7a2 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 30 Jul 2024 22:44:52 +0400 Subject: [PATCH 42/64] Split examples into separate package --- LICENSE | 28 +++++++++++ cabal.project | 4 ++ ghc-wasm-meta | 2 +- htmlt.cabal | 83 +++++++-------------------------- jsbits/index.js | 12 +++-- jsbits/protocol.ts | 12 +++++ src/Clickable/Main/Dev.hs | 4 +- src/Clickable/Protocol/Value.hs | 10 ++++ 8 files changed, 83 insertions(+), 72 deletions(-) create mode 100644 LICENSE create mode 100644 cabal.project diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3e80ac2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +Copyright 2024 Vladislav Lagunov + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +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. + +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. + +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. \ No newline at end of file diff --git a/cabal.project b/cabal.project new file mode 100644 index 0000000..4b3729b --- /dev/null +++ b/cabal.project @@ -0,0 +1,4 @@ +packages: + . + examples + benchmarks diff --git a/ghc-wasm-meta b/ghc-wasm-meta index 426e46a..7b3caea 160000 --- a/ghc-wasm-meta +++ b/ghc-wasm-meta @@ -1 +1 @@ -Subproject commit 426e46a5a8ffda63a5dde02e0bf9eb60f9cca089 +Subproject commit 7b3caea9828966b9f9b70b715f96768adb51c052 diff --git a/htmlt.cabal b/htmlt.cabal index e810592..f7ed86f 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -4,6 +4,7 @@ name: htmlt version: 0.1.0.0 homepage: https://github.com/lagunoff/htmlt license: BSD-3-Clause +license-file: LICENSE author: Vladislav Lagunov maintainer: vlad.lagunoff@gmail.com copyright: 2019 Vladislav Lagunov @@ -12,76 +13,12 @@ build-type: Simple extra-source-files: README.md -Flag production - default: True - description: Add optimisations - -Flag examples - default: False - description: Build examples - -Flag benchmarks - default: False - description: Build benchmarks - -common htmlt-common - ghc-options: - -Wall -Wno-missing-signatures -Wno-name-shadowing -Wno-unused-matches - -Wno-unused-do-bind - if flag(production) - ghc-options: -O3 - default-extensions: - AllowAmbiguousTypes - BangPatterns - BlockArguments - ConstraintKinds - DataKinds - DefaultSignatures - DeriveAnyClass - DeriveFunctor - DeriveGeneric - DerivingStrategies - DerivingVia - DoAndIfThenElse - DuplicateRecordFields - EmptyDataDecls - FlexibleContexts - FlexibleInstances - ForeignFunctionInterface - FunctionalDependencies - GADTs - GeneralizedNewtypeDeriving - ImplicitParams - ImportQualifiedPost - LambdaCase - NamedFieldPuns - OverloadedLabels - OverloadedRecordDot - OverloadedStrings - PackageImports - PartialTypeSignatures - PatternGuards - PolyKinds - QuasiQuotes - RankNTypes - RecordWildCards - RecursiveDo - ScopedTypeVariables - StandaloneDeriving - StrictData - TupleSections - TypeApplications - TypeFamilies - TypeOperators - UndecidableInstances - ViewPatterns - library - import: htmlt-common ghc-options: + -O3 -funbox-strict-fields -fstrictness -Wall -Wno-missing-signatures -Wno-name-shadowing -Wno-unused-matches -Wno-unused-do-bind - hs-source-dirs: src ./examples/charts ./examples/todomvc + hs-source-dirs: src exposed-modules: Clickable Clickable.Core @@ -119,3 +56,17 @@ library wai-websockets, warp, websockets, + default-extensions: + AllowAmbiguousTypes + BlockArguments + DefaultSignatures + DeriveAnyClass + DuplicateRecordFields + FunctionalDependencies + GHC2024 + OverloadedRecordDot + OverloadedStrings + PackageImports + RecursiveDo + TypeFamilies + UndecidableInstances diff --git a/jsbits/index.js b/jsbits/index.js index 208a2e3..2399096 100644 --- a/jsbits/index.js +++ b/jsbits/index.js @@ -1,5 +1,11 @@ -import * as wasm from './wasm'; import * as dev from './dev'; +import * as protocol from './protocol'; +import * as wasm from './wasm'; -window.startWasm = wasm.startWasm; -window.startDev = dev.startDev; +// Inject ClickablePublic object into the global scope +window.clickable = { + startWasm: wasm.startWasm, + startDev: dev.startDev, + evalExpr: protocol.evalExpr, + evalUint8Array: protocol.evalUint8Array +}; diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index 8dddc6d..db48af7 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -23,6 +23,13 @@ export function cdr(pair: Cons): List { return pair[1]; } +export type ClickablePublic = { + startWasm(wasmUri: string, startFlags?: unknown): void; + startDev(devSocketUri: string, startFlags?: unknown): void; + evalExpr(hscb: HaskellCallback, idenScope: List, argScope: List, exp: Expr): unknown; + evalUint8Array(hscb: HaskellCallback, idenScope: List, argScope: List, exp: Uint8Array): unknown; +}; + export type HaskellCallback = (jsMsg: JavaScriptMessage, argScope: List) => void; export function evalExpr(hscb: HaskellCallback, idenScope: List, argScope: List, exp: Expr): unknown { @@ -267,6 +274,11 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc absurd(exp); } +export function evalUint8Array(hscb: HaskellCallback, idenScope: List, argScope: List, exp: Uint8Array): unknown { + const decoded: Expr = expr.decode(exp); + return evalExpr(hscb, idenScope, argScope, decoded); +} + export function unknownToValue(inp: unknown): Value { if (typeof(inp) === 'boolean') { return { tag: ValueTag.Boolean, 0: inp ? 1 : 0 }; diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 2f757bb..454c28e 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -149,7 +149,7 @@ htmlTemplate devUrl = \ \n\ \ \n\ \ \n\ \\n" @@ -315,4 +315,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,HA:()=>x,PV:()=>w,Tf:()=>P,YE:()=>y,YO:()=>M,Yj:()=>D,b9:()=>m,g1:()=>O,tB:()=>A});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 4;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return h(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[new DataView(t.buffer).getInt32(r,!0),r+4];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=h(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s)return new DataView(t.buffer).setInt32(r,_,!0),r+4;if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function h(e){return Math.ceil(Math.log2(e)/8)}const y=new a,x=new s,T=new i,D=new c,m=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function A(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}const t=58;class r{static read_bytes(e,t){const n=new r;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const _=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class i extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let o,c=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof i)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,_,a={}){this.args=[],this.env=[],this.fds=[],s.enable(a.debug),this.args=e,this.env=t,this.fds=_;const o=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);r.setUint32(e,o.args.length,!0);let n=0;for(const e of o.args)n+=e.length+1;return r.setUint32(t,n,!0),s.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(o.inst.exports.memory.buffer),n=new Uint8Array(o.inst.exports.memory.buffer),_=t;for(let _=0;_null!=o.fds[e]?o.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=o.fds[e]){const t=o.fds[e].fd_close();return o.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=o.fds[e]?o.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=o.fds[e]){const{ret:r,fdstat:n}=o.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=o.fds[e]?o.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=o.fds[e]){const{ret:r,filestat:n}=o.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(o.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=o.fds[e]?o.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,n,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=r.read_bytes_array(s,t,n),{ret:l,nread:p}=o.fds[e].fd_pread(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,prestat:_}=o.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=o.fds[e]){const{ret:r,prestat_dir_name:n}=o.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(o.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,_,a){const s=new DataView(o.inst.exports.memory.buffer),i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=n.read_bytes_array(s,t,r),{ret:l,nwritten:p}=o.fds[e].fd_pwrite(i,c,_);return s.setUint32(a,p,!0),l}return 8},fd_read(e,t,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=r.read_bytes_array(a,t,n),{ret:c,nread:l}=o.fds[e].fd_read(s,i);return a.setUint32(_,l,!0),c}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){let i=0;for(;;){const{ret:c,dirent:l}=o.fds[e].fd_readdir_single(n);if(0!=c)return a.setUint32(_,i,!0),c;if(null==l)break;if(r-inull!=o.fds[e]?o.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const{ret:n,offset:_}=o.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=n.read_bytes_array(a,t,r),{ret:c,nwritten:l}=o.fds[e].fd_write(s,i);return a.setUint32(_,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(o.inst.exports.memory.buffer),s=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const i=new TextDecoder(\"utf-8\").decode(s.slice(r,r+n)),{ret:c,filestat:l}=o.fds[e].path_filestat_get(t,i);return null!=l&&l.write_bytes(a,_),c}return 8},path_filestat_set_times(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n));return o.fds[e].path_filestat_set_times(t,c,_,a,s)}return 8},path_link(e,t,r,n,_,a,s){const i=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]&&null!=o.fds[_]){const c=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(i.slice(a,a+s));return o.fds[_].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,_,a,i,c,l){const p=new DataView(o.inst.exports.memory.buffer),u=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));s.log(f);const{ret:d,fd_obj:E}=o.fds[e].path_open(t,f,_,a,i,c);if(0!=d)return d;o.fds.push(E);const g=o.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(o.inst.exports.memory.buffer),c=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const l=new TextDecoder(\"utf-8\").decode(c.slice(t,t+r));s.log(l);const{ret:p,data:u}=o.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>_)return i.setUint32(a,0,!0),8;c.set(e,n),i.setUint32(a,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[r]){const s=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),i=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return o.fds[r].path_symlink(s,i)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(o.inst.exports.memory.buffer);if(null!=o.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return o.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new i(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(o.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class u{open(e){const t=new p(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new a(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class d{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)o=globalThis.setImmediate;else{const e=new d;o=(t,...r)=>e.setImmediate(t,...r)}const E=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>o(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const r=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),n=g.sy.decode(r),_=(t,r)=>{const n=g.bR.encode(t),_=b(e,n);e.wasm_app(_)};switch(n.tag){case g.I4.EvalExpr:{const t=g.wL(_,[globalThis,null],null,n.expr),r={tag:g.dB.Return,value:g.bp(t),threadId:n.threadId},a=g.bR.encode(r);return b(e,a)}case g.I4.HotReload:return window.location.reload(),0;case g.I4.Halt:return 0}}(e,t)}};var g=__webpack_require__(933);function b(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let h={};var y=__webpack_require__(366);const x=[window,null];window.startWasm=function(t){return e(this,arguments,void 0,(function*(e,t=null){const r=new c([],[],[new p(new u([])),new p(new u([])),new p(new u([]))]),n=yield WebAssembly.compileStreaming(fetch(e)),_=yield WebAssembly.instantiate(n,{wasi_snapshot_preview1:r.wasiImport,ghc_wasm_jsffi:E(h)});Object.assign(h,_.exports),r.initialize(_),yield _.exports.hs_init();const a=g.bp(t),s={tag:g.dB.Start,0:a},i=g.bR.encode(s),o=b(h,i);yield _.exports.wasm_app(o),window.addEventListener(\"beforeunload\",(()=>{const e={tag:g.dB.BeforeUnload},t=g.bR.encode(e),r=b(h,t);h.wasm_app(r)}))}))},window.startDev=function(t,r=null){const n=new WebSocket(t),_=t=>e(this,void 0,void 0,(function*(){n.send(g.bR.encode(t))}));n.onopen=e=>{const t=g.bp(r),_=g.bR.encode({tag:g.dB.Start,0:t});n.send(_)},n.onmessage=t=>e(this,void 0,void 0,(function*(){const r=yield(n=t.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(n)})));var n;!function(t,r,n){e(this,void 0,void 0,(function*(){switch(t.tag){case g.I4.EvalExpr:{const e=g.wL(n,x,null,t.expr),r=g.bp(e),_={tag:g.dB.Return,value:r,threadId:t.threadId};return n(_,null)}case g.I4.HotReload:return void window.location.reload();case g.I4.Halt:return}(0,y.G)(t)}))}(g.sy.decode(r),0,_)})),n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,HA:()=>x,PV:()=>w,Tf:()=>P,YE:()=>y,YO:()=>M,Yj:()=>D,b9:()=>m,g1:()=>O,tB:()=>A});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 4;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return h(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[new DataView(t.buffer).getInt32(r,!0),r+4];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=h(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s)return new DataView(t.buffer).setInt32(r,_,!0),r+4;if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function h(e){return Math.ceil(Math.log2(e)/8)}const y=new a,x=new s,T=new i,D=new c,m=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function A(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function evalUint8Array(e,t,r,n){return evalExpr(e,t,r,expr.decode(n))}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=[window,null],_=58;class a{static read_bytes(e,t){const r=new a;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let _=0;_{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let p,u=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],c.enable(n.debug),this.args=e,this.env=t,this.fds=r;const _=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.args.length,!0);let n=0;for(const e of _.args)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.args.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.args[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},environ_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.env.length,!0);let n=0;for(const e of _.env)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},environ_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.env.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.env[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},clock_res_get(e,t){let r;switch(e){case 1:r=5000n;break;case 0:r=1000000n;break;default:return 52}return new DataView(_.inst.exports.memory.buffer).setBigUint64(t,r,!0),0},clock_time_get(e,t,r){const n=new DataView(_.inst.exports.memory.buffer);if(0===e)n.setBigUint64(r,1000000n*BigInt((new Date).getTime()),!0);else if(1==e){let e;try{e=BigInt(Math.round(1e6*performance.now()))}catch(t){e=0n}n.setBigUint64(r,e,!0)}else n.setBigUint64(r,0n,!0);return 0},fd_advise:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=_.fds[e]){const t=_.fds[e].fd_close();return _.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=_.fds[e]?_.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=_.fds[e]){const{ret:r,fdstat:n}=_.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=_.fds[e]){const{ret:r,filestat:n}=_.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=a.read_bytes_array(i,t,r),{ret:l,nread:p}=_.fds[e].fd_pread(o,c,n);return i.setUint32(s,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,prestat:a}=_.fds[e].fd_prestat_get();return null!=a&&a.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=_.fds[e]){const{ret:r,prestat_dir_name:n}=_.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(_.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,a){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=s.read_bytes_array(i,t,r),{ret:l,nwritten:p}=_.fds[e].fd_pwrite(o,c,n);return i.setUint32(a,p,!0),l}return 8},fd_read(e,t,r,n){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=a.read_bytes_array(s,t,r),{ret:c,nread:l}=_.fds[e].fd_read(i,o);return s.setUint32(n,l,!0),c}return 8},fd_readdir(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){let o=0;for(;;){const{ret:c,dirent:l}=_.fds[e].fd_readdir_single(n);if(0!=c)return s.setUint32(a,o,!0),c;if(null==l)break;if(r-onull!=_.fds[e]?_.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,offset:a}=_.fds[e].fd_tell();return r.setBigUint64(t,a,!0),n}return 8},fd_write(e,t,r,n){const a=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=s.read_bytes_array(a,t,r),{ret:c,nwritten:l}=_.fds[e].fd_write(i,o);return a.setUint32(n,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_create_directory(a)}},path_filestat_get(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:c,filestat:l}=_.fds[e].path_filestat_get(t,o);return null!=l&&l.write_bytes(s,a),c}return 8},path_filestat_set_times(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return _.fds[e].path_filestat_set_times(t,c,a,s,i)}return 8},path_link(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]&&null!=_.fds[a]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(o.slice(s,s+i));return _.fds[a].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,a,s,i,o,l){const p=new DataView(_.inst.exports.memory.buffer),u=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));c.log(f);const{ret:d,fd_obj:E}=_.fds[e].path_open(t,f,a,s,i,o);if(0!=d)return d;_.fds.push(E);const g=_.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,a,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(t,t+r));c.log(l);const{ret:p,data:u}=_.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>a)return i.setUint32(s,0,!0),8;o.set(e,n),i.setUint32(s,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_remove_directory(a)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,a){const s=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[r]){const i=new TextDecoder(\"utf-8\").decode(s.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(s.slice(n,n+a));return _.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_unlink_file(a)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(_.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class E{open(e){const t=new d(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new o(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class g{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class b{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)p=globalThis.setImmediate;else{const e=new b;p=(t,...r)=>e.setImmediate(t,...r)}const h=e=>{const t=new g;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>p(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=(t,n)=>{const _=r.bR.encode(t),a=y(e,_);e.wasm_app(a)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(a,[globalThis,null],null,_.expr),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return y(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function y(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let x={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new u([],[],[new d(new E([])),new d(new E([])),new d(new E([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:h(x)});Object.assign(x,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),c=y(x,o);yield a.exports.wasm_app(c),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=y(x,t);x.wasm_app(n)}))}))},startDev:function(_,a=null){const s=new WebSocket(_),i=t=>e(this,void 0,void 0,(function*(){s.send(r.bR.encode(t))}));s.onopen=e=>{const t=r.bp(a),n=r.bR.encode({tag:r.dB.Start,0:t});s.send(n)},s.onmessage=_=>e(this,void 0,void 0,(function*(){const a=yield(s=_.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(s)})));var s;!function(_,a,s){e(this,void 0,void 0,(function*(){switch(_.tag){case r.I4.EvalExpr:{const e=r.wL(s,n,null,_.expr),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:_.threadId};return s(a,null)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(_)}))}(r.sy.decode(a),0,i)})),s.onerror=e=>{console.error(\"WebSocket error:\",e)},s.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" diff --git a/src/Clickable/Protocol/Value.hs b/src/Clickable/Protocol/Value.hs index ff05022..36c04b9 100644 --- a/src/Clickable/Protocol/Value.hs +++ b/src/Clickable/Protocol/Value.hs @@ -56,6 +56,10 @@ instance ToValue Char where instance ToValue Text where toValue = String +instance ToValue ByteString where toValue = Uint8Array + +instance ToValue () where toValue _ = Null + instance ToValue a => ToValue [a] where toValue = Array . fmap toValue instance ToValue a => ToValue (Maybe a) where toValue = maybe Null toValue @@ -98,6 +102,12 @@ instance FromValue Char where instance FromValue Text where fromValue = \case String a -> Just a; _ -> Nothing +instance FromValue ByteString where + fromValue = \case Uint8Array a -> Just a; _ -> Nothing + +instance FromValue () where + fromValue = \case Null -> Just (); _ -> Nothing + instance FromValue a => FromValue [a] where fromValue = \case Array xs -> Just (mapMaybe fromValue xs) From d421e6b96eb5c4e4244eef220cc40e2612d9d810 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sat, 3 Aug 2024 02:11:11 +0400 Subject: [PATCH 43/64] A few changes to DevServer --- default.nix | 2 ++ src/Clickable/Main/Dev.hs | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/default.nix b/default.nix index 7b7d4c5..904fd94 100644 --- a/default.nix +++ b/default.nix @@ -41,6 +41,8 @@ let pkgs = haskellPackages; shell = pkgs.mkShell { inputsFrom = [haskellPackages.htmlt.env]; + # fails to build, you have to have cabal installed on your system + # buildDepends = [haskellPackages.cabal-install]; }; }; in diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 454c28e..31e7a18 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -6,9 +6,12 @@ import Control.Exception import Control.Monad import Control.Monad.State import Data.Binary qualified as Binary +import Data.ByteString.Builder (Builder) +import Data.ByteString.Builder qualified as Builder import Data.ByteString as BS import Data.ByteString.Lazy qualified as BSL import Data.Function +import Data.Maybe import Data.IORef import Data.List qualified as List import Data.Map (Map) @@ -45,7 +48,7 @@ data DevConfig a = DevConfig , reload_app :: a -> IO ApplicationSpec -- ^ Given resource of type 'a', initialize instances of client and -- server applications. Runs each time ghci session reloads - , html_template :: BSL.ByteString -> BSL.ByteString + , html_template :: ByteString -> Builder -- ^ Template for index.html, receives the current URL origin -- (protocol + host) , docroots :: [FilePath] @@ -109,8 +112,8 @@ runSettings settings cfg = do staticApp (defaultFileServerSettings docroot) {ss404Handler = Just (withStaticApp docroots next)} forkIfRepl action = do - inRepl <- (== "") <$> getProgName - if inRepl then void (forkIO action) else action + isRepl <- (== "") <$> getProgName + if isRepl then void (forkIO action) else action runDev :: (StartFlags -> ClickM ()) -> IO () runDev clientApp = runSettings @@ -131,25 +134,25 @@ middleware opts next req resp = indexHtml req resp = do let devSocket = mkWebsocketUrl req RunningApp{devserver_config} <- readIORef opts.app_state_ref - resp $ responseLBS status200 + resp $ responseBuilder status200 [(hContentType, "text/html; charset=utf-8")] $ devserver_config.html_template devSocket -mkWebsocketUrl :: WAI.Request -> BSL.ByteString +mkWebsocketUrl :: WAI.Request -> ByteString mkWebsocketUrl req = WAI.requestHeaders req & List.lookup "Host" - & maybe "localhost" BSL.fromStrict + & fromMaybe "localhost" & ((if WAI.isSecure req then "wss://" else "ws://") <>) & (<> "/dev.sock") -htmlTemplate :: BSL.ByteString -> BSL.ByteString +htmlTemplate :: ByteString -> Builder htmlTemplate devUrl = "\n\ \ \n\ \ \n\ \ \n\ \\n" From e34ee2756880cae9dad7a7050bc05ed6fefb09bd Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 6 Aug 2024 06:04:36 +0400 Subject: [PATCH 44/64] Better typed EventId --- src/Clickable/Core.hs | 6 ++--- src/Clickable/DOM.hs | 10 +++++--- src/Clickable/Internal.hs | 53 ++++++++++++++++++++------------------- src/Clickable/Main/Dev.hs | 16 ++++++------ src/Clickable/Protocol.hs | 8 +++--- src/Clickable/Types.hs | 22 +++++++++------- 6 files changed, 61 insertions(+), 54 deletions(-) diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index a04626f..b510964 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -30,7 +30,7 @@ import Clickable.Protocol.Value (Value, ToValue(..)) newVar :: a -> ClickM (DynVar a) newVar a = do ref <- liftIO $ newIORef a - state \s -> (SourceVar (SourceId s.next_id) ref, s {next_id = s.next_id + 1}) + state \s -> (SourceVar (EventId s.next_id) ref, s {next_id = s.next_id + 1}) overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a overrideVar = OverrideVar @@ -50,7 +50,7 @@ readVar = Internal.readVar modifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a modifyVar var@(SourceVar varId ref) f = do (newVal, a) <- liftIO $ atomicModifyIORef' ref g - modify $ Internal.unsafeTrigger varId newVal + modify $ Internal.triggerEvent varId newVal return a where g old = let (new, a) = f old in (new, (new, a)) @@ -131,7 +131,7 @@ installFinalizer k = reactive_ $ Internal.installFinalizer k newVarId :: ClickM VarId newVarId = reactive Internal.newVarId -newCallback :: (Value -> ClickM ()) -> ClickM SourceId +newCallback :: (Value -> ClickM ()) -> ClickM (EventId Value) newCallback k = reactive $ Internal.newCallback k ------------------ diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index 1e9e668..0d6b74d 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -7,6 +7,7 @@ import Data.Kind import Data.Int import GHC.Generics import Unsafe.Coerce +import Data.Coerce import Clickable.Types import Clickable.Protocol @@ -29,7 +30,7 @@ addEventListener :: ConnectResourceArgs callback -> callback -> HtmlM () addEventListener args k = lift $ connectResource args k data ConnectResourceArgs callback = ConnectResourceArgs - { aquire_resource :: ResourceScope -> SourceId -> Expr + { aquire_resource :: ResourceScope -> AnyEventId -> Expr -- ^ When evaluated, as a side-effect resulting `Expr` must -- initialize some resource (could be DOM event, WebSocket -- connection etc) also must return a function that frees that @@ -42,9 +43,10 @@ connectResource args k = reactive_ \scope s -> let k' :: Value -> ClickM () k' = local (\e -> e {scope}) . args.mk_callback k - sourceId = SourceId s.next_id - newSub = SubscriptionSimple scope sourceId (k' . unsafeCoerce) - connectExpr = ConnectResource scope $ args.aquire_resource scope sourceId + sourceId = EventId s.next_id + anyEventId = AnyEventId s.next_id + newSub = SubscriptionSimple scope (coerce sourceId) (k' . unsafeCoerce) + connectExpr = ConnectResource scope $ args.aquire_resource scope anyEventId in s { evaluation_queue = connectExpr : s.evaluation_queue , subscriptions = newSub : s.subscriptions diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 03fc3e8..eae04c2 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -24,25 +24,26 @@ newInternalEnv eval_expr = do internal_state_ref <- newIORef emptyState {next_id = emptyState.next_id + 1} return InternalEnv {internal_state_ref, scope, eval_expr} --- | Unsafe because there is no gurantee that @a@ matches @a@ in --- correspoding @DynVar a@ where SourceId comes from -unsafeTrigger :: SourceId -> a -> InternalState -> InternalState -unsafeTrigger sourceId a = - defer sourceId $ gets (.subscriptions) >>= notify +triggerEvent :: EventId a -> a -> InternalState -> InternalState +triggerEvent eventId a = + defer eventId $ gets (.subscriptions) >>= notify where + anyEventId :: EventId Any = coerce eventId + notify :: [Subscription Any] -> ClickM () notify [] = return () notify (SubscriptionSimple {ss_event_id, ss_callback} : xs) - | ss_event_id == sourceId = ss_callback (unsafeCoerce a) >> notify xs + | ss_event_id == anyEventId = ss_callback (unsafeCoerce a) >> notify xs | otherwise = notify xs notify (SubscriptionAccum {sa_event_id, sa_callback, sa_accum_ref} : xs) - | sa_event_id == sourceId = notifyAcc sa_callback sa_accum_ref >> notify xs + | sa_event_id == anyEventId = notifyAcc sa_callback sa_accum_ref >> notify xs | otherwise = notify xs notifyAcc :: forall b. (Any -> b -> ClickM b) -> IORef b -> ClickM () notifyAcc k ref = do acc <- liftIO $ readIORef ref acc' <- k (unsafeCoerce a) acc liftIO $ writeIORef ref acc' - defer k act s = s {transaction_queue = Map.insert k act s.transaction_queue} + defer :: EventId a -> ClickM () -> InternalState -> InternalState + defer k act s = s {transaction_queue = Map.insert (coerce k) act s.transaction_queue} newScope :: ResourceScope -> InternalState -> (InternalState, ResourceScope) newScope p s = @@ -78,31 +79,31 @@ installFinalizer k scope s = s {finalizers = CustomFinalizer scope k : s.finaliz subscribe :: forall a. DynVal a -> (a -> ClickM ()) -> ClickM () subscribe (ConstVal _) _ = return () subscribe (FromVar (SourceVar srcid _)) k = reactive_ g where - g scope s = s {subscriptions = SubscriptionSimple scope srcid (k . unsafeCoerce) : s.subscriptions } + g scope s = s {subscriptions = SubscriptionSimple scope (coerce srcid) (k . unsafeCoerce) : s.subscriptions } subscribe (FromVar (OverrideVar _ var)) k = subscribe (FromVar var) k subscribe (FromVar (LensMap l var)) k = subscribe (FromVar var) (k . getConst . l Const) subscribe (MapVal v f) k = subscribe v (k . f) subscribe (MapHoldVal _ _ srcid ref) k = reactive_ g where - g scope s = s {subscriptions = SubscriptionSimple scope srcid (k . unsafeCoerce) : s.subscriptions } + g scope s = s {subscriptions = SubscriptionSimple scope (coerce srcid) (k . unsafeCoerce) : s.subscriptions } subscribe (SplatVal fv av) k = do src <- reactive h subscribe fv $ f src subscribe av $ g src where - h scope s = (s', SourceId s.next_id) where + h scope s = (s', EventId s.next_id) where s' = s { subscriptions = newsub : s.subscriptions , next_id = s.next_id + 1 } - newsub = SubscriptionSimple scope (SourceId s.next_id) (k . unsafeCoerce) + newsub = SubscriptionSimple scope (EventId s.next_id) (k . unsafeCoerce) f src fv' = do av' <- readVal av - modify $ unsafeTrigger src $ fv' av' + modify $ triggerEvent src $ fv' av' g src av' = do fv' <- readVal fv - modify $ unsafeTrigger src $ fv' av' + modify $ triggerEvent src $ fv' av' subscribe (OverrideSub f d) k = f subscribe' k' where k' a _ = k a subscribe' k = subscribe d \a -> k a () @@ -111,7 +112,7 @@ subscribeAccum :: DynVal a -> (a -> b -> ClickM b) -> b -> ClickM () subscribeAccum (ConstVal _) _ _ = return () subscribeAccum (FromVar (SourceVar srcid _)) k b = do ref <- liftIO $ newIORef b - let newSub scope = SubscriptionAccum scope srcid (k . unsafeCoerce) ref + let newSub scope = SubscriptionAccum scope (coerce srcid) (k . unsafeCoerce) ref let g scope s = s {subscriptions = newSub scope : s.subscriptions} reactive_ g subscribeAccum (FromVar (OverrideVar _ var)) k b = @@ -121,24 +122,24 @@ subscribeAccum (FromVar (LensMap l var)) k b = subscribeAccum (MapVal v f) k b = subscribeAccum v (k . f) b subscribeAccum (MapHoldVal _ _ srcid ref) k b = do ref <- liftIO $ newIORef b - let newSub scope = SubscriptionAccum scope srcid (k . unsafeCoerce) ref + let newSub scope = SubscriptionAccum scope (coerce srcid) (k . unsafeCoerce) ref let g scope s = s {subscriptions = newSub scope : s.subscriptions} reactive_ g subscribeAccum (SplatVal fv av) k b = do ref <- liftIO $ newIORef b let - h scope s = (s', SourceId s.next_id) where + h scope s = (s', EventId s.next_id) where s' = s { subscriptions = newsub : s.subscriptions , next_id = s.next_id + 1 } - newsub = SubscriptionAccum scope (SourceId s.next_id) (k . unsafeCoerce) ref + newsub = SubscriptionAccum scope (EventId s.next_id) (k . unsafeCoerce) ref f src fv' = do av' <- readVal av - modify $ unsafeTrigger src $ fv' av' + modify $ triggerEvent src $ fv' av' g src av' = do fv' <- readVal fv - modify $ unsafeTrigger src $ fv' av' + modify $ triggerEvent src $ fv' av' src <- reactive h subscribe fv $ f src subscribe av $ g src @@ -160,13 +161,13 @@ readVar (OverrideVar _ var) = readVar var newCallback :: (Value -> ClickM ()) -> ResourceScope -> - InternalState -> (InternalState, SourceId) + InternalState -> (InternalState, EventId Value) newCallback k rscope s = let - new = SubscriptionSimple rscope (SourceId s.next_id) (k . unsafeCoerce) + new = SubscriptionSimple rscope (EventId s.next_id) (k . unsafeCoerce) subscriptions = new : s.subscriptions in - (s { next_id = s.next_id + 1, subscriptions}, SourceId s.next_id) + (s { next_id = s.next_id + 1, subscriptions}, EventId s.next_id) launchClickM :: InternalEnv -> ClickM a -> IO a launchClickM env = flip runReaderT env . unClickT . (<* syncPoint) . trampoline @@ -225,12 +226,12 @@ mapHoldVal f da = do reactive $ g ref where g ref scope s = (s', val) where - srcId = SourceId s.next_id - newSub = SubscriptionSimple scope srcId (k . unsafeCoerce) + srcId = EventId s.next_id + newSub = SubscriptionSimple scope (coerce srcId) (k . unsafeCoerce) k a = do let b = f a liftIO $ writeIORef ref b - modify $ unsafeTrigger srcId b + modify $ triggerEvent srcId b s' = s {subscriptions = newSub : s.subscriptions, next_id = succ s.next_id} val = MapHoldVal da f srcId ref diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 31e7a18..a7f9191 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -6,18 +6,21 @@ import Control.Exception import Control.Monad import Control.Monad.State import Data.Binary qualified as Binary +import Data.ByteString as BS import Data.ByteString.Builder (Builder) import Data.ByteString.Builder qualified as Builder -import Data.ByteString as BS import Data.ByteString.Lazy qualified as BSL import Data.Function -import Data.Maybe import Data.IORef import Data.List qualified as List import Data.Map (Map) import Data.Map qualified as Map +import Data.Maybe +import Data.Tuple import Data.Typeable +import Data.Word import Foreign.Store +import GHC.Conc.Sync import GHC.Generics import GHC.IO.Exception import Network.HTTP.Types as H @@ -28,15 +31,12 @@ import Network.Wai.Handler.WebSockets import Network.WebSockets import System.Environment import System.IO -import Data.Tuple -import Data.Word -import GHC.Conc.Sync -import "this" Clickable.Types -import "this" Clickable.Protocol -import "this" Clickable.Protocol.Value (Value(..)) import "this" Clickable.Internal (ClientMessage(..)) import "this" Clickable.Internal qualified as Internal +import "this" Clickable.Protocol +import "this" Clickable.Protocol.Value (Value(..)) +import "this" Clickable.Types data DevConfig a = DevConfig diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index d03f7f5..4082e47 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -24,11 +24,11 @@ data HaskellMessage data JavaScriptMessage = Start StartFlags | Return Value.Int32Le Value.Value - | TriggerCallbackMsg Value.Value SourceId + | TriggerCallbackMsg Value.Value AnyEventId | BeforeUnload -- ^ Fired from addEventListener("beforeunload") listener. Won't -- work under the DevServer! - deriving stock (Generic, Show) + deriving (Generic, Show) deriving anyclass (Binary) newtype StartFlags = StartFlags {unStartFlags :: Value.Value} @@ -145,7 +145,7 @@ data Expr -- ^ Evaluate arbitrary JavaScript code @(Eval "setTimeout(() => -- console.log('Hi!'), 1000)")@ will print a message with one second -- delay - | TriggerCallback SourceId Expr + | TriggerCallback AnyEventId Expr -- ^ As a side-effect emits `TriggerCallbackMsg` message to Haskell | UncaughtException Text deriving stock (Generic, Show) @@ -175,7 +175,7 @@ newtype FinalizerId = FinalizerId { unFinalizerId :: Value.Int32Le } newtype ResourceScope = ResourceScope {unResourceScope :: Value.Int32Le} deriving newtype (Show, Num, Ord, Eq, Binary) -newtype SourceId = SourceId {unSourceId :: Value.Int32Le} +newtype AnyEventId = AnyEventId {unAnyEventId :: Value.Int32Le} deriving newtype (Show, Num, Ord, Eq, Binary) newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index b79e699..40b6ec1 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -4,6 +4,7 @@ import Control.Monad.Reader import Control.Monad.Catch import Control.Monad.Fix import Control.Monad.State +import Data.Binary import Data.IORef import Data.Tuple import Data.Map (Map) @@ -13,8 +14,11 @@ import GHC.Exts import Clickable.Protocol import Clickable.Protocol.Value (Int32Le, Value) +newtype EventId a = EventId {unEventId :: Int32Le} + deriving newtype (Show, Num, Ord, Eq, Binary) + data DynVar a where - SourceVar :: SourceId -> IORef a -> DynVar a + SourceVar :: EventId a -> IORef a -> DynVar a OverrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a LensMap :: Lens' s a -> DynVar s -> DynVar a @@ -26,7 +30,7 @@ data DynVal a where ConstVal :: a -> DynVal a FromVar :: DynVar a -> DynVal a MapVal :: DynVal a -> (a -> b) -> DynVal b - MapHoldVal :: DynVal a -> (a -> b) -> SourceId -> IORef b -> DynVal b + MapHoldVal :: DynVal a -> (a -> b) -> EventId b -> IORef b -> DynVal b -- ^ todo: need redesign SplatVal :: DynVal (a -> b) -> DynVal a -> DynVal b OverrideSub :: (forall b. SubscribeFn a b -> SubscribeFn a b) -> DynVal a -> DynVal a @@ -67,7 +71,7 @@ data InternalEnv = InternalEnv data InternalState = InternalState { subscriptions :: [Subscription Any] , finalizers :: [Finalizer] - , transaction_queue :: Map SourceId (ClickM ()) + , transaction_queue :: Map AnyEventId (ClickM ()) , evaluation_queue :: [Expr] , next_id :: Int32Le } deriving (Generic) @@ -75,12 +79,12 @@ data InternalState = InternalState data Subscription a = SubscriptionSimple { ss_scope :: ResourceScope - , ss_event_id :: SourceId + , ss_event_id :: EventId a , ss_callback :: a -> ClickM () } | forall b. SubscriptionAccum { sa_resource_scope :: ResourceScope - , sa_event_id :: SourceId + , sa_event_id :: EventId a , sa_callback :: a -> b -> ClickM b , sa_accum_ref :: IORef b } @@ -96,9 +100,9 @@ data Finalizer } finalizerScope :: Finalizer -> ResourceScope -finalizerScope CustomFinalizer {cf_resource_scope} = cf_resource_scope -finalizerScope ScopeFinalizer {sf_resource_scope} = sf_resource_scope +finalizerScope CustomFinalizer{cf_resource_scope} = cf_resource_scope +finalizerScope ScopeFinalizer{sf_resource_scope} = sf_resource_scope subscriptionScope :: Subscription a -> ResourceScope -subscriptionScope SubscriptionSimple {ss_scope} = ss_scope -subscriptionScope SubscriptionAccum {sa_resource_scope} = sa_resource_scope +subscriptionScope SubscriptionSimple{ss_scope} = ss_scope +subscriptionScope SubscriptionAccum{sa_resource_scope} = sa_resource_scope From 36e808de46af5df4f1db30a7441926eee01b6ab3 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 6 Aug 2024 18:34:39 +0400 Subject: [PATCH 45/64] Rename EventId -> Event --- src/Clickable/Core.hs | 5 +++-- src/Clickable/DOM.hs | 15 +++++++-------- src/Clickable/Internal.hs | 31 +++++++++++++++++-------------- src/Clickable/Main/Dev.hs | 4 ++-- src/Clickable/Main/Wasm.hs | 4 ++-- src/Clickable/Protocol.hs | 6 +++--- src/Clickable/Types.hs | 18 ++++++++++++------ 7 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index b510964..89b50c7 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -30,7 +30,8 @@ import Clickable.Protocol.Value (Value, ToValue(..)) newVar :: a -> ClickM (DynVar a) newVar a = do ref <- liftIO $ newIORef a - state \s -> (SourceVar (EventId s.next_id) ref, s {next_id = s.next_id + 1}) + let mkEv s = unsafeFromEventId $ EventId s.next_id + state \s -> (SourceVar (mkEv s) ref, s {next_id = s.next_id + 1}) overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a overrideVar = OverrideVar @@ -131,7 +132,7 @@ installFinalizer k = reactive_ $ Internal.installFinalizer k newVarId :: ClickM VarId newVarId = reactive Internal.newVarId -newCallback :: (Value -> ClickM ()) -> ClickM (EventId Value) +newCallback :: (Value -> ClickM ()) -> ClickM (Event Value) newCallback k = reactive $ Internal.newCallback k ------------------ diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index 0d6b74d..6c117a3 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -1,13 +1,12 @@ module Clickable.DOM where import Control.Monad.Reader -import Data.Text (Text) import Data.Foldable -import Data.Kind import Data.Int +import Data.Kind +import Data.Text (Text) import GHC.Generics import Unsafe.Coerce -import Data.Coerce import Clickable.Types import Clickable.Protocol @@ -30,7 +29,7 @@ addEventListener :: ConnectResourceArgs callback -> callback -> HtmlM () addEventListener args k = lift $ connectResource args k data ConnectResourceArgs callback = ConnectResourceArgs - { aquire_resource :: ResourceScope -> AnyEventId -> Expr + { aquire_resource :: ResourceScope -> EventId -> Expr -- ^ When evaluated, as a side-effect resulting `Expr` must -- initialize some resource (could be DOM event, WebSocket -- connection etc) also must return a function that frees that @@ -43,10 +42,10 @@ connectResource args k = reactive_ \scope s -> let k' :: Value -> ClickM () k' = local (\e -> e {scope}) . args.mk_callback k - sourceId = EventId s.next_id - anyEventId = AnyEventId s.next_id - newSub = SubscriptionSimple scope (coerce sourceId) (k' . unsafeCoerce) - connectExpr = ConnectResource scope $ args.aquire_resource scope anyEventId + event = unsafeFromEventId eventId + eventId = EventId s.next_id + newSub = SubscriptionSimple scope event (k' . unsafeCoerce) + connectExpr = ConnectResource scope $ args.aquire_resource scope eventId in s { evaluation_queue = connectExpr : s.evaluation_queue , subscriptions = newSub : s.subscriptions diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index eae04c2..e79a57c 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -24,11 +24,11 @@ newInternalEnv eval_expr = do internal_state_ref <- newIORef emptyState {next_id = emptyState.next_id + 1} return InternalEnv {internal_state_ref, scope, eval_expr} -triggerEvent :: EventId a -> a -> InternalState -> InternalState +triggerEvent :: Event a -> a -> InternalState -> InternalState triggerEvent eventId a = defer eventId $ gets (.subscriptions) >>= notify where - anyEventId :: EventId Any = coerce eventId + anyEventId :: Event Any = coerce eventId notify :: [Subscription Any] -> ClickM () notify [] = return () notify (SubscriptionSimple {ss_event_id, ss_callback} : xs) @@ -42,7 +42,7 @@ triggerEvent eventId a = acc <- liftIO $ readIORef ref acc' <- k (unsafeCoerce a) acc liftIO $ writeIORef ref acc' - defer :: EventId a -> ClickM () -> InternalState -> InternalState + defer :: Event a -> ClickM () -> InternalState -> InternalState defer k act s = s {transaction_queue = Map.insert (coerce k) act s.transaction_queue} newScope :: ResourceScope -> InternalState -> (InternalState, ResourceScope) @@ -92,12 +92,13 @@ subscribe (SplatVal fv av) k = do subscribe fv $ f src subscribe av $ g src where - h scope s = (s', EventId s.next_id) where + h scope s = (s', coerce event) where s' = s { subscriptions = newsub : s.subscriptions , next_id = s.next_id + 1 } - newsub = SubscriptionSimple scope (EventId s.next_id) (k . unsafeCoerce) + event = unsafeFromEventId $ EventId s.next_id + newsub = SubscriptionSimple scope event (k . unsafeCoerce) f src fv' = do av' <- readVal av modify $ triggerEvent src $ fv' av' @@ -128,12 +129,13 @@ subscribeAccum (MapHoldVal _ _ srcid ref) k b = do subscribeAccum (SplatVal fv av) k b = do ref <- liftIO $ newIORef b let - h scope s = (s', EventId s.next_id) where + h scope s = (s', coerce event) where s' = s { subscriptions = newsub : s.subscriptions , next_id = s.next_id + 1 } - newsub = SubscriptionAccum scope (EventId s.next_id) (k . unsafeCoerce) ref + event = unsafeFromEventId $ EventId s.next_id + newsub = SubscriptionAccum scope event (k . unsafeCoerce) ref f src fv' = do av' <- readVal av modify $ triggerEvent src $ fv' av' @@ -161,13 +163,14 @@ readVar (OverrideVar _ var) = readVar var newCallback :: (Value -> ClickM ()) -> ResourceScope -> - InternalState -> (InternalState, EventId Value) + InternalState -> (InternalState, Event Value) newCallback k rscope s = let - new = SubscriptionSimple rscope (EventId s.next_id) (k . unsafeCoerce) + event = unsafeFromEventId $ EventId s.next_id + new = SubscriptionSimple rscope (coerce event) (k . unsafeCoerce) subscriptions = new : s.subscriptions in - (s { next_id = s.next_id + 1, subscriptions}, EventId s.next_id) + (s { next_id = s.next_id + 1, subscriptions}, event) launchClickM :: InternalEnv -> ClickM a -> IO a launchClickM env = flip runReaderT env . unClickT . (<* syncPoint) . trampoline @@ -226,14 +229,14 @@ mapHoldVal f da = do reactive $ g ref where g ref scope s = (s', val) where - srcId = EventId s.next_id - newSub = SubscriptionSimple scope (coerce srcId) (k . unsafeCoerce) + event = unsafeFromEventId $ EventId s.next_id + newSub = SubscriptionSimple scope (coerce event) (k . unsafeCoerce) k a = do let b = f a liftIO $ writeIORef ref b - modify $ triggerEvent srcId b + modify $ triggerEvent event b s' = s {subscriptions = newSub : s.subscriptions, next_id = succ s.next_id} - val = MapHoldVal da f srcId ref + val = MapHoldVal da f event ref unsafeInsertHtml :: Text -> Expr unsafeInsertHtml rawHtml = Eval diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index a7f9191..20484f8 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -203,9 +203,9 @@ websocketApp opt p = swap . Map.alterF (,Nothing) (fromIntegral tid) forM_ mmvar \mvar -> void $ tryPutMVar mvar val - BrowserMessage (TriggerCallbackMsg arg sourceId) -> void $ forkIO + BrowserMessage (TriggerCallbackMsg arg eid) -> void $ forkIO $ Internal.launchClickM conn.internal_env - $ modify (Internal.unsafeTrigger sourceId arg) + $ modify (Internal.triggerEvent (unsafeFromEventId eid) arg) BrowserMessage BeforeUnload -> return () DevServerMessage a -> void $ forkIO diff --git a/src/Clickable/Main/Wasm.hs b/src/Clickable/Main/Wasm.hs index a5b28fc..f606e9d 100644 --- a/src/Clickable/Main/Wasm.hs +++ b/src/Clickable/Main/Wasm.hs @@ -27,8 +27,8 @@ runWasm app p = mdo case jmsg of Just (Start flags) -> launchClickM internalEnv $ app flags - Just (TriggerCallbackMsg arg sourceId) -> - launchClickM internalEnv $ modify $ Internal.unsafeTrigger sourceId arg + Just (TriggerCallbackMsg arg eid) -> + launchClickM internalEnv $ modify $ Internal.triggerEvent (unsafeFromEventId eid) arg Just BeforeUnload -> launchClickM internalEnv $ freeScope True $ ResourceScope Internal.emptyState.next_id _ -> diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index 4082e47..cd7c946 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -24,7 +24,7 @@ data HaskellMessage data JavaScriptMessage = Start StartFlags | Return Value.Int32Le Value.Value - | TriggerCallbackMsg Value.Value AnyEventId + | TriggerCallbackMsg Value.Value EventId | BeforeUnload -- ^ Fired from addEventListener("beforeunload") listener. Won't -- work under the DevServer! @@ -145,7 +145,7 @@ data Expr -- ^ Evaluate arbitrary JavaScript code @(Eval "setTimeout(() => -- console.log('Hi!'), 1000)")@ will print a message with one second -- delay - | TriggerCallback AnyEventId Expr + | TriggerCallback EventId Expr -- ^ As a side-effect emits `TriggerCallbackMsg` message to Haskell | UncaughtException Text deriving stock (Generic, Show) @@ -175,7 +175,7 @@ newtype FinalizerId = FinalizerId { unFinalizerId :: Value.Int32Le } newtype ResourceScope = ResourceScope {unResourceScope :: Value.Int32Le} deriving newtype (Show, Num, Ord, Eq, Binary) -newtype AnyEventId = AnyEventId {unAnyEventId :: Value.Int32Le} +newtype EventId = EventId {unEventId :: Value.Int32Le} deriving newtype (Show, Num, Ord, Eq, Binary) newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index 40b6ec1..63cdf6d 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -14,11 +14,17 @@ import GHC.Exts import Clickable.Protocol import Clickable.Protocol.Value (Int32Le, Value) -newtype EventId a = EventId {unEventId :: Int32Le} +newtype Event a = Event {unEvent :: EventId} deriving newtype (Show, Num, Ord, Eq, Binary) +unsafeFromEventId :: EventId -> Event a +unsafeFromEventId = Event + +unsafeToEventId :: Event a -> EventId +unsafeToEventId = unEvent + data DynVar a where - SourceVar :: EventId a -> IORef a -> DynVar a + SourceVar :: Event a -> IORef a -> DynVar a OverrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a LensMap :: Lens' s a -> DynVar s -> DynVar a @@ -30,7 +36,7 @@ data DynVal a where ConstVal :: a -> DynVal a FromVar :: DynVar a -> DynVal a MapVal :: DynVal a -> (a -> b) -> DynVal b - MapHoldVal :: DynVal a -> (a -> b) -> EventId b -> IORef b -> DynVal b + MapHoldVal :: DynVal a -> (a -> b) -> Event b -> IORef b -> DynVal b -- ^ todo: need redesign SplatVal :: DynVal (a -> b) -> DynVal a -> DynVal b OverrideSub :: (forall b. SubscribeFn a b -> SubscribeFn a b) -> DynVal a -> DynVal a @@ -71,7 +77,7 @@ data InternalEnv = InternalEnv data InternalState = InternalState { subscriptions :: [Subscription Any] , finalizers :: [Finalizer] - , transaction_queue :: Map AnyEventId (ClickM ()) + , transaction_queue :: Map EventId (ClickM ()) , evaluation_queue :: [Expr] , next_id :: Int32Le } deriving (Generic) @@ -79,12 +85,12 @@ data InternalState = InternalState data Subscription a = SubscriptionSimple { ss_scope :: ResourceScope - , ss_event_id :: EventId a + , ss_event_id :: Event a , ss_callback :: a -> ClickM () } | forall b. SubscriptionAccum { sa_resource_scope :: ResourceScope - , sa_event_id :: EventId a + , sa_event_id :: Event a , sa_callback :: a -> b -> ClickM b , sa_accum_ref :: IORef b } From d9a91e94db835a63e0d0af1459082cabef01c8a1 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 7 Aug 2024 01:26:32 +0400 Subject: [PATCH 46/64] Polymorphic newCallback --- src/Clickable/Core.hs | 2 +- src/Clickable/Internal.hs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 89b50c7..49c5c7d 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -132,7 +132,7 @@ installFinalizer k = reactive_ $ Internal.installFinalizer k newVarId :: ClickM VarId newVarId = reactive Internal.newVarId -newCallback :: (Value -> ClickM ()) -> ClickM (Event Value) +newCallback :: (a -> ClickM ()) -> ClickM (Event a) newCallback k = reactive $ Internal.newCallback k ------------------ diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index e79a57c..7f4119a 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -161,9 +161,9 @@ readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var readVar (OverrideVar _ var) = readVar var newCallback :: - (Value -> ClickM ()) -> + (a -> ClickM ()) -> ResourceScope -> - InternalState -> (InternalState, Event Value) + InternalState -> (InternalState, Event a) newCallback k rscope s = let event = unsafeFromEventId $ EventId s.next_id From afba6e30d481178e37dceebfa75c34e2a707d670 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 12 Aug 2024 10:12:28 +0400 Subject: [PATCH 47/64] Improve generic deriving --- src/Clickable/Protocol/Value.hs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Clickable/Protocol/Value.hs b/src/Clickable/Protocol/Value.hs index 36c04b9..a0cdbe3 100644 --- a/src/Clickable/Protocol/Value.hs +++ b/src/Clickable/Protocol/Value.hs @@ -43,6 +43,9 @@ class ToValue a where default toValue :: (Generic a, GToValue (Rep a)) => a -> Value toValue = gToValue . G.from +instance (Generic a, GToValue (Rep a)) => ToValue (Generically a) where + toValue = gToValue . G.from . (\(Generically x) -> x) + instance ToValue Value where toValue = Prelude.id instance ToValue Bool where toValue = Bool @@ -76,6 +79,9 @@ class FromValue a where default fromValue :: (Generic a, GFromValue (Rep a)) => Value -> Maybe a fromValue = fmap G.to . gFromValue +instance (Generic a, GFromValue (Rep a)) => FromValue (Generically a) where + fromValue = fmap (Generically . G.to) . gFromValue + instance FromValue Value where fromValue = pure instance FromValue Bool where @@ -133,6 +139,9 @@ class GFromValue (f :: Type -> Type) where instance GFromValue f => GFromValue (M1 m c f) where gFromValue = fmap M1 . gFromValue @f +instance GFromValue U1 where + gFromValue _ = Just U1 + instance GFromJSObject (x :*: y) => GFromValue (x :*: y) where gFromValue (Object kvs) = gFromJSObject kvs gFromValue _ = Nothing @@ -147,6 +156,9 @@ class GToValue (f :: Type -> Type) where instance GToValue f => GToValue (M1 m c f) where gToValue (M1 f) = gToValue f +instance GToValue U1 where + gToValue _ = Null + instance GToJSObject (x :*: y) => GToValue (x :*: y) where gToValue (x :*: y) = Object $ gToJSObject (x :*: y) From 41c212c83ce1c42621677698662bc6bc6ca63c63 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 12 Aug 2024 11:47:52 +0400 Subject: [PATCH 48/64] Introduce more primitives into the protocol --- examples/charts/App.hs | 80 +++++++++++++ examples/charts/Charts.hs | 116 +++++++++++++++++++ examples/charts/PairSelector.hs | 44 ++++++++ examples/charts/charts.hs | 13 +++ examples/charts/dev.hs | 8 ++ examples/examples.cabal | 44 ++++++++ examples/todomvc/App.hs | 1 - examples/todomvc/TodoItem.hs | 27 ++--- examples/todomvc/Utils.hs | 7 +- examples/todomvc/wasm.hs | 1 - htmlt.cabal | 1 + jsbits/binary.ts | 127 ++++++++++++++++++--- jsbits/protocol.ts | 92 +++++++++++++++ src/Clickable.hs | 1 + src/Clickable/Core.hs | 4 +- src/Clickable/DOM.hs | 4 +- src/Clickable/Internal.hs | 18 +-- src/Clickable/Main/Dev.hs | 8 +- src/Clickable/Main/Wasm.hs | 9 +- src/Clickable/Protocol.hs | 97 +++++++++------- src/Clickable/Protocol/Value.hs | 192 ++++++++++++++++++++++++-------- src/Clickable/Types.hs | 7 +- 22 files changed, 750 insertions(+), 151 deletions(-) create mode 100644 examples/charts/App.hs create mode 100644 examples/charts/Charts.hs create mode 100644 examples/charts/PairSelector.hs create mode 100644 examples/charts/charts.hs create mode 100644 examples/charts/dev.hs create mode 100644 examples/examples.cabal diff --git a/examples/charts/App.hs b/examples/charts/App.hs new file mode 100644 index 0000000..1d212cb --- /dev/null +++ b/examples/charts/App.hs @@ -0,0 +1,80 @@ +module App where + +import Charts qualified as Charts +import Control.Monad.State +import Control.Monad +import Control.Concurrent +import Data.Proxy +import Data.Function ((&)) +import Data.Text (Text) +import Data.Text qualified as Text +import GHC.Generics +import Clickable +import Clickable.Protocol +import Clickable.Protocol.Value qualified as Value +import Clickable.FFI +import Data.Int +import Debug.Trace + + +data AppInstance = AppInstance + { state_var :: DynVar AppTab + } deriving (Generic) + +data AppTab + = ChartsTab Charts.ChartInstance + | HelpTab + +new :: ClickM AppInstance +new = do + charts_instance <- Charts.new + state_var <- newVar $ ChartsTab charts_instance + return AppInstance {state_var} + +html :: AppInstance -> HtmlM () +html self = do + el "style" $ text styles + div_ do + button_ do + text "Open Charts" + on @"click" do + inst <- Charts.new + modifyVar_ self.state_var $ const $ ChartsTab inst + button_ do + text "Open Help" + on @"click" $ modifyVar_ self.state_var $ const HelpTab + button_ do + text "Open Modal" + on @"click" do + mvar <- liftIO newEmptyMVar + attachToBody do + p_ $ text "Content of the modal" + button_ do + text "Close" + on @"click" $ liftIO $ putMVar mvar "dljfhdlsfjh" + syncPoint + answer <- liftIO $ takeMVar mvar + -- consoleLog answer + return () + dyn $ fromVar self.state_var & fmap \case + ChartsTab inst -> Charts.html inst + HelpTab -> p_ $ text + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod \ + \tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim \ + \veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea \ + \commodo consequat. Duis aute irure dolor in reprehenderit in voluptate \ + \velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint \ + \occaecat cupidatat non proident, sunt in culpa qui officia deserunt \ + \mollit anim id est laborum." + button_ do + text "Run computation" + on @"click" do + result <- evalExpr $ F64 2 `Subtract` F64 4 + traceShowM result + let md :: Maybe Int32 = Value.fromValue result + forM_ md \d -> enqueueExpr $ Call (Id "console") "log" [toExpr d] + +styles :: Text +styles = "\ + \ \ + \ " diff --git a/examples/charts/Charts.hs b/examples/charts/Charts.hs new file mode 100644 index 0000000..41ed7a3 --- /dev/null +++ b/examples/charts/Charts.hs @@ -0,0 +1,116 @@ +module Charts where + +import Data.Text (Text) +import Data.Text qualified as Text +import Data.Function ((&)) +import GHC.Generics + +import Clickable +import Clickable.FFI +import PairSelector qualified as PairSelector + +------------------------------------------------------- +-- EXAMPLE OF APPLICATION FEATURING FINANCIAL CHARTS -- +------------------------------------------------------- + +data ChartState = ChartState + { main_transform :: Transform2D + , mouse_position :: Point + , counter :: Int + } deriving (Show, Eq, Generic) + +data ChartInstance = ChartInstance + { state_var :: DynVar ChartState + , pair_selector_instance :: DynVar PairSelector.PairSelectorState + } deriving (Generic) + +new :: ClickM ChartInstance +new = do + pair_selector_instance <- PairSelector.new + state_var <- newVar ChartState + { main_transform = Transform2D 0 0 0 0 + , mouse_position = Point 0 0 + , counter = 0 + } + return ChartInstance {state_var, pair_selector_instance} + +html :: ChartInstance -> HtmlM () +html self = do + el "style" $ text styles + div_ [class_ "Charts-root"] do + addEventListener mouseMove do + enqueueExpr $ Call (Id "console") "log" [String "jshflkjsdhflasfjhlaskjfhsdaj"] + h1_ $ text "Canvas with candle chart" + div_ do + PairSelector.html self.pair_selector_instance + div_ do + button_ do + text "Clickable this button" + on @"click" do + modifyVar_ self.state_var \s -> s {counter = s.counter + 1 } + button_ do + text "Print state" + on @"click" do + s <- readVar self.state_var + -- consoleLog $ Text.pack $ show s + return () + span_ [] $ dynText $ fromVar self.state_var & fmap \s -> + "You clicked " <> Text.pack (show s.counter) <> " times" + canvas_ [class_ "Charts-canvas"] $ return () + +styles :: Text +styles = "\ + \.Charts-root {\ + \ max-width: 900;\ + \ width: 100%\ + \ padding: 16px;\ + \ margin: 0 auto;\ + \}\ + \.Charts-canvas {\ + \ width: 100%;\ + \ height: 550px;\ + \ border: solid 1px black;\ + \}\ + \ " + +data Transform2D = Transform2D + { a :: Double -- ^ X scaling + , c :: Double -- ^ X translation + , e :: Double -- ^ Y scaling + , f :: Double -- ^ Y translation + } deriving (Show, Eq, Generic) + +data Point = Point + { point_x :: Double + , point_y :: Double + } deriving (Eq, Show, Generic) + +-- setMouseCoords :: Point -> Edit ChartState +-- setMouseCoords p = Fld (Proxy @"mouse_position") (Ins p) + + +-- moveScreen :: Double -> Jet ChartState -> Jet ChartState +-- moveScreen dir old = +-- let +-- beg = negate old.position.main_transform.c / old.position.main_transform.a +-- end = (w - old.position.main_transform.c) / old.position.main_transform.a +-- inc = (end - beg) * dir +-- w = 1000 +-- c = old.position.main_transform.c - +-- (inc * old.position.main_transform.a) +-- new = old.position +-- { main_transform = old.position.main_transform {c} +-- } +-- in +-- Jet new (Fld (Proxy @"main_transform") (Fld (Proxy @"c") (Ins c)) : old.velocity) + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event +mouseMove :: ConnectResourceArgs (ClickM ()) +mouseMove = ConnectResourceArgs + { aquire_resource = \scope sourceId -> + Eval (normalEventWrapper "mousemove" EventListenerOptions + { prevent_default = True + , stop_propagation = True + }) `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + , mk_callback = \k _ -> k + } diff --git a/examples/charts/PairSelector.hs b/examples/charts/PairSelector.hs new file mode 100644 index 0000000..77cbf52 --- /dev/null +++ b/examples/charts/PairSelector.hs @@ -0,0 +1,44 @@ +module PairSelector where + +import Data.Text (Text) +import Data.Text qualified as Text +import Data.Function hiding (on) +import GHC.Generics + +import Clickable + +data TradingPair = TradingPair + { base :: Text + , quote :: Text + , exchange :: Text + } deriving (Show, Eq, Generic) + +data PairSelectorState = PairSelectorState + { selected_pair :: Maybe TradingPair + , options :: [TradingPair] + } deriving (Show, Eq, Generic) + +new :: ClickM (DynVar PairSelectorState) +new = + newVar PairSelectorState + { selected_pair = Nothing + , options = [] + } + +html :: DynVar PairSelectorState -> HtmlM () +html self = do + el "style" $ text styles + div_ [class_ "PairSelector-root"] do + button_ do + text "Select pair" + on @"click" $ modifyVar_ self \s -> case s.selected_pair of + Just _ -> s {selected_pair = Nothing} + Nothing -> s {selected_pair = Just $ TradingPair "BTC" "USDT" "MEXC"} + span_ $ dynText $ fromVar self & fmap \s -> s.selected_pair & maybe + "Nothing selected" + (("Selected pair: " <>) . Text.pack . show) + +styles :: Text +styles = "\ + \ \ + \ " diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs new file mode 100644 index 0000000..310e418 --- /dev/null +++ b/examples/charts/charts.hs @@ -0,0 +1,13 @@ +import Control.Monad.Reader +import Clickable +import GHC.Ptr +import GHC.Word +import "this" App qualified as App + +main :: IO () +main = return () + +foreign export ccall wasm_main :: Ptr Word8 -> IO () +wasm_main p = do + _ <- runApp p \_ -> attachToBody $ lift App.new >>= App.html + return () diff --git a/examples/charts/dev.hs b/examples/charts/dev.hs new file mode 100644 index 0000000..e42e9a5 --- /dev/null +++ b/examples/charts/dev.hs @@ -0,0 +1,8 @@ +import Clickable +import Clickable.Main.DevServer +import Control.Monad.Reader + +import "this" App qualified as App + +main :: IO () +main = runDev \_ -> attachToBody $ lift App.new >>= App.html diff --git a/examples/examples.cabal b/examples/examples.cabal new file mode 100644 index 0000000..749e385 --- /dev/null +++ b/examples/examples.cabal @@ -0,0 +1,44 @@ +cabal-version: 3.4 + +name: examples +version: 0.1.0.0 +build-type: Simple + +executable todomvc + ghc-options: + -O3 -funbox-strict-fields -fstrictness -ddump-splices + -Wall -Wno-missing-signatures -Wno-name-shadowing -Wno-unused-matches + -Wno-unused-do-bind + hs-source-dirs: todomvc + if arch(wasm32) + ghc-options: + -no-hs-main -optl-mexec-model=reactor + -optl-Wl,--export=hs_init,--export=wasm_app,--export=malloc,--export=free + main-is: wasm.hs + else + main-is: dev.hs + build-depends: + base, + text, + transformers, + mtl, + htmlt, + other-modules: + App + TodoItem + TodoList + Utils + default-extensions: + GHC2024 + AllowAmbiguousTypes + BlockArguments + DefaultSignatures + DeriveAnyClass + FunctionalDependencies + OverloadedRecordDot + OverloadedStrings + PackageImports + RecordWildCards + RecursiveDo + TypeFamilies + UndecidableInstances diff --git a/examples/todomvc/App.hs b/examples/todomvc/App.hs index 9068dd1..5435714 100644 --- a/examples/todomvc/App.hs +++ b/examples/todomvc/App.hs @@ -3,7 +3,6 @@ module App where import Control.Monad.Trans import Data.Maybe import Clickable -import Clickable.Protocol import "this" TodoList qualified as TodoList import "this" Utils diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index 5c4b678..1319a85 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -1,12 +1,10 @@ module TodoItem where +import Clickable import Data.List qualified as List import Data.Maybe import Data.Text (Text) import GHC.Int -import Clickable -import Clickable.Protocol (VarId) -import Clickable.Protocol.Value qualified as Value import "this" Utils @@ -62,10 +60,9 @@ eval cfg = \case html :: TodoItemConfig -> HtmlM () html cfg = li_ mdo - let - completedDyn = (.completed) <$> fromVar cfg.state_var - editingDyn = isJust . (.editing) <$> fromVar cfg.state_var - valueDyn = fromMaybe "" . (.editing) <$> fromVar cfg.state_var + let completedDyn = (.completed) <$> fromVar cfg.state_var + editingDyn = isJust . (.editing) <$> fromVar cfg.state_var + valueDyn = fromMaybe "" . (.editing) <$> fromVar cfg.state_var toggleClass "completed" completedDyn toggleClass "editing" editingDyn toggleClass "hidden" cfg.is_hidden_dyn @@ -85,15 +82,15 @@ html cfg = li_ mdo saveCurrentNode return () -instance Value.ToValue TodoItemState where - toValue s = Value.Object - [ ("title", Value.toValue s.title) - , ("completed", Value.toValue s.completed) +instance ToValue TodoItemState where + toValue s = Vobj + [ ("title", toValue s.title) + , ("completed", toValue s.completed) ] -instance Value.FromValue TodoItemState where - fromValue (Value.Object kv) = do - title <- Value.fromValue =<< List.lookup "title" kv - completed <- Value.fromValue =<< List.lookup "completed" kv +instance FromValue TodoItemState where + fromValue (Vobj kv) = do + title <- fromValue =<< List.lookup "title" kv + completed <- fromValue =<< List.lookup "completed" kv return TodoItemState {editing=Nothing, ..} fromValue _ = Nothing diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs index 83da890..da360ed 100644 --- a/examples/todomvc/Utils.hs +++ b/examples/todomvc/Utils.hs @@ -1,21 +1,18 @@ module Utils where import Data.Text (Text) - import Clickable -import Clickable.Protocol -import Clickable.Protocol.Value (FromValue(..), ToValue(..)) readLocalStorage :: FromValue v => Text -> ClickM (Maybe v) readLocalStorage key = do let jsonParse = Call (Id "JSON") "parse" . (:[]) - jsval <- evalExpr $ jsonParse $ Call (Id "localStorage") "getItem" [String key] + jsval <- evalExpr $ jsonParse $ Call (Id "localStorage") "getItem" [Str key] return $ fromValue jsval saveLocalStorage :: ToValue v => Text -> v -> ClickM () saveLocalStorage key val = do let stringify = Call (Id "JSON") "stringify" . (:[]) . valueToExpr . toValue - enqueueExpr $ Call (Id "localStorage") "setItem" [String key, stringify val] + enqueueExpr $ Call (Id "localStorage") "setItem" [Str key, stringify val] assignFocus :: VarId -> ClickM () assignFocus elem = enqueueExpr $ Call (Var elem) "focus" [] diff --git a/examples/todomvc/wasm.hs b/examples/todomvc/wasm.hs index a5ef076..60c19ad 100644 --- a/examples/todomvc/wasm.hs +++ b/examples/todomvc/wasm.hs @@ -1,4 +1,3 @@ -import Control.Monad.Reader import Clickable.Main.Wasm import GHC.Ptr import GHC.Word diff --git a/htmlt.cabal b/htmlt.cabal index f7ed86f..2e35985 100644 --- a/htmlt.cabal +++ b/htmlt.cabal @@ -68,5 +68,6 @@ library OverloadedStrings PackageImports RecursiveDo + StrictData TypeFamilies UndecidableInstances diff --git a/jsbits/binary.ts b/jsbits/binary.ts index 70ed1b0..69d0949 100644 --- a/jsbits/binary.ts +++ b/jsbits/binary.ts @@ -26,7 +26,14 @@ export class DecoderBase { export type Decoder = | Int8Decoder + | Int16Decoder | Int32Decoder + | Int64Decoder + | Word8Decoder + | Word16Decoder + | Word32Decoder + | Word64Decoder + | Float32Decoder | Float64Decoder | Uint8ArrayDecoder | StringDecoder @@ -37,16 +44,18 @@ export type Decoder = | TupleDecoder ; -export class Int8Decoder extends DecoderBase { -} -export class Int32Decoder extends DecoderBase { -} -export class Float64Decoder extends DecoderBase { -} -export class Uint8ArrayDecoder extends DecoderBase { -} -export class StringDecoder extends DecoderBase { -} +export class Int8Decoder extends DecoderBase {} +export class Int16Decoder extends DecoderBase {} +export class Int32Decoder extends DecoderBase {} +export class Int64Decoder extends DecoderBase {} +export class Word8Decoder extends DecoderBase {} +export class Word16Decoder extends DecoderBase {} +export class Word32Decoder extends DecoderBase {} +export class Word64Decoder extends DecoderBase {} +export class Float32Decoder extends DecoderBase {} +export class Float64Decoder extends DecoderBase {} +export class Uint8ArrayDecoder extends DecoderBase {} +export class StringDecoder extends DecoderBase {} export class ArrayDecoder extends DecoderBase { constructor( readonly _element: Decoder, @@ -79,9 +88,30 @@ export function computeSize( if (decoder instanceof Int8Decoder) { return 1; } + if (decoder instanceof Int16Decoder) { + return 2; + } if (decoder instanceof Int32Decoder) { return 4; } + if (decoder instanceof Int64Decoder) { + return 8; + } + if (decoder instanceof Word8Decoder) { + return 1; + } + if (decoder instanceof Word16Decoder) { + return 2; + } + if (decoder instanceof Word32Decoder) { + return 4; + } + if (decoder instanceof Word64Decoder) { + return 8; + } + if (decoder instanceof Float32Decoder) { + return 4; + } if (decoder instanceof Float64Decoder) { return 8; } @@ -128,17 +158,44 @@ export function runDecoder( mem: Uint8Array, ptr: HaskellPointer, ): [A, HaskellPointer] { + const view = new DataView(mem.buffer); if (decoder instanceof Int8Decoder) { - const result = mem[ptr] as any as A; - return [result, ptr + 1]; + const value = view.getInt8(ptr) as any; + return [value, ptr + 1]; + } + if (decoder instanceof Int16Decoder) { + const value = view.getInt16(ptr, true) as any; + return [value, ptr + 2]; } if (decoder instanceof Int32Decoder) { - const view = new DataView(mem.buffer); const value = view.getInt32(ptr, true) as any; return [value as any as A, ptr + 4]; } + if (decoder instanceof Int64Decoder) { + const value = view.getBigInt64(ptr, true) as any; + return [value, ptr + 8]; + } + if (decoder instanceof Word8Decoder) { + const result = mem[ptr] as any as A; + return [result, ptr + 1]; + } + if (decoder instanceof Word16Decoder) { + const value = view.getUint8(ptr) as any; + return [value, ptr + 1]; + } + if (decoder instanceof Word32Decoder) { + const value = view.getUint32(ptr, true) as any; + return [value as any as A, ptr + 4]; + } + if (decoder instanceof Word64Decoder) { + const value = view.getBigUint64(ptr, true) as any; + return [value, ptr + 8]; + } + if (decoder instanceof Float32Decoder) { + const value = view.getFloat32(ptr, true) as any; + return [value, ptr + 4]; + } if (decoder instanceof Float64Decoder) { - const view = new DataView(mem.buffer); const value = view.getFloat64(ptr, true) as any; return [value, ptr + 8]; } @@ -224,17 +281,44 @@ export function runEncoder( ptr: HaskellPointer, value: A, ): HaskellPointer { + const view = new DataView(mem.buffer); if (decoder instanceof Int8Decoder) { - mem[ptr] = value as any as number; + view.setInt8(ptr, value as number); return ptr + 1; } + if (decoder instanceof Int16Decoder) { + view.setInt16(ptr, value as number, true); + return ptr + 2; + } if (decoder instanceof Int32Decoder) { - const view = new DataView(mem.buffer); view.setInt32(ptr, value as number, true); return ptr + 4; } + if (decoder instanceof Int64Decoder) { + view.setBigInt64(ptr, value as bigint, true); + return ptr + 8; + } + if (decoder instanceof Word8Decoder) { + view.setUint8(ptr, value as number); + return ptr + 1; + } + if (decoder instanceof Word16Decoder) { + view.setUint16(ptr, value as number, true); + return ptr + 2; + } + if (decoder instanceof Word32Decoder) { + view.setUint32(ptr, value as number, true); + return ptr + 4; + } + if (decoder instanceof Word64Decoder) { + view.setBigUint64(ptr, value as bigint, true); + return ptr + 8; + } + if (decoder instanceof Float32Decoder) { + view.setFloat32(ptr, value as number, true); + return ptr + 4; + } if (decoder instanceof Float64Decoder) { - const view = new DataView(mem.buffer); view.setFloat64(ptr, value as number, true); return ptr + 8; } @@ -326,9 +410,16 @@ function readDiscriminator(dscrSize: number, mem: Uint8Array, ix: HaskellPointer } export const int8 = new Int8Decoder(); - +export const int16 = new Int16Decoder(); export const int32 = new Int32Decoder(); +export const int64 = new Int64Decoder(); + +export const word8 = new Word8Decoder(); +export const word16 = new Word16Decoder(); +export const word32 = new Word32Decoder(); +export const word64 = new Word64Decoder(); +export const float32 = new Float32Decoder(); export const float64 = new Float64Decoder(); export const string = new StringDecoder(); diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index db48af7..3083f65 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -40,9 +40,33 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc case ExprTag.Boolean: { return exp[0] != 0; } + case ExprTag.I8: { + return exp[0]; + } + case ExprTag.I16: { + return exp[0]; + } case ExprTag.I32: { return exp[0]; } + case ExprTag.I64: { + return exp[0]; + } + case ExprTag.U8: { + return exp[0]; + } + case ExprTag.U16: { + return exp[0]; + } + case ExprTag.U32: { + return exp[0]; + } + case ExprTag.U64: { + return exp[0]; + } + case ExprTag.F32: { + return exp[0]; + } case ExprTag.F64: { return exp[0]; } @@ -293,6 +317,9 @@ export function unknownToValue(inp: unknown): Value { if (typeof(inp) === 'string') { return { tag: ValueTag.String, 0: inp }; } + if (typeof(inp) === 'bigint') { + return { tag: ValueTag.I64, 0: inp }; + } if (Array.isArray(inp)) { return { tag: ValueTag.Array, 0: inp.map(unknownToValue) }; } @@ -313,7 +340,15 @@ export function unknownToValue(inp: unknown): Value { export enum ValueTag { Null, Boolean, + I8, + I16, I32, + I64, + U8, + U16, + U32, + U64, + F32, F64, String, Array, @@ -324,7 +359,15 @@ export enum ValueTag { export type Value = | { tag: ValueTag.Null } | { tag: ValueTag.Boolean, 0: number } + | { tag: ValueTag.I8, 0: number } + | { tag: ValueTag.I16, 0: number } | { tag: ValueTag.I32, 0: number } + | { tag: ValueTag.I64, 0: bigint } + | { tag: ValueTag.U8, 0: number } + | { tag: ValueTag.U16, 0: number } + | { tag: ValueTag.U32, 0: number } + | { tag: ValueTag.U64, 0: bigint } + | { tag: ValueTag.F32, 0: number } | { tag: ValueTag.F64, 0: number } | { tag: ValueTag.String, 0: string } | { tag: ValueTag.Array, 0: Value[] } @@ -335,8 +378,20 @@ export type Value = export const jvalue = b.recursive(self => b.discriminate({ [ValueTag.Null]: b.record({ }), [ValueTag.Boolean]: b.record({ 0: b.int8 }), + + [ValueTag.I8]: b.record({ 0: b.int8 }), + [ValueTag.I16]: b.record({ 0: b.int16 }), [ValueTag.I32]: b.record({ 0: b.int32 }), + [ValueTag.I64]: b.record({ 0: b.int64 }), + + [ValueTag.U8]: b.record({ 0: b.word8 }), + [ValueTag.U16]: b.record({ 0: b.word16 }), + [ValueTag.U32]: b.record({ 0: b.word32 }), + [ValueTag.U64]: b.record({ 0: b.word64 }), + + [ValueTag.F32]: b.record({ 0: b.float32 }), [ValueTag.F64]: b.record({ 0: b.float64 }), + [ValueTag.String]: b.record({ 0: b.string }), [ValueTag.Array]: b.record({ 0: b.array(self) }), [ValueTag.Object]: b.record({ 0: b.array(b.tuple(b.string, self)) }), @@ -346,8 +401,20 @@ export const jvalue = b.recursive(self => b.discriminate({ export enum ExprTag { Null, Boolean, + + I8, + I16, I32, + I64, + + U8, + U16, + U32, + U64, + + F32, F64, + String, Array, Object, @@ -399,8 +466,20 @@ export enum ExprTag { export type Expr = | { tag: ExprTag.Null } | { tag: ExprTag.Boolean, 0: number } + + | { tag: ExprTag.I8, 0: number } + | { tag: ExprTag.I16, 0: number } | { tag: ExprTag.I32, 0: number } + | { tag: ExprTag.I64, 0: bigint } + + | { tag: ExprTag.U8, 0: number } + | { tag: ExprTag.U16, 0: number } + | { tag: ExprTag.U32, 0: number } + | { tag: ExprTag.U64, 0: bigint } + + | { tag: ExprTag.F32, 0: number } | { tag: ExprTag.F64, 0: number } + | { tag: ExprTag.String, 0: string } | { tag: ExprTag.Array, 0: Expr[] } | { tag: ExprTag.Object, 0: [string, Expr][] } @@ -452,11 +531,24 @@ export type Expr = export const expr = b.recursive(self => b.discriminate({ [ExprTag.Null]: b.record({}), [ExprTag.Boolean]: b.record({ 0: b.int8 }), + + [ExprTag.I8]: b.record({ 0: b.int8 }), + [ExprTag.I16]: b.record({ 0: b.int16 }), [ExprTag.I32]: b.record({ 0: b.int32 }), + [ExprTag.I64]: b.record({ 0: b.int64 }), + + [ExprTag.U8]: b.record({ 0: b.word8 }), + [ExprTag.U16]: b.record({ 0: b.word16 }), + [ExprTag.U32]: b.record({ 0: b.word32 }), + [ExprTag.U64]: b.record({ 0: b.word64 }), + + [ExprTag.F32]: b.record({ 0: b.float32 }), [ExprTag.F64]: b.record({ 0: b.float64 }), + [ExprTag.String]: b.record({ 0: b.string }), [ExprTag.Array]: b.record({ 0: b.array(self) }), [ExprTag.Object]: b.record({ 0: b.array(b.tuple(b.string, self)) }), + [ExprTag.Uint8Array]: b.record({ 0: b.u8array }), [ExprTag.Dot]: b.record({ 0: self, 1: b.string }), [ExprTag.SetProp]: b.record({ 0: self, 1: b.string, 2: self }), diff --git a/src/Clickable.hs b/src/Clickable.hs index 4eda004..3fe4dc8 100644 --- a/src/Clickable.hs +++ b/src/Clickable.hs @@ -5,5 +5,6 @@ import Clickable.Core as Exports import Clickable.Element as Exports import Clickable.Property as Exports import Clickable.Protocol as Exports +import Clickable.Protocol.Value as Exports import Clickable.Types as Exports import Wasm.Compat.Prim as Exports diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 49c5c7d..7932378 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -21,7 +21,7 @@ import Clickable.Internal (reactive, reactive_) import Clickable.Internal qualified as Internal import Clickable.Types import Clickable.Protocol -import Clickable.Protocol.Value (Value, ToValue(..)) +import Clickable.Protocol.Value --------------------------------------- -- OPERATIONS OVER DYNAMIC VARIABLES -- @@ -30,7 +30,7 @@ import Clickable.Protocol.Value (Value, ToValue(..)) newVar :: a -> ClickM (DynVar a) newVar a = do ref <- liftIO $ newIORef a - let mkEv s = unsafeFromEventId $ EventId s.next_id + let mkEv s = unsafeFromEventId $ EventId $ Int32Le s.next_id state \s -> (SourceVar (mkEv s) ref, s {next_id = s.next_id + 1}) overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index 6c117a3..c1189d2 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -10,7 +10,7 @@ import Unsafe.Coerce import Clickable.Types import Clickable.Protocol -import Clickable.Protocol.Value (Value, FromValue(..), ToValue(..)) +import Clickable.Protocol.Value import Clickable.Internal @@ -43,7 +43,7 @@ connectResource args k = reactive_ \scope s -> k' :: Value -> ClickM () k' = local (\e -> e {scope}) . args.mk_callback k event = unsafeFromEventId eventId - eventId = EventId s.next_id + eventId = EventId $ Int32Le s.next_id newSub = SubscriptionSimple scope event (k' . unsafeCoerce) connectExpr = ConnectResource scope $ args.aquire_resource scope eventId in diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index 7f4119a..cfaa65f 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -12,7 +12,7 @@ import Unsafe.Coerce import GHC.Exts import Clickable.Protocol -import Clickable.Protocol.Value (Value) +import Clickable.Protocol.Value import Clickable.Types emptyState :: InternalState @@ -20,7 +20,7 @@ emptyState = InternalState [] [] Map.empty [] 0 newInternalEnv :: (Expr -> IO Value) -> IO InternalEnv newInternalEnv eval_expr = do - let scope = ResourceScope emptyState.next_id + let scope = ResourceScope $ Int32Le emptyState.next_id internal_state_ref <- newIORef emptyState {next_id = emptyState.next_id + 1} return InternalEnv {internal_state_ref, scope, eval_expr} @@ -48,14 +48,14 @@ triggerEvent eventId a = newScope :: ResourceScope -> InternalState -> (InternalState, ResourceScope) newScope p s = let - scopeId = ResourceScope s.next_id + scopeId = ResourceScope $ Int32Le s.next_id finalizers = ScopeFinalizer p scopeId : s.finalizers s' = s {finalizers, next_id = s.next_id + 1} in (s', scopeId) newVarId :: ResourceScope -> InternalState -> (InternalState, VarId) -newVarId e s = (s {next_id = s.next_id + 1}, VarId e s.next_id) +newVarId e s = (s {next_id = s.next_id + 1}, VarId e $ Int32Le s.next_id) freeScope :: Bool -> @@ -97,7 +97,7 @@ subscribe (SplatVal fv av) k = do { subscriptions = newsub : s.subscriptions , next_id = s.next_id + 1 } - event = unsafeFromEventId $ EventId s.next_id + event = unsafeFromEventId $ EventId $ Int32Le s.next_id newsub = SubscriptionSimple scope event (k . unsafeCoerce) f src fv' = do av' <- readVal av @@ -134,7 +134,7 @@ subscribeAccum (SplatVal fv av) k b = do { subscriptions = newsub : s.subscriptions , next_id = s.next_id + 1 } - event = unsafeFromEventId $ EventId s.next_id + event = unsafeFromEventId $ EventId $ Int32Le s.next_id newsub = SubscriptionAccum scope event (k . unsafeCoerce) ref f src fv' = do av' <- readVal av @@ -166,7 +166,7 @@ newCallback :: InternalState -> (InternalState, Event a) newCallback k rscope s = let - event = unsafeFromEventId $ EventId s.next_id + event = unsafeFromEventId $ EventId $ Int32Le s.next_id new = SubscriptionSimple rscope (coerce event) (k . unsafeCoerce) subscriptions = new : s.subscriptions in @@ -229,7 +229,7 @@ mapHoldVal f da = do reactive $ g ref where g ref scope s = (s', val) where - event = unsafeFromEventId $ EventId s.next_id + event = unsafeFromEventId $ EventId $ Int32Le s.next_id newSub = SubscriptionSimple scope (coerce event) (k . unsafeCoerce) k a = do let b = f a @@ -252,4 +252,4 @@ unsafeInsertHtml rawHtml = Eval \ builder.appendChild(iter);\ \ }\ \}\ - \})" `Apply` [Arg 0 0, String rawHtml] + \})" `Apply` [Arg 0 0, Str rawHtml] diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 20484f8..ae35e84 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -35,7 +35,7 @@ import System.IO import "this" Clickable.Internal (ClientMessage(..)) import "this" Clickable.Internal qualified as Internal import "this" Clickable.Protocol -import "this" Clickable.Protocol.Value (Value(..)) +import "this" Clickable.Protocol.Value import "this" Clickable.Types @@ -200,7 +200,7 @@ websocketApp opt p = $ app.client_app conn flags BrowserMessage (Return tid val) -> do mmvar <- atomicModifyIORef' conn.threads_ref $ - swap . Map.alterF (,Nothing) (fromIntegral tid) + swap . Map.alterF (,Nothing) (fromIntegral tid.unInt32Le) forM_ mmvar \mvar -> void $ tryPutMVar mvar val BrowserMessage (TriggerCallbackMsg arg eid) -> void $ forkIO @@ -231,7 +231,7 @@ websocketApp opt p = newInternalEnv conn awaiting = Internal.newInternalEnv \expr -> do tid <- fmap fromThreadId myThreadId - sendDataMessage conn . Binary . Binary.encode $ EvalExpr (fromIntegral tid) expr + sendDataMessage conn . Binary . Binary.encode $ EvalExpr (Int32Le (fromIntegral tid)) expr mvar <- newEmptyMVar modifyIORef' awaiting $ Map.insert tid mvar takeMVar mvar @@ -318,4 +318,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>T,HA:()=>x,PV:()=>w,Tf:()=>P,YE:()=>y,YO:()=>M,Yj:()=>D,b9:()=>m,g1:()=>O,tB:()=>A});var n=r(366);class _{encode(e){const t=E(this,e),r=new Uint8Array(t);return b(this,r,0,e),r}decode(e){const[t,r]=g(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{constructor(e){super(),this._element=e}}class p extends _{constructor(e){super(),this._description=e}}class u extends _{constructor(e){super(),this._alternatives=e}}class f extends _{constructor(e){super(),this._self=e}}class d extends _{constructor(e){super(),this._tuple=e}}function E(e,t){if(e instanceof a)return 1;if(e instanceof s)return 4;if(e instanceof i)return 8;if(e instanceof c){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof o)return 8+t.length;if(e instanceof l){const r=8;return t.reduce(((t,r)=>t+E(e._element,r)),r)}if(e instanceof p){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+E(e._description[n],r[n])),0)}if(e instanceof u){const r=t;return h(Object.keys(e._alternatives).length)+E(e._alternatives[r.tag],r)}if(e instanceof f)return E(e._self,t);if(e instanceof d){const r=t;return e._tuple.reduce(((e,t,n)=>e+E(t,r[n])),0)}return(0,n.G)(e)}function g(e,t,r){if(e instanceof a)return[t[r],r+1];if(e instanceof s)return[new DataView(t.buffer).getInt32(r,!0),r+4];if(e instanceof i)return[new DataView(t.buffer).getFloat64(r,!0),r+8];if(e instanceof c){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof o){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof l){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=g(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof u){const n=h(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=g(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof f)return g(e._self,t,r);if(e instanceof d){let n=r;return[e._tuple.map((e=>{const[r,_]=g(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function b(e,t,r,_){if(e instanceof a)return t[r]=_,r+1;if(e instanceof s)return new DataView(t.buffer).setInt32(r,_,!0),r+4;if(e instanceof i)return new DataView(t.buffer).setFloat64(r,_,!0),r+8;if(e instanceof c){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof o){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof l){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=b(e,t,a,n[r])})),a}return(0,n.G)(e)}function h(e){return Math.ceil(Math.log2(e)/8)}const y=new a,x=new s,T=new i,D=new c,m=new o;function M(e){return new l(e)}function O(e){return new p(e)}function P(e){return new u(e)}function w(...e){return new d(e)}function A(e){const t=new f(void 0),r=e(t);return t._self=r,r}var I;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(I||(I={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function evalUint8Array(e,t,r,n){return evalExpr(e,t,r,expr.decode(n))}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I32=2]=\"I32\",e[e.F64=3]=\"F64\",e[e.String=4]=\"String\",e[e.Array=5]=\"Array\",e[e.Object=6]=\"Object\",e[e.Uint8Array=7]=\"Uint8Array\",e[e.Dot=8]=\"Dot\",e[e.SetProp=9]=\"SetProp\",e[e.Ix=10]=\"Ix\",e[e.Plus=11]=\"Plus\",e[e.Subtract=12]=\"Subtract\",e[e.Multiply=13]=\"Multiply\",e[e.Divide=14]=\"Divide\",e[e.Id=15]=\"Id\",e[e.Lam=16]=\"Lam\",e[e.Arg=17]=\"Arg\",e[e.Apply=18]=\"Apply\",e[e.Call=19]=\"Call\",e[e.AssignVar=20]=\"AssignVar\",e[e.FreeVar=21]=\"FreeVar\",e[e.Var=22]=\"Var\",e[e.FreeScope=23]=\"FreeScope\",e[e.InsertNode=24]=\"InsertNode\",e[e.CreateElement=25]=\"CreateElement\",e[e.CreateElementNS=26]=\"CreateElementNS\",e[e.CreateText=27]=\"CreateText\",e[e.ElementProp=28]=\"ElementProp\",e[e.ElementAttr=29]=\"ElementAttr\",e[e.InsertClassList=30]=\"InsertClassList\",e[e.RemoveClassList=31]=\"RemoveClassList\",e[e.UpdateTextNode=32]=\"UpdateTextNode\",e[e.InsertBoundary=33]=\"InsertBoundary\",e[e.ClearBoundary=34]=\"ClearBoundary\",e[e.AddEventListener=35]=\"AddEventListener\",e[e.ConnectResource=36]=\"ConnectResource\",e[e.SetTimeout=37]=\"SetTimeout\",e[e.ApplyFinalizer=38]=\"ApplyFinalizer\",e[e.RevSeq=39]=\"RevSeq\",e[e.Eval=40]=\"Eval\",e[e.TriggerCallback=41]=\"TriggerCallback\",e[e.UncaughtException=42]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=[window,null],_=58;class a{static read_bytes(e,t){const r=new a;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let _=0;_{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let p,u=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],c.enable(n.debug),this.args=e,this.env=t,this.fds=r;const _=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.args.length,!0);let n=0;for(const e of _.args)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.args.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.args[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},environ_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.env.length,!0);let n=0;for(const e of _.env)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},environ_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.env.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.env[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},clock_res_get(e,t){let r;switch(e){case 1:r=5000n;break;case 0:r=1000000n;break;default:return 52}return new DataView(_.inst.exports.memory.buffer).setBigUint64(t,r,!0),0},clock_time_get(e,t,r){const n=new DataView(_.inst.exports.memory.buffer);if(0===e)n.setBigUint64(r,1000000n*BigInt((new Date).getTime()),!0);else if(1==e){let e;try{e=BigInt(Math.round(1e6*performance.now()))}catch(t){e=0n}n.setBigUint64(r,e,!0)}else n.setBigUint64(r,0n,!0);return 0},fd_advise:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=_.fds[e]){const t=_.fds[e].fd_close();return _.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=_.fds[e]?_.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=_.fds[e]){const{ret:r,fdstat:n}=_.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=_.fds[e]){const{ret:r,filestat:n}=_.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=a.read_bytes_array(i,t,r),{ret:l,nread:p}=_.fds[e].fd_pread(o,c,n);return i.setUint32(s,p,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,prestat:a}=_.fds[e].fd_prestat_get();return null!=a&&a.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=_.fds[e]){const{ret:r,prestat_dir_name:n}=_.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(_.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,a){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=s.read_bytes_array(i,t,r),{ret:l,nwritten:p}=_.fds[e].fd_pwrite(o,c,n);return i.setUint32(a,p,!0),l}return 8},fd_read(e,t,r,n){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=a.read_bytes_array(s,t,r),{ret:c,nread:l}=_.fds[e].fd_read(i,o);return s.setUint32(n,l,!0),c}return 8},fd_readdir(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){let o=0;for(;;){const{ret:c,dirent:l}=_.fds[e].fd_readdir_single(n);if(0!=c)return s.setUint32(a,o,!0),c;if(null==l)break;if(r-onull!=_.fds[e]?_.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,offset:a}=_.fds[e].fd_tell();return r.setBigUint64(t,a,!0),n}return 8},fd_write(e,t,r,n){const a=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=s.read_bytes_array(a,t,r),{ret:c,nwritten:l}=_.fds[e].fd_write(i,o);return a.setUint32(n,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_create_directory(a)}},path_filestat_get(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:c,filestat:l}=_.fds[e].path_filestat_get(t,o);return null!=l&&l.write_bytes(s,a),c}return 8},path_filestat_set_times(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return _.fds[e].path_filestat_set_times(t,c,a,s,i)}return 8},path_link(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]&&null!=_.fds[a]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(o.slice(s,s+i));return _.fds[a].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,a,s,i,o,l){const p=new DataView(_.inst.exports.memory.buffer),u=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const f=new TextDecoder(\"utf-8\").decode(u.slice(r,r+n));c.log(f);const{ret:d,fd_obj:E}=_.fds[e].path_open(t,f,a,s,i,o);if(0!=d)return d;_.fds.push(E);const g=_.fds.length-1;return p.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,a,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(t,t+r));c.log(l);const{ret:p,data:u}=_.fds[e].path_readlink(l);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>a)return i.setUint32(s,0,!0),8;o.set(e,n),i.setUint32(s,e.length,!0)}return p}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_remove_directory(a)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,a){const s=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[r]){const i=new TextDecoder(\"utf-8\").decode(s.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(s.slice(n,n+a));return _.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_unlink_file(a)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(_.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class E{open(e){const t=new d(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new o(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class g{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class b{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)p=globalThis.setImmediate;else{const e=new b;p=(t,...r)=>e.setImmediate(t,...r)}const h=e=>{const t=new g;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>p(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=(t,n)=>{const _=r.bR.encode(t),a=y(e,_);e.wasm_app(a)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(a,[globalThis,null],null,_.expr),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return y(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function y(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let x={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new u([],[],[new d(new E([])),new d(new E([])),new d(new E([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:h(x)});Object.assign(x,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),c=y(x,o);yield a.exports.wasm_app(c),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=y(x,t);x.wasm_app(n)}))}))},startDev:function(_,a=null){const s=new WebSocket(_),i=t=>e(this,void 0,void 0,(function*(){s.send(r.bR.encode(t))}));s.onopen=e=>{const t=r.bp(a),n=r.bR.encode({tag:r.dB.Start,0:t});s.send(n)},s.onmessage=_=>e(this,void 0,void 0,(function*(){const a=yield(s=_.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(s)})));var s;!function(_,a,s){e(this,void 0,void 0,(function*(){switch(_.tag){case r.I4.EvalExpr:{const e=r.wL(s,n,null,_.expr),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:_.threadId};return s(a,null)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(_)}))}(r.sy.decode(a),0,i)})),s.onerror=e=>{console.error(\"WebSocket error:\",e)},s.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>R,D:()=>v,Gk:()=>A,HA:()=>I,HQ:()=>w,In:()=>L,K2:()=>C,PV:()=>j,Sj:()=>B,Tf:()=>V,YE:()=>m,YO:()=>K,Yj:()=>S,b9:()=>W,g1:()=>k,l8:()=>U,tB:()=>H});var n=r(366);class _{encode(e){const t=M(this,e),r=new Uint8Array(t);return h(this,r,0,e),r}decode(e){const[t,r]=O(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{}class E extends _{}class p extends _{}class u extends _{}class f extends _{}class d extends _{}class g extends _{}class b extends _{constructor(e){super(),this._element=e}}class y extends _{constructor(e){super(),this._description=e}}class D extends _{constructor(e){super(),this._alternatives=e}}class x extends _{constructor(e){super(),this._self=e}}class T extends _{constructor(e){super(),this._tuple=e}}function M(e,t){if(e instanceof a)return 1;if(e instanceof s)return 2;if(e instanceof i)return 4;if(e instanceof o)return 8;if(e instanceof c)return 1;if(e instanceof l)return 2;if(e instanceof E)return 4;if(e instanceof p)return 8;if(e instanceof u)return 4;if(e instanceof f)return 8;if(e instanceof g){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof d)return 8+t.length;if(e instanceof b){const r=8;return t.reduce(((t,r)=>t+M(e._element,r)),r)}if(e instanceof y){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+M(e._description[n],r[n])),0)}if(e instanceof D){const r=t;return P(Object.keys(e._alternatives).length)+M(e._alternatives[r.tag],r)}if(e instanceof x)return M(e._self,t);if(e instanceof T){const r=t;return e._tuple.reduce(((e,t,n)=>e+M(t,r[n])),0)}return(0,n.G)(e)}function O(e,t,r){const _=new DataView(t.buffer);if(e instanceof a)return[_.getInt8(r),r+1];if(e instanceof s)return[_.getInt16(r,!0),r+2];if(e instanceof i)return[_.getInt32(r,!0),r+4];if(e instanceof o)return[_.getBigInt64(r,!0),r+8];if(e instanceof c)return[t[r],r+1];if(e instanceof l)return[_.getUint8(r),r+1];if(e instanceof E)return[_.getUint32(r,!0),r+4];if(e instanceof p)return[_.getBigUint64(r,!0),r+8];if(e instanceof u)return[_.getFloat32(r,!0),r+4];if(e instanceof f)return[_.getFloat64(r,!0),r+8];if(e instanceof g){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof d){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof b){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=O(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof D){const n=P(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=O(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof x)return O(e._self,t,r);if(e instanceof T){let n=r;return[e._tuple.map((e=>{const[r,_]=O(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function h(e,t,r,_){const M=new DataView(t.buffer);if(e instanceof a)return M.setInt8(r,_),r+1;if(e instanceof s)return M.setInt16(r,_,!0),r+2;if(e instanceof i)return M.setInt32(r,_,!0),r+4;if(e instanceof o)return M.setBigInt64(r,_,!0),r+8;if(e instanceof c)return M.setUint8(r,_),r+1;if(e instanceof l)return M.setUint16(r,_,!0),r+2;if(e instanceof E)return M.setUint32(r,_,!0),r+4;if(e instanceof p)return M.setBigUint64(r,_,!0),r+8;if(e instanceof u)return M.setFloat32(r,_,!0),r+4;if(e instanceof f)return M.setFloat64(r,_,!0),r+8;if(e instanceof g){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof d){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof b){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=h(e,t,a,n[r])})),a}return(0,n.G)(e)}function P(e){return Math.ceil(Math.log2(e)/8)}const m=new a,U=new s,I=new i,A=new o,w=new c,B=new l,C=new E,v=new p,L=new u,R=new f,S=new g,W=new d;function K(e){return new b(e)}function k(e){return new y(e)}function V(e){return new D(e)}function j(...e){return new T(e)}function H(e){const t=new x(void 0),r=e(t);return t._self=r,r}var N;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(N||(N={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I8:case ExprTag.I16:case ExprTag.I32:case ExprTag.I64:case ExprTag.U8:case ExprTag.U16:case ExprTag.U32:case ExprTag.U64:case ExprTag.F32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function evalUint8Array(e,t,r,n){return evalExpr(e,t,r,expr.decode(n))}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(\"bigint\"==typeof e)return{tag:ValueTag.I64,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.String=12]=\"String\",e[e.Array=13]=\"Array\",e[e.Object=14]=\"Object\",e[e.Uint8Array=15]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ValueTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ValueTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ValueTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ValueTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.String=12]=\"String\",e[e.Array=13]=\"Array\",e[e.Object=14]=\"Object\",e[e.Uint8Array=15]=\"Uint8Array\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Plus=19]=\"Plus\",e[e.Subtract=20]=\"Subtract\",e[e.Multiply=21]=\"Multiply\",e[e.Divide=22]=\"Divide\",e[e.Id=23]=\"Id\",e[e.Lam=24]=\"Lam\",e[e.Arg=25]=\"Arg\",e[e.Apply=26]=\"Apply\",e[e.Call=27]=\"Call\",e[e.AssignVar=28]=\"AssignVar\",e[e.FreeVar=29]=\"FreeVar\",e[e.Var=30]=\"Var\",e[e.FreeScope=31]=\"FreeScope\",e[e.InsertNode=32]=\"InsertNode\",e[e.CreateElement=33]=\"CreateElement\",e[e.CreateElementNS=34]=\"CreateElementNS\",e[e.CreateText=35]=\"CreateText\",e[e.ElementProp=36]=\"ElementProp\",e[e.ElementAttr=37]=\"ElementAttr\",e[e.InsertClassList=38]=\"InsertClassList\",e[e.RemoveClassList=39]=\"RemoveClassList\",e[e.UpdateTextNode=40]=\"UpdateTextNode\",e[e.InsertBoundary=41]=\"InsertBoundary\",e[e.ClearBoundary=42]=\"ClearBoundary\",e[e.AddEventListener=43]=\"AddEventListener\",e[e.ConnectResource=44]=\"ConnectResource\",e[e.SetTimeout=45]=\"SetTimeout\",e[e.ApplyFinalizer=46]=\"ApplyFinalizer\",e[e.RevSeq=47]=\"RevSeq\",e[e.Eval=48]=\"Eval\",e[e.TriggerCallback=49]=\"TriggerCallback\",e[e.UncaughtException=50]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ExprTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ExprTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ExprTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ExprTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=[window,null],_=58;class a{static read_bytes(e,t){const r=new a;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let _=0;_{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let E,p=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],c.enable(n.debug),this.args=e,this.env=t,this.fds=r;const _=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.args.length,!0);let n=0;for(const e of _.args)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.args.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.args[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},environ_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.env.length,!0);let n=0;for(const e of _.env)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},environ_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.env.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.env[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},clock_res_get(e,t){let r;switch(e){case 1:r=5000n;break;case 0:r=1000000n;break;default:return 52}return new DataView(_.inst.exports.memory.buffer).setBigUint64(t,r,!0),0},clock_time_get(e,t,r){const n=new DataView(_.inst.exports.memory.buffer);if(0===e)n.setBigUint64(r,1000000n*BigInt((new Date).getTime()),!0);else if(1==e){let e;try{e=BigInt(Math.round(1e6*performance.now()))}catch(t){e=0n}n.setBigUint64(r,e,!0)}else n.setBigUint64(r,0n,!0);return 0},fd_advise:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=_.fds[e]){const t=_.fds[e].fd_close();return _.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=_.fds[e]?_.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=_.fds[e]){const{ret:r,fdstat:n}=_.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=_.fds[e]){const{ret:r,filestat:n}=_.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=a.read_bytes_array(i,t,r),{ret:l,nread:E}=_.fds[e].fd_pread(o,c,n);return i.setUint32(s,E,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,prestat:a}=_.fds[e].fd_prestat_get();return null!=a&&a.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=_.fds[e]){const{ret:r,prestat_dir_name:n}=_.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(_.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,a){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=s.read_bytes_array(i,t,r),{ret:l,nwritten:E}=_.fds[e].fd_pwrite(o,c,n);return i.setUint32(a,E,!0),l}return 8},fd_read(e,t,r,n){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=a.read_bytes_array(s,t,r),{ret:c,nread:l}=_.fds[e].fd_read(i,o);return s.setUint32(n,l,!0),c}return 8},fd_readdir(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){let o=0;for(;;){const{ret:c,dirent:l}=_.fds[e].fd_readdir_single(n);if(0!=c)return s.setUint32(a,o,!0),c;if(null==l)break;if(r-onull!=_.fds[e]?_.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,offset:a}=_.fds[e].fd_tell();return r.setBigUint64(t,a,!0),n}return 8},fd_write(e,t,r,n){const a=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=s.read_bytes_array(a,t,r),{ret:c,nwritten:l}=_.fds[e].fd_write(i,o);return a.setUint32(n,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_create_directory(a)}},path_filestat_get(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:c,filestat:l}=_.fds[e].path_filestat_get(t,o);return null!=l&&l.write_bytes(s,a),c}return 8},path_filestat_set_times(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return _.fds[e].path_filestat_set_times(t,c,a,s,i)}return 8},path_link(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]&&null!=_.fds[a]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(o.slice(s,s+i));return _.fds[a].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,a,s,i,o,l){const E=new DataView(_.inst.exports.memory.buffer),p=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const u=new TextDecoder(\"utf-8\").decode(p.slice(r,r+n));c.log(u);const{ret:f,fd_obj:d}=_.fds[e].path_open(t,u,a,s,i,o);if(0!=f)return f;_.fds.push(d);const g=_.fds.length-1;return E.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,a,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(t,t+r));c.log(l);const{ret:E,data:p}=_.fds[e].path_readlink(l);if(null!=p){const e=(new TextEncoder).encode(p);if(e.length>a)return i.setUint32(s,0,!0),8;o.set(e,n),i.setUint32(s,e.length,!0)}return E}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_remove_directory(a)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,a){const s=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[r]){const i=new TextDecoder(\"utf-8\").decode(s.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(s.slice(n,n+a));return _.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_unlink_file(a)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(_.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class d{open(e){const t=new f(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new o(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class g{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class b{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)E=globalThis.setImmediate;else{const e=new b;E=(t,...r)=>e.setImmediate(t,...r)}const y=e=>{const t=new g;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>E(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=(t,n)=>{const _=r.bR.encode(t),a=D(e,_);e.wasm_app(a)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(a,[globalThis,null],null,_.expr),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return D(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function D(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let x={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new p([],[],[new f(new d([])),new f(new d([])),new f(new d([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:y(x)});Object.assign(x,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),c=D(x,o);yield a.exports.wasm_app(c),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=D(x,t);x.wasm_app(n)}))}))},startDev:function(_,a=null){const s=new WebSocket(_),i=t=>e(this,void 0,void 0,(function*(){s.send(r.bR.encode(t))}));s.onopen=e=>{const t=r.bp(a),n=r.bR.encode({tag:r.dB.Start,0:t});s.send(n)},s.onmessage=_=>e(this,void 0,void 0,(function*(){const a=yield(s=_.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(s)})));var s;!function(_,a,s){e(this,void 0,void 0,(function*(){switch(_.tag){case r.I4.EvalExpr:{const e=r.wL(s,n,null,_.expr),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:_.threadId};return s(a,null)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(_)}))}(r.sy.decode(a),0,i)})),s.onerror=e=>{console.error(\"WebSocket error:\",e)},s.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" diff --git a/src/Clickable/Main/Wasm.hs b/src/Clickable/Main/Wasm.hs index f606e9d..ebac24e 100644 --- a/src/Clickable/Main/Wasm.hs +++ b/src/Clickable/Main/Wasm.hs @@ -15,8 +15,7 @@ import System.IO.Unsafe import Clickable.FFI qualified as FFI import Clickable.Protocol -import Clickable.Protocol.Value (Value) -import Clickable.Protocol.Value qualified as Value +import Clickable.Protocol.Value import Clickable.Core import Clickable.Internal qualified as Internal import Clickable.Types @@ -30,7 +29,7 @@ runWasm app p = mdo Just (TriggerCallbackMsg arg eid) -> launchClickM internalEnv $ modify $ Internal.triggerEvent (unsafeFromEventId eid) arg Just BeforeUnload -> - launchClickM internalEnv $ freeScope True $ ResourceScope Internal.emptyState.next_id + launchClickM internalEnv $ freeScope True $ ResourceScope $ Int32Le Internal.emptyState.next_id _ -> return () @@ -39,13 +38,13 @@ internalEnv = unsafePerformIO $ Internal.newInternalEnv sendMessage sendMessage :: Expr -> IO Value sendMessage expr = do - hptr <- storeByteString $ BSL.toStrict $ Binary.encode $ EvalExpr 0 expr + hptr <- storeByteString $ BSL.toStrict $ Binary.encode $ EvalExpr (Int32Le 0) expr jptr <- FFI.js_evalMessage hptr Alloc.free hptr jmsg <- loadMessage jptr case jmsg of Just (Return _ v) -> return v - _ -> return Value.Null + _ -> return Vnull where storeByteString :: ByteString -> IO (Ptr a) storeByteString bs = do diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index cd7c946..2f74ea1 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -8,10 +8,10 @@ import Data.String import Data.Word import GHC.Generics -import "this" Clickable.Protocol.Value qualified as Value +import Clickable.Protocol.Value data HaskellMessage - = EvalExpr Value.Int32Le Expr + = EvalExpr Int32Le Expr -- ^ Evaluate expression, expect the result to be returned by -- 'Return' message | HotReload @@ -23,15 +23,15 @@ data HaskellMessage data JavaScriptMessage = Start StartFlags - | Return Value.Int32Le Value.Value - | TriggerCallbackMsg Value.Value EventId + | Return Int32Le Value + | TriggerCallbackMsg Value EventId | BeforeUnload -- ^ Fired from addEventListener("beforeunload") listener. Won't -- work under the DevServer! deriving (Generic, Show) deriving anyclass (Binary) -newtype StartFlags = StartFlags {unStartFlags :: Value.Value} +newtype StartFlags = StartFlags {unStartFlags :: Value} deriving newtype (Generic, Show, Binary) -- | Strict Lambda calculus with arbitrary side-effects, meant to be @@ -39,21 +39,26 @@ newtype StartFlags = StartFlags {unStartFlags :: Value.Value} -- non-blocking execution and minimizing round-trips. data Expr = Null - -- ^ Represents null or undefined values - | Boolean Bool + -- ^ null or undefined values + | Bool Bool -- ^ JavaScript boolean value - | I32 Value.Int32Le - -- ^ JavaScript integer number - | F64 Value.Float64 - -- ^ JavaScript floating point number - | String Text - -- ^ JavaScript string - | Array [Expr] - -- ^ JavaScript array - | Object [(Text, Expr)] - -- ^ JavaScript object - | Uint8Array ByteString - -- ^ Raw byte array + | I8 Int8 + | I16 Int16Le + | I32 Int32Le + | I64 Int64Le + + | U8 Word8 + | U16 Word16Le + | U32 Word32Le + | U64 Word64Le + + | F32 Float32Le + | F64 Float64Le + + | Str Text -- ^ JavaScript string + | Arr [Expr] -- ^ JavaScript array + | Obj [(Text, Expr)] -- ^ JavaScript object + | U8Arr ByteString -- ^ Raw byte array | Dot Expr Text -- ^ Read string property of an object. @(Dot (Id "document") @@ -130,7 +135,7 @@ data Expr -- will be freed with 'FreeScope' | ConnectResource ResourceScope Expr -- ^ Returns FinalizerId - | SetTimeout ResourceScope Expr Value.Int32Le + | SetTimeout ResourceScope Expr Int32Le -- ^ Returns FinalizerId | ApplyFinalizer ResourceScope Expr -- ^ Actuate given finalizer before the ResourceScope is freed @@ -151,32 +156,44 @@ data Expr deriving stock (Generic, Show) deriving anyclass (Binary) -valueToExpr :: Value.Value -> Expr +valueToExpr :: Value -> Expr valueToExpr = \case - Value.Null -> Null - Value.Bool a -> Boolean a - Value.I32 a -> I32 a - Value.F64 a -> F64 a - Value.String a -> String a - Value.Array xs -> Array $ fmap valueToExpr xs - Value.Object kv -> Object $ fmap (\(k, v) -> (k, valueToExpr v)) kv - Value.Uint8Array a -> Uint8Array a - -toExpr :: Value.ToValue a => a -> Expr -toExpr = valueToExpr . Value.toValue - -data VarId = VarId ResourceScope Value.Int32Le + Vnull -> Null + Vbool a -> Bool a + + Vi8 a -> I8 a + Vi16 a -> I16 a + Vi32 a -> I32 a + Vi64 a -> I64 a + + Vu8 a -> U8 a + Vu16 a -> U16 a + Vu32 a -> U32 a + Vu64 a -> U64 a + + Vf64 a -> F64 a + Vf32 a -> F32 a + + Vstr a -> Str a + Varr xs -> Arr $ fmap valueToExpr xs + Vobj kv -> Obj $ fmap (\(k, v) -> (k, valueToExpr v)) kv + Vu8arr a -> U8Arr a + +toExpr :: ToValue a => a -> Expr +toExpr = valueToExpr . toValue + +data VarId = VarId ResourceScope Int32Le deriving stock (Generic, Show, Ord, Eq) deriving anyclass (Binary) -newtype FinalizerId = FinalizerId { unFinalizerId :: Value.Int32Le } - deriving newtype (Show, Num, Ord, Eq, Binary) +newtype FinalizerId = FinalizerId { unFinalizerId :: Int32Le } + deriving newtype (Show, Ord, Eq, Binary) -newtype ResourceScope = ResourceScope {unResourceScope :: Value.Int32Le} - deriving newtype (Show, Num, Ord, Eq, Binary) +newtype ResourceScope = ResourceScope {unResourceScope :: Int32Le} + deriving newtype (Show, Ord, Eq, Binary) -newtype EventId = EventId {unEventId :: Value.Int32Le} - deriving newtype (Show, Num, Ord, Eq, Binary) +newtype EventId = EventId {unEventId :: Int32Le} + deriving newtype (Show, Ord, Eq, Binary) newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} deriving newtype (IsString, Show, Semigroup, Monoid, Binary) diff --git a/src/Clickable/Protocol/Value.hs b/src/Clickable/Protocol/Value.hs index a0cdbe3..0cfd723 100644 --- a/src/Clickable/Protocol/Value.hs +++ b/src/Clickable/Protocol/Value.hs @@ -1,8 +1,8 @@ module Clickable.Protocol.Value where import Data.Binary -import Data.Binary.Put import Data.Binary.Get +import Data.Binary.Put import Data.ByteString import Data.Kind import Data.List qualified as List @@ -13,31 +13,25 @@ import GHC.Generics as G import GHC.Int data Value - = Null - | Bool Bool - | I32 Int32Le - | F64 Float64 - | String Text - | Array [Value] - | Object [(Text, Value)] - | Uint8Array ByteString + = Vnull + | Vbool Bool + | Vi8 Int8 + | Vi16 Int16Le + | Vi32 Int32Le + | Vi64 Int64Le + | Vu8 Word8 + | Vu16 Word16Le + | Vu32 Word32Le + | Vu64 Word64Le + | Vf32 Float32Le + | Vf64 Float64Le + | Vstr Text + | Varr [Value] + | Vobj [(Text, Value)] + | Vu8arr ByteString deriving stock (Generic, Show) deriving anyclass (Binary) -newtype Float64 = Float64 {unFloat64 :: Double} - deriving newtype (Show, Ord, Eq, Floating, RealFloat, Fractional, Num, RealFrac, Real) - -instance Binary Float64 where - put = putDoublele . unFloat64 - get = fmap Float64 getDoublele - -newtype Int32Le = Int32Le {unInt32Le :: Int32} - deriving newtype (Show, Ord, Eq, Num, Real, Integral, Enum, Bounded) - -instance Binary Int32Le where - put = putInt32le . unInt32Le - get = fmap Int32Le getInt32le - class ToValue a where toValue :: a -> Value default toValue :: (Generic a, GToValue (Rep a)) => a -> Value @@ -48,24 +42,35 @@ instance (Generic a, GToValue (Rep a)) => ToValue (Generically a) where instance ToValue Value where toValue = Prelude.id -instance ToValue Bool where toValue = Bool +instance ToValue Bool where toValue = Vbool + +instance ToValue Int8 where toValue = Vi8 +instance ToValue Int16 where toValue = Vi16 . Int16Le +instance ToValue Int32 where toValue = Vi32 . Int32Le +instance ToValue Int64 where toValue = Vi64 . Int64Le -instance ToValue Int32 where toValue = I32 . Int32Le +instance ToValue Word8 where toValue = Vu8 +instance ToValue Word16 where toValue = Vu16 . Word16Le +instance ToValue Word32 where toValue = Vu32 . Word32Le +instance ToValue Word64 where toValue = Vu64 . Word64Le -instance ToValue Double where toValue = F64 . Float64 +instance ToValue Float where toValue = Vf32 . Float32Le +instance ToValue Double where toValue = Vf64 . Float64Le + +instance ToValue Int where toValue = Vi64 . Int64Le . fromIntegral instance ToValue Char where - toValue c = String $ Text.cons c Text.empty + toValue c = Vstr $ Text.cons c Text.empty -instance ToValue Text where toValue = String +instance ToValue Text where toValue = Vstr -instance ToValue ByteString where toValue = Uint8Array +instance ToValue ByteString where toValue = Vu8arr -instance ToValue () where toValue _ = Null +instance ToValue () where toValue _ = Vnull -instance ToValue a => ToValue [a] where toValue = Array . fmap toValue +instance ToValue a => ToValue [a] where toValue = Varr . fmap toValue -instance ToValue a => ToValue (Maybe a) where toValue = maybe Null toValue +instance ToValue a => ToValue (Maybe a) where toValue = maybe Vnull toValue instance (ToValue a, ToValue b) => ToValue (a, b) where toValue (a, b) = toValue [toValue a, toValue b] @@ -85,38 +90,74 @@ instance (Generic a, GFromValue (Rep a)) => FromValue (Generically a) where instance FromValue Value where fromValue = pure instance FromValue Bool where - fromValue = \case Bool a -> Just a; _ -> Nothing + fromValue = \case Vbool a -> Just a; _ -> Nothing + +instance FromValue Int8 where + fromValue (Vi8 j) = Just j + fromValue _ = Nothing + +instance FromValue Int16 where + fromValue (Vi16 j) = Just j.unInt16Le + fromValue _ = Nothing instance FromValue Int32 where fromValue = \case - I32 (Int32Le j) -> Just j - F64 j -> Just $ floor j + Vi32 (Int32Le j) -> Just j + Vf64 j -> Just $ floor j.unFloat64Le _ -> Nothing +instance FromValue Int64 where + fromValue (Vi64 j) = Just j.unInt64Le + fromValue _ = Nothing + +instance FromValue Word8 where + fromValue (Vu8 j) = Just j + fromValue _ = Nothing + +instance FromValue Word16 where + fromValue (Vu16 j) = Just j.unWord16Le + fromValue _ = Nothing + +instance FromValue Word32 where + fromValue (Vu32 j) = Just j.unWord32Le + fromValue _ = Nothing + +instance FromValue Word64 where + fromValue (Vu64 j) = Just j.unWord64Le + fromValue _ = Nothing + +instance FromValue Float where + fromValue (Vf32 j) = Just j.unFloat32Le + fromValue _ = Nothing + instance FromValue Double where fromValue = \case - I32 j -> Just $ fromIntegral j - F64 (Float64 j) -> Just j + Vi32 j -> Just $ fromIntegral j.unInt32Le + Vf64 (Float64Le j) -> Just j _ -> Nothing +instance FromValue Int where + fromValue (Vi64 j) = Just $ fromIntegral j.unInt64Le + fromValue _ = Nothing + instance FromValue Char where fromValue = \case - String a | Just (c, _) <- Text.uncons a -> Just c - | otherwise -> Nothing + Vstr a | Just (c, _) <- Text.uncons a -> Just c + | otherwise -> Nothing _ -> Nothing instance FromValue Text where - fromValue = \case String a -> Just a; _ -> Nothing + fromValue = \case Vstr a -> Just a; _ -> Nothing instance FromValue ByteString where - fromValue = \case Uint8Array a -> Just a; _ -> Nothing + fromValue = \case Vu8arr a -> Just a; _ -> Nothing instance FromValue () where - fromValue = \case Null -> Just (); _ -> Nothing + fromValue = \case Vnull -> Just (); _ -> Nothing instance FromValue a => FromValue [a] where fromValue = \case - Array xs -> Just (mapMaybe fromValue xs) + Varr xs -> Just (mapMaybe fromValue xs) _ -> Nothing instance FromValue a => FromValue (Maybe a) where @@ -143,7 +184,7 @@ instance GFromValue U1 where gFromValue _ = Just U1 instance GFromJSObject (x :*: y) => GFromValue (x :*: y) where - gFromValue (Object kvs) = gFromJSObject kvs + gFromValue (Vobj kvs) = gFromJSObject kvs gFromValue _ = Nothing instance {-# OVERLAPPING #-} FromValue a => GFromValue (S1 s (Rec0 a)) where @@ -157,10 +198,10 @@ instance GToValue f => GToValue (M1 m c f) where gToValue (M1 f) = gToValue f instance GToValue U1 where - gToValue _ = Null + gToValue _ = Vnull instance GToJSObject (x :*: y) => GToValue (x :*: y) where - gToValue (x :*: y) = Object $ gToJSObject (x :*: y) + gToValue (x :*: y) = Vobj $ gToJSObject (x :*: y) instance {-# OVERLAPPING #-} (ToValue a) => GToValue (S1 s (Rec0 a)) where gToValue (M1 (K1 a)) = toValue a @@ -194,3 +235,62 @@ instance {-# OVERLAPPING #-} (FromValue a, Selector s) => GFromJSObject (S1 s (R gFromJSObject kvs = List.lookup key kvs >>= fmap (M1 . K1) . fromValue where key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) +-------------------------------------------------------------------------------- + +newtype Float64Le = Float64Le {unFloat64Le :: Double} + deriving newtype (Show, Ord, Eq) + +instance Binary Float64Le where + put = putDoublele . unFloat64Le + get = fmap Float64Le getDoublele + +newtype Float32Le = Float32Le {unFloat32Le :: Float} + deriving newtype (Show, Ord, Eq) + +instance Binary Float32Le where + put = putFloatle . unFloat32Le + get = fmap Float32Le getFloatle +-------------------------------------------------------------------------------- + +newtype Int16Le = Int16Le {unInt16Le :: Int16} + deriving newtype (Show, Ord, Eq) + +instance Binary Int16Le where + put = putInt16le . unInt16Le + get = fmap Int16Le getInt16le + +newtype Int32Le = Int32Le {unInt32Le :: Int32} + deriving newtype (Show, Ord, Eq) + +instance Binary Int32Le where + put = putInt32le . unInt32Le + get = fmap Int32Le getInt32le + +newtype Int64Le = Int64Le {unInt64Le :: Int64} + deriving newtype (Show, Ord, Eq) + +instance Binary Int64Le where + put = putInt64le . unInt64Le + get = fmap Int64Le getInt64le +-------------------------------------------------------------------------------- + +newtype Word16Le = Word16Le {unWord16Le :: Word16} + deriving newtype (Show, Ord, Eq) + +instance Binary Word16Le where + put = putWord16le . unWord16Le + get = fmap Word16Le getWord16le + +newtype Word32Le = Word32Le {unWord32Le :: Word32} + deriving newtype (Show, Ord, Eq) + +instance Binary Word32Le where + put = putWord32le . unWord32Le + get = fmap Word32Le getWord32le + +newtype Word64Le = Word64Le {unWord64Le :: Word64} + deriving newtype (Show, Ord, Eq) + +instance Binary Word64Le where + put = putWord64le . unWord64Le + get = fmap Word64Le getWord64le diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs index 63cdf6d..51d3dcc 100644 --- a/src/Clickable/Types.hs +++ b/src/Clickable/Types.hs @@ -10,12 +10,13 @@ import Data.Tuple import Data.Map (Map) import GHC.Generics import GHC.Exts +import GHC.Int import Clickable.Protocol -import Clickable.Protocol.Value (Int32Le, Value) +import Clickable.Protocol.Value newtype Event a = Event {unEvent :: EventId} - deriving newtype (Show, Num, Ord, Eq, Binary) + deriving newtype (Show, Ord, Eq, Binary) unsafeFromEventId :: EventId -> Event a unsafeFromEventId = Event @@ -79,7 +80,7 @@ data InternalState = InternalState , finalizers :: [Finalizer] , transaction_queue :: Map EventId (ClickM ()) , evaluation_queue :: [Expr] - , next_id :: Int32Le + , next_id :: Int32 } deriving (Generic) data Subscription a From 3169ce216cce01aaf138be60b6cbef045b6a77f4 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 12 Aug 2024 17:53:28 +0400 Subject: [PATCH 49/64] Rename a few definitions --- jsbits/protocol.ts | 168 ++++++++++++++++++------------------- src/Clickable/Core.hs | 108 ++++++++++++------------ src/Clickable/DOM.hs | 20 ++--- src/Clickable/Main/Dev.hs | 4 +- src/Clickable/Main/Wasm.hs | 2 +- src/Clickable/Protocol.hs | 32 ++++--- 6 files changed, 171 insertions(+), 163 deletions(-) diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index 3083f65..40607bd 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -70,16 +70,16 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc case ExprTag.F64: { return exp[0]; } - case ExprTag.String: { + case ExprTag.Str: { return exp[0]; } - case ExprTag.Array: { + case ExprTag.Arr: { return exp[0].map(evalExpr.bind(undefined, hscb, idenScope, argScope)); } - case ExprTag.Object: { + case ExprTag.Obj: { return Object.fromEntries(exp[0].map(([k, e]) => [k, evalExpr(hscb, idenScope, argScope, e)])); } - case ExprTag.Uint8Array: { + case ExprTag.U8Arr: { return exp[0]; } case ExprTag.Dot: { @@ -282,10 +282,10 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc case ExprTag.Eval: { return eval(exp.rawJavaScript); } - case ExprTag.TriggerCallback: { + case ExprTag.TriggerEvent: { const arg = evalExpr(hscb, idenScope, argScope, exp.arg); const jsMsg: JavaScriptMessage = { - tag: JavaScriptMessageTag.TriggerCallback, + tag: JavaScriptMessageTag.TriggerEventMsg, arg: unknownToValue(arg), callbackId: exp.callbackId, } @@ -305,97 +305,97 @@ export function evalUint8Array(hscb: HaskellCallback, idenScope: List, export function unknownToValue(inp: unknown): Value { if (typeof(inp) === 'boolean') { - return { tag: ValueTag.Boolean, 0: inp ? 1 : 0 }; + return { tag: ValueTag.Vbool, 0: inp ? 1 : 0 }; } if (typeof(inp) === 'number') { if (Number.isInteger(inp)) { - return { tag: ValueTag.I32, 0: inp }; + return { tag: ValueTag.Vi32, 0: inp }; } else { - return { tag: ValueTag.F64, 0: inp }; + return { tag: ValueTag.Vf64, 0: inp }; } } if (typeof(inp) === 'string') { - return { tag: ValueTag.String, 0: inp }; + return { tag: ValueTag.Vstr, 0: inp }; } if (typeof(inp) === 'bigint') { - return { tag: ValueTag.I64, 0: inp }; + return { tag: ValueTag.Vi64, 0: inp }; } if (Array.isArray(inp)) { - return { tag: ValueTag.Array, 0: inp.map(unknownToValue) }; + return { tag: ValueTag.Varr, 0: inp.map(unknownToValue) }; } if (inp instanceof Uint8Array) { - return { tag: ValueTag.Uint8Array, 0: inp }; + return { tag: ValueTag.Vu8arr, 0: inp }; } if (inp === null || inp === undefined) { - return { tag: ValueTag.Null }; + return { tag: ValueTag.Vnull }; } const entries = Object.entries(inp) .map(([k, v]) => [k, unknownToValue(v)] as KV); - return { tag: ValueTag.Object, 0: entries } + return { tag: ValueTag.Vobj, 0: entries } type KV = [string, Value]; } export enum ValueTag { - Null, - Boolean, - I8, - I16, - I32, - I64, - U8, - U16, - U32, - U64, - F32, - F64, - String, - Array, - Object, - Uint8Array, + Vnull, + Vbool, + Vi8, + Vi16, + Vi32, + Vi64, + Vu8, + Vu16, + Vu32, + Vu64, + Vf32, + Vf64, + Vstr, + Varr, + Vobj, + Vu8arr, } export type Value = - | { tag: ValueTag.Null } - | { tag: ValueTag.Boolean, 0: number } - | { tag: ValueTag.I8, 0: number } - | { tag: ValueTag.I16, 0: number } - | { tag: ValueTag.I32, 0: number } - | { tag: ValueTag.I64, 0: bigint } - | { tag: ValueTag.U8, 0: number } - | { tag: ValueTag.U16, 0: number } - | { tag: ValueTag.U32, 0: number } - | { tag: ValueTag.U64, 0: bigint } - | { tag: ValueTag.F32, 0: number } - | { tag: ValueTag.F64, 0: number } - | { tag: ValueTag.String, 0: string } - | { tag: ValueTag.Array, 0: Value[] } - | { tag: ValueTag.Object, 0: [string, Value][] } - | { tag: ValueTag.Uint8Array, 0: Uint8Array } + | { tag: ValueTag.Vnull } + | { tag: ValueTag.Vbool, 0: number } + | { tag: ValueTag.Vi8, 0: number } + | { tag: ValueTag.Vi16, 0: number } + | { tag: ValueTag.Vi32, 0: number } + | { tag: ValueTag.Vi64, 0: bigint } + | { tag: ValueTag.Vu8, 0: number } + | { tag: ValueTag.Vu16, 0: number } + | { tag: ValueTag.Vu32, 0: number } + | { tag: ValueTag.Vu64, 0: bigint } + | { tag: ValueTag.Vf32, 0: number } + | { tag: ValueTag.Vf64, 0: number } + | { tag: ValueTag.Vstr, 0: string } + | { tag: ValueTag.Varr, 0: Value[] } + | { tag: ValueTag.Vobj, 0: [string, Value][] } + | { tag: ValueTag.Vu8arr, 0: Uint8Array } ; export const jvalue = b.recursive(self => b.discriminate({ - [ValueTag.Null]: b.record({ }), - [ValueTag.Boolean]: b.record({ 0: b.int8 }), - - [ValueTag.I8]: b.record({ 0: b.int8 }), - [ValueTag.I16]: b.record({ 0: b.int16 }), - [ValueTag.I32]: b.record({ 0: b.int32 }), - [ValueTag.I64]: b.record({ 0: b.int64 }), - - [ValueTag.U8]: b.record({ 0: b.word8 }), - [ValueTag.U16]: b.record({ 0: b.word16 }), - [ValueTag.U32]: b.record({ 0: b.word32 }), - [ValueTag.U64]: b.record({ 0: b.word64 }), - - [ValueTag.F32]: b.record({ 0: b.float32 }), - [ValueTag.F64]: b.record({ 0: b.float64 }), - - [ValueTag.String]: b.record({ 0: b.string }), - [ValueTag.Array]: b.record({ 0: b.array(self) }), - [ValueTag.Object]: b.record({ 0: b.array(b.tuple(b.string, self)) }), - [ValueTag.Uint8Array]: b.record({ 0: b.u8array }), + [ValueTag.Vnull]: b.record({ }), + [ValueTag.Vbool]: b.record({ 0: b.int8 }), + + [ValueTag.Vi8]: b.record({ 0: b.int8 }), + [ValueTag.Vi16]: b.record({ 0: b.int16 }), + [ValueTag.Vi32]: b.record({ 0: b.int32 }), + [ValueTag.Vi64]: b.record({ 0: b.int64 }), + + [ValueTag.Vu8]: b.record({ 0: b.word8 }), + [ValueTag.Vu16]: b.record({ 0: b.word16 }), + [ValueTag.Vu32]: b.record({ 0: b.word32 }), + [ValueTag.Vu64]: b.record({ 0: b.word64 }), + + [ValueTag.Vf32]: b.record({ 0: b.float32 }), + [ValueTag.Vf64]: b.record({ 0: b.float64 }), + + [ValueTag.Vstr]: b.record({ 0: b.string }), + [ValueTag.Varr]: b.record({ 0: b.array(self) }), + [ValueTag.Vobj]: b.record({ 0: b.array(b.tuple(b.string, self)) }), + [ValueTag.Vu8arr]: b.record({ 0: b.u8array }), })); export enum ExprTag { @@ -415,10 +415,10 @@ export enum ExprTag { F32, F64, - String, - Array, - Object, - Uint8Array, + Str, + Arr, + Obj, + U8Arr, Dot, SetProp, @@ -459,7 +459,7 @@ export enum ExprTag { RevSeq, Eval, - TriggerCallback, + TriggerEvent, UncaughtException, } @@ -480,10 +480,10 @@ export type Expr = | { tag: ExprTag.F32, 0: number } | { tag: ExprTag.F64, 0: number } - | { tag: ExprTag.String, 0: string } - | { tag: ExprTag.Array, 0: Expr[] } - | { tag: ExprTag.Object, 0: [string, Expr][] } - | { tag: ExprTag.Uint8Array, 0: Uint8Array } + | { tag: ExprTag.Str, 0: string } + | { tag: ExprTag.Arr, 0: Expr[] } + | { tag: ExprTag.Obj, 0: [string, Expr][] } + | { tag: ExprTag.U8Arr, 0: Uint8Array } | { tag: ExprTag.Dot, 0: Expr, 1: string } | { tag: ExprTag.SetProp, 0: Expr, 1: string, 2: Expr } @@ -524,7 +524,7 @@ export type Expr = | { tag: ExprTag.RevSeq, exprs: Expr[] } | { tag: ExprTag.Eval, rawJavaScript: string } - | { tag: ExprTag.TriggerCallback, callbackId: number, arg: Expr } + | { tag: ExprTag.TriggerEvent, callbackId: number, arg: Expr } | { tag: ExprTag.UncaughtException, message: string } ; @@ -545,10 +545,10 @@ export const expr = b.recursive(self => b.discriminate({ [ExprTag.F32]: b.record({ 0: b.float32 }), [ExprTag.F64]: b.record({ 0: b.float64 }), - [ExprTag.String]: b.record({ 0: b.string }), - [ExprTag.Array]: b.record({ 0: b.array(self) }), - [ExprTag.Object]: b.record({ 0: b.array(b.tuple(b.string, self)) }), - [ExprTag.Uint8Array]: b.record({ 0: b.u8array }), + [ExprTag.Str]: b.record({ 0: b.string }), + [ExprTag.Arr]: b.record({ 0: b.array(self) }), + [ExprTag.Obj]: b.record({ 0: b.array(b.tuple(b.string, self)) }), + [ExprTag.U8Arr]: b.record({ 0: b.u8array }), [ExprTag.Dot]: b.record({ 0: self, 1: b.string }), [ExprTag.SetProp]: b.record({ 0: self, 1: b.string, 2: self }), @@ -589,7 +589,7 @@ export const expr = b.recursive(self => b.discriminate({ [ExprTag.RevSeq]: b.record({ exprs: b.array(self) }), [ExprTag.Eval]: b.record({ rawJavaScript: b.string }), - [ExprTag.TriggerCallback]: b.record({ callbackId: b.int32, arg: self }), + [ExprTag.TriggerEvent]: b.record({ callbackId: b.int32, arg: self }), [ExprTag.UncaughtException]: b.record({ message: b.string }), })); @@ -608,14 +608,14 @@ export const haskellMessage = b.discriminate({ export enum JavaScriptMessageTag { Start, Return, - TriggerCallback, + TriggerEventMsg, BeforeUnload, } export const javascriptMessage = b.discriminate({ [JavaScriptMessageTag.Start]: b.record({ 0: jvalue }), [JavaScriptMessageTag.Return]: b.record({ threadId: b.int32, value: jvalue }), - [JavaScriptMessageTag.TriggerCallback]: b.record({ arg: jvalue, callbackId: b.int32 }), + [JavaScriptMessageTag.TriggerEventMsg]: b.record({ arg: jvalue, callbackId: b.int32 }), [JavaScriptMessageTag.BeforeUnload]: b.record({}), }); diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index 7932378..cf21fae 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -140,72 +140,72 @@ newCallback k = reactive $ Internal.newCallback k ------------------ el :: Text -> HtmlM a -> HtmlM a -el t ch = lift $ htmlBuilder (CreateElement t) $ evalStateT ch.unHtmlT Nothing +el t = lift . insertHtml (DomBuilder (CreateElement t)) elns :: Text -> Text -> HtmlM a -> HtmlM a -elns ns t ch = lift $ htmlBuilder (CreateElementNS ns t) $ evalStateT ch.unHtmlT Nothing +elns ns t = lift . insertHtml (DomBuilder (CreateElementNS ns t)) property :: ToValue a => Text -> a -> HtmlM () property k v = lift $ modify f where f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = ElementProp (Arg 0 0) k (toExpr v) + expr = ElementProp builderContext k (toExpr v) attribute :: Text -> Text -> HtmlM () attribute k v = lift $ modify f where f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = ElementAttr (Arg 0 0) k v + expr = ElementAttr builderContext k v text :: Text -> HtmlM () text t = lift $ modify f where f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = InsertNode (Arg 0 0) $ CreateTextNode t + expr = InsertNode builderContext $ CreateTextNode t dynText :: DynVal Text -> HtmlM () dynText val = do t <- lift $ readVal val v <- lift $ newVarId lift $ modify $ f v t - lift $ subscribe val $ enqueueExpr . UpdateTextNode (Var v) + lift $ subscribe val $ enqueueExpr . UpdateTextNode (DomBuilder (Var v)) where f v t s = s {evaluation_queue = expr v t : s.evaluation_queue } - expr v t = InsertNode (Arg 0 0) $ AssignVar v $ CreateTextNode t + expr v t = InsertNode builderContext $ AssignVar v $ CreateTextNode t dynProp :: ToValue a => Text -> DynVal a -> HtmlM () dynProp k val = do t <- lift $ readVal val - v <- saveCurrentNode + v <- saveCurrentBuilder lift $ modify $ f t - lift $ subscribe val $ enqueueExpr . ElementProp (Var v) k . toExpr + lift $ subscribe val $ enqueueExpr . ElementProp (DomBuilder (Var v)) k . toExpr where f v s = s {evaluation_queue = expr v : s.evaluation_queue } - expr v = ElementProp (Arg 0 0) k (toExpr v) + expr v = ElementProp builderContext k (toExpr v) dynAttr :: Text -> DynVal Text -> HtmlM () dynAttr k val = do t <- lift $ readVal val - v <- saveCurrentNode + v <- saveCurrentBuilder lift $ modify $ f t - lift $ subscribe val $ enqueueExpr . ElementAttr (Var v) k + lift $ subscribe val $ enqueueExpr . ElementAttr (DomBuilder (Var v)) k where f v s = s {evaluation_queue = expr v : s.evaluation_queue } - expr v = ElementAttr (Arg 0 0) k v + expr v = ElementAttr builderContext k v toggleClass :: Text -> DynVal Bool -> HtmlM () toggleClass className val = do scope <- lift $ asks (.scope) v <- lift $ readVal val - n <- saveCurrentNode + n <- saveCurrentBuilder let initCmd False queue = queue - initCmd True queue = InsertClassList (Arg 0 0) [className] : queue - updateCmd False = RemoveClassList (Var n) [className] - updateCmd True = InsertClassList (Var n) [className] + initCmd True queue = InsertClassList builderContext [className] : queue + updateCmd False = RemoveClassList (DomBuilder (Var n)) [className] + updateCmd True = InsertClassList (DomBuilder (Var n)) [className] lift $ modify \s -> s {evaluation_queue = initCmd v s.evaluation_queue} lift $ subscribe val $ enqueueExpr . updateCmd dynClassList :: DynVal [Text] -> HtmlM () dynClassList dynList = do - n <- saveCurrentNode + n <- saveCurrentBuilder scope <- lift $ asks (.scope) initVal <- lift $ readVal dynList let @@ -218,13 +218,16 @@ dynClassList dynList = do modQueue $ updateCmd (added, removed, newList) return (added, removed, newList) updateCmd ([], [], _) queue = queue - updateCmd (added, [], _) queue = InsertClassList (Var n) added : queue - updateCmd ([], removed, _) queue = RemoveClassList (Var n) removed : queue - updateCmd (added, removed, _) queue = RemoveClassList (Var n) removed : InsertClassList (Var n) added : queue + updateCmd (added, [], _) queue = + InsertClassList (DomBuilder (Var n)) added : queue + updateCmd ([], removed, _) queue = + RemoveClassList (DomBuilder (Var n)) removed : queue + updateCmd (added, removed, _) queue = + RemoveClassList (DomBuilder (Var n)) removed : InsertClassList (DomBuilder (Var n)) added : queue modQueue f = modify \s -> s { evaluation_queue = f s.evaluation_queue } - lift $ enqueueExpr $ InsertClassList (Arg 0 0) initVal + lift $ enqueueExpr $ InsertClassList builderContext initVal lift $ Internal.subscribeAccum dynList k ([], [], initVal) --------------------- @@ -240,8 +243,8 @@ dyn val = do update html = do lift $ clearBoundary boundary html - exec h = evalStateT h.unHtmlT Nothing - & htmlBuilder1 (Var boundary) + exec h = + customizeHtml (DomBuilder (Var boundary)) h & local (\s -> s {scope}) lift $ exec $ update initialVal lift $ subscribe val $ \newVal -> do @@ -269,10 +272,10 @@ simpleList listDyn h = lift do internalStateRef <- liftIO $ newIORef ([] :: [ElemEnv a]) boundary <- insertBoundary let - exec boundary scope h = evalStateT h.unHtmlT Nothing - & htmlBuilder1 (Var boundary) + exec boundary scope h = + customizeHtml (DomBuilder (Var boundary)) h & local (\s -> s {scope}) - exec1 boundary = htmlBuilder1 (Var boundary) + exec1 boundary = customizeHtml (DomBuilder (Var boundary)) setup :: Int -> [a] -> [ElemEnv a] -> ClickM [ElemEnv a] setup idx new existing = case (existing, new) of @@ -307,65 +310,65 @@ simpleList listDyn h = lift do newEenvs <- setup 0 new eenvs liftIO $ writeIORef internalStateRef newEenvs initialVal <- readVal listDyn - exec1 boundary $ updateList initialVal - subscribe listDyn $ exec1 boundary . updateList + exec1 boundary $ lift $ updateList initialVal + subscribe listDyn $ exec1 boundary . lift . updateList ---------------------------- -- AUXILLIARY DEFINITIONS -- ---------------------------- -htmlBuilder :: Expr -> ClickM a -> ClickM a -htmlBuilder builder content = do +insertHtml :: DomBuilder -> HtmlM a -> ClickM a +insertHtml builder content = do prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - result <- content - let mkExpr revSeq = InsertNode (Arg 0 0) (Lam (RevSeq (Arg 0 0 : revSeq)) `Apply` [builder]) + result <- evalStateT content.unHtmlT Nothing + let mkExpr revSeq = InsertNode builderContext (Lam (RevSeq (Arg 0 0 : revSeq)) `Apply` [builder.unDomBuilder]) modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} return result -htmlBuilder1 :: Expr -> ClickM a -> ClickM a -htmlBuilder1 builder content = do +customizeHtml :: DomBuilder -> HtmlM a -> ClickM a +customizeHtml builder content = do prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - result <- content - let mkExpr revSeq = Apply (Lam (RevSeq (Arg 0 0 : revSeq))) [builder] + result <- evalStateT content.unHtmlT Nothing + let mkExpr revSeq = Lam (RevSeq (Arg 0 0 : revSeq)) `Apply` [builder.unDomBuilder] modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} return result -saveCurrentNode :: HtmlM VarId -saveCurrentNode = do +saveCurrentBuilder :: HtmlM VarId +saveCurrentBuilder = do alreadySaved <- HtmlT get case alreadySaved of Nothing -> do varId <- lift newVarId HtmlT $ put $ Just varId - lift $ enqueueExpr $ AssignVar varId (Arg 0 0) + lift $ enqueueExpr $ AssignVar varId builderContext.unDomBuilder return varId Just saved -> return saved insertBoundary :: ClickM VarId insertBoundary = do boundary <- newVarId - enqueueExpr $ AssignVar boundary (InsertBoundary (Arg 0 0)) + enqueueExpr $ AssignVar boundary (InsertBoundary builderContext) return boundary clearBoundary :: VarId -> ClickM () -clearBoundary boundary = enqueueExpr (ClearBoundary (Var boundary) False) +clearBoundary boundary = enqueueExpr (ClearBoundary (DomBuilder (Var boundary)) False) destroyBoundary :: VarId -> ClickM () -destroyBoundary boundary = enqueueExpr (ClearBoundary (Var boundary) True) +destroyBoundary boundary = enqueueExpr (ClearBoundary (DomBuilder (Var boundary)) True) -attachHtml :: Expr -> HtmlM a -> ClickM a -attachHtml rootElm contents = do +attachHtml :: DomBuilder -> HtmlM a -> ClickM a +attachHtml rootEl contents = do savedQueue <- state saveQueue evalStateT contents.unHtmlT Nothing <* modify (enqueueHtml savedQueue) where enqueueHtml saved s = s {evaluation_queue = e : saved} where - e = Lam (RevSeq (Arg 0 0 : s.evaluation_queue)) `Apply` [rootElm] + e = Lam (RevSeq (Arg 0 0 : s.evaluation_queue)) `Apply` [rootEl.unDomBuilder] saveQueue s = (s.evaluation_queue, s {evaluation_queue = []}) attachToBody :: HtmlM a -> ClickM a -attachToBody = attachHtml (Id "document" `Dot` "body") +attachToBody = attachHtml (DomBuilder (Id "document" `Dot` "body")) blank :: Applicative m => m () blank = pure () @@ -387,13 +390,12 @@ unsafeHtml rawHtml = lift $ enqueueExpr (Internal.unsafeInsertHtml rawHtml) -- supposed to go given the cotext it used in. Might be useful for -- implementing modal dialogs, tooltips etc. Similar to what called -- portals in React ecosystem -portal :: Expr -> HtmlM a -> HtmlM a +portal :: DomBuilder -> HtmlM a -> HtmlM a portal newRootEl html = - lift $ htmlBuilder1 newRootEl do - boundary <- insertBoundary - result <- htmlBuilder1 (Var boundary) $ - evalStateT html.unHtmlT Nothing - installFinalizer $ destroyBoundary boundary + lift $ customizeHtml newRootEl do + boundary <- lift $ insertBoundary + result <- lift $ customizeHtml (DomBuilder (Var boundary)) html + lift $ installFinalizer $ destroyBoundary boundary return result instance (a ~ ()) => IsString (HtmlM a) where diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index c1189d2..729dc33 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -123,7 +123,7 @@ eventListenerOptions :: Text -> Bool -> Bool -> ConnectResourceArgs (ClickM ()) eventListenerOptions eventName preventDef stopProp = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval (normalEventWrapper eventName $ EventListenerOptions preventDef stopProp) - `Apply` [Arg 0 0, Lam (TriggerCallback sourceId Null)] + `Apply` [Arg 0 0, Lam (TriggerEvent sourceId Null)] , mk_callback = \k _ -> k } @@ -132,7 +132,7 @@ pointerConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) pointerConnectArgs eventName = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval (normalEventWrapper eventName defaultEventListenerOptions) - `Apply` [Arg 0 0, Lam (TriggerCallback sourceId Null)] + `Apply` [Arg 0 0, Lam (TriggerEvent sourceId Null)] , mk_callback = \k _ -> k } @@ -143,7 +143,7 @@ submitConnectArgs = ConnectResourceArgs Eval (normalEventWrapper "submit" EventListenerOptions { prevent_default = True , stop_propagation = True - }) `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + }) `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] , mk_callback = \k _ -> k } @@ -157,7 +157,7 @@ inputConnectArgs eventName = ConnectResourceArgs \ }\n\ \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => window.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + \})") `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromValue event) k } @@ -172,7 +172,7 @@ keyboardConnectArgs eventName = ConnectResourceArgs \ }\n\ \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + \})") `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromValue event) k } @@ -184,7 +184,7 @@ focusConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) focusConnectArgs eventName = ConnectResourceArgs { aquire_resource = \scope sourceId -> Eval (normalEventWrapper eventName defaultEventListenerOptions) - `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] , mk_callback = \k _ -> k } @@ -198,7 +198,7 @@ checkboxChangeConnectArgs = ConnectResourceArgs \ }\n\ \ target.addEventListener('change', listener);\n\ \ return () => window.removeEventListener('change', listener);\n\ - \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + \})" `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromValue event) k } @@ -212,7 +212,7 @@ selectChangeConnectArgs = ConnectResourceArgs \ }\n\ \ target.addEventListener('change', listener);\n\ \ return () => target.removeEventListener('change', listener);\n\ - \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + \})" `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromValue event) k } @@ -268,7 +268,7 @@ popstateConnectArgs = ConnectResourceArgs \ }\n\ \ target.addEventListener('popstate', listener);\n\ \ return () => target.removeEventListener('popstate', listener);\n\ - \})" `Apply` [Id "window", Lam (TriggerCallback sourceId (Arg 0 0))] + \})" `Apply` [Id "window", Lam (TriggerEvent sourceId (Arg 0 0))] , mk_callback = \k event -> forM_ (fromValue event) k } @@ -304,5 +304,5 @@ mouseWheelConnectArgs = ConnectResourceArgs \ }\n\ \ target.addEventListener('popstate', listener);\n\ \ return () => target.removeEventListener('popstate', listener);\n\ - \})" `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] + \})" `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] } diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index ae35e84..04dbc04 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -203,7 +203,7 @@ websocketApp opt p = swap . Map.alterF (,Nothing) (fromIntegral tid.unInt32Le) forM_ mmvar \mvar -> void $ tryPutMVar mvar val - BrowserMessage (TriggerCallbackMsg arg eid) -> void $ forkIO + BrowserMessage (TriggerEventMsg arg eid) -> void $ forkIO $ Internal.launchClickM conn.internal_env $ modify (Internal.triggerEvent (unsafeFromEventId eid) arg) BrowserMessage BeforeUnload -> @@ -318,4 +318,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>R,D:()=>v,Gk:()=>A,HA:()=>I,HQ:()=>w,In:()=>L,K2:()=>C,PV:()=>j,Sj:()=>B,Tf:()=>V,YE:()=>m,YO:()=>K,Yj:()=>S,b9:()=>W,g1:()=>k,l8:()=>U,tB:()=>H});var n=r(366);class _{encode(e){const t=M(this,e),r=new Uint8Array(t);return h(this,r,0,e),r}decode(e){const[t,r]=O(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{}class E extends _{}class p extends _{}class u extends _{}class f extends _{}class d extends _{}class g extends _{}class b extends _{constructor(e){super(),this._element=e}}class y extends _{constructor(e){super(),this._description=e}}class D extends _{constructor(e){super(),this._alternatives=e}}class x extends _{constructor(e){super(),this._self=e}}class T extends _{constructor(e){super(),this._tuple=e}}function M(e,t){if(e instanceof a)return 1;if(e instanceof s)return 2;if(e instanceof i)return 4;if(e instanceof o)return 8;if(e instanceof c)return 1;if(e instanceof l)return 2;if(e instanceof E)return 4;if(e instanceof p)return 8;if(e instanceof u)return 4;if(e instanceof f)return 8;if(e instanceof g){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof d)return 8+t.length;if(e instanceof b){const r=8;return t.reduce(((t,r)=>t+M(e._element,r)),r)}if(e instanceof y){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+M(e._description[n],r[n])),0)}if(e instanceof D){const r=t;return P(Object.keys(e._alternatives).length)+M(e._alternatives[r.tag],r)}if(e instanceof x)return M(e._self,t);if(e instanceof T){const r=t;return e._tuple.reduce(((e,t,n)=>e+M(t,r[n])),0)}return(0,n.G)(e)}function O(e,t,r){const _=new DataView(t.buffer);if(e instanceof a)return[_.getInt8(r),r+1];if(e instanceof s)return[_.getInt16(r,!0),r+2];if(e instanceof i)return[_.getInt32(r,!0),r+4];if(e instanceof o)return[_.getBigInt64(r,!0),r+8];if(e instanceof c)return[t[r],r+1];if(e instanceof l)return[_.getUint8(r),r+1];if(e instanceof E)return[_.getUint32(r,!0),r+4];if(e instanceof p)return[_.getBigUint64(r,!0),r+8];if(e instanceof u)return[_.getFloat32(r,!0),r+4];if(e instanceof f)return[_.getFloat64(r,!0),r+8];if(e instanceof g){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof d){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof b){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=O(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof D){const n=P(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=O(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof x)return O(e._self,t,r);if(e instanceof T){let n=r;return[e._tuple.map((e=>{const[r,_]=O(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function h(e,t,r,_){const M=new DataView(t.buffer);if(e instanceof a)return M.setInt8(r,_),r+1;if(e instanceof s)return M.setInt16(r,_,!0),r+2;if(e instanceof i)return M.setInt32(r,_,!0),r+4;if(e instanceof o)return M.setBigInt64(r,_,!0),r+8;if(e instanceof c)return M.setUint8(r,_),r+1;if(e instanceof l)return M.setUint16(r,_,!0),r+2;if(e instanceof E)return M.setUint32(r,_,!0),r+4;if(e instanceof p)return M.setBigUint64(r,_,!0),r+8;if(e instanceof u)return M.setFloat32(r,_,!0),r+4;if(e instanceof f)return M.setFloat64(r,_,!0),r+8;if(e instanceof g){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof d){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof b){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=h(e,t,a,n[r])})),a}return(0,n.G)(e)}function P(e){return Math.ceil(Math.log2(e)/8)}const m=new a,U=new s,I=new i,A=new o,w=new c,B=new l,C=new E,v=new p,L=new u,R=new f,S=new g,W=new d;function K(e){return new b(e)}function k(e){return new y(e)}function V(e){return new D(e)}function j(...e){return new T(e)}function H(e){const t=new x(void 0),r=e(t);return t._self=r,r}var N;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(N||(N={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I8:case ExprTag.I16:case ExprTag.I32:case ExprTag.I64:case ExprTag.U8:case ExprTag.U16:case ExprTag.U32:case ExprTag.U64:case ExprTag.F32:case ExprTag.F64:case ExprTag.String:return exp[0];case ExprTag.Array:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Object:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.Uint8Array:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerCallback:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerCallback,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function evalUint8Array(e,t,r,n){return evalExpr(e,t,r,expr.decode(n))}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Boolean,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.I32,0:e}:{tag:ValueTag.F64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.String,0:e};if(\"bigint\"==typeof e)return{tag:ValueTag.I64,0:e};if(Array.isArray(e))return{tag:ValueTag.Array,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Uint8Array,0:e};if(null==e)return{tag:ValueTag.Null};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Object,0:t}}!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.String=12]=\"String\",e[e.Array=13]=\"Array\",e[e.Object=14]=\"Object\",e[e.Uint8Array=15]=\"Uint8Array\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ValueTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ValueTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ValueTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ValueTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ValueTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ValueTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.String=12]=\"String\",e[e.Array=13]=\"Array\",e[e.Object=14]=\"Object\",e[e.Uint8Array=15]=\"Uint8Array\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Plus=19]=\"Plus\",e[e.Subtract=20]=\"Subtract\",e[e.Multiply=21]=\"Multiply\",e[e.Divide=22]=\"Divide\",e[e.Id=23]=\"Id\",e[e.Lam=24]=\"Lam\",e[e.Arg=25]=\"Arg\",e[e.Apply=26]=\"Apply\",e[e.Call=27]=\"Call\",e[e.AssignVar=28]=\"AssignVar\",e[e.FreeVar=29]=\"FreeVar\",e[e.Var=30]=\"Var\",e[e.FreeScope=31]=\"FreeScope\",e[e.InsertNode=32]=\"InsertNode\",e[e.CreateElement=33]=\"CreateElement\",e[e.CreateElementNS=34]=\"CreateElementNS\",e[e.CreateText=35]=\"CreateText\",e[e.ElementProp=36]=\"ElementProp\",e[e.ElementAttr=37]=\"ElementAttr\",e[e.InsertClassList=38]=\"InsertClassList\",e[e.RemoveClassList=39]=\"RemoveClassList\",e[e.UpdateTextNode=40]=\"UpdateTextNode\",e[e.InsertBoundary=41]=\"InsertBoundary\",e[e.ClearBoundary=42]=\"ClearBoundary\",e[e.AddEventListener=43]=\"AddEventListener\",e[e.ConnectResource=44]=\"ConnectResource\",e[e.SetTimeout=45]=\"SetTimeout\",e[e.ApplyFinalizer=46]=\"ApplyFinalizer\",e[e.RevSeq=47]=\"RevSeq\",e[e.Eval=48]=\"Eval\",e[e.TriggerCallback=49]=\"TriggerCallback\",e[e.UncaughtException=50]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ExprTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ExprTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ExprTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ExprTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.String]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Object]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.Uint8Array]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerCallback=2]=\"TriggerCallback\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerCallback]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=[window,null],_=58;class a{static read_bytes(e,t){const r=new a;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let _=0;_{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let E,p=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],c.enable(n.debug),this.args=e,this.env=t,this.fds=r;const _=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.args.length,!0);let n=0;for(const e of _.args)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.args.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.args[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},environ_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.env.length,!0);let n=0;for(const e of _.env)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},environ_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.env.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.env[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},clock_res_get(e,t){let r;switch(e){case 1:r=5000n;break;case 0:r=1000000n;break;default:return 52}return new DataView(_.inst.exports.memory.buffer).setBigUint64(t,r,!0),0},clock_time_get(e,t,r){const n=new DataView(_.inst.exports.memory.buffer);if(0===e)n.setBigUint64(r,1000000n*BigInt((new Date).getTime()),!0);else if(1==e){let e;try{e=BigInt(Math.round(1e6*performance.now()))}catch(t){e=0n}n.setBigUint64(r,e,!0)}else n.setBigUint64(r,0n,!0);return 0},fd_advise:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=_.fds[e]){const t=_.fds[e].fd_close();return _.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=_.fds[e]?_.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=_.fds[e]){const{ret:r,fdstat:n}=_.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=_.fds[e]){const{ret:r,filestat:n}=_.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=a.read_bytes_array(i,t,r),{ret:l,nread:E}=_.fds[e].fd_pread(o,c,n);return i.setUint32(s,E,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,prestat:a}=_.fds[e].fd_prestat_get();return null!=a&&a.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=_.fds[e]){const{ret:r,prestat_dir_name:n}=_.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(_.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,a){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=s.read_bytes_array(i,t,r),{ret:l,nwritten:E}=_.fds[e].fd_pwrite(o,c,n);return i.setUint32(a,E,!0),l}return 8},fd_read(e,t,r,n){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=a.read_bytes_array(s,t,r),{ret:c,nread:l}=_.fds[e].fd_read(i,o);return s.setUint32(n,l,!0),c}return 8},fd_readdir(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){let o=0;for(;;){const{ret:c,dirent:l}=_.fds[e].fd_readdir_single(n);if(0!=c)return s.setUint32(a,o,!0),c;if(null==l)break;if(r-onull!=_.fds[e]?_.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,offset:a}=_.fds[e].fd_tell();return r.setBigUint64(t,a,!0),n}return 8},fd_write(e,t,r,n){const a=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=s.read_bytes_array(a,t,r),{ret:c,nwritten:l}=_.fds[e].fd_write(i,o);return a.setUint32(n,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_create_directory(a)}},path_filestat_get(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:c,filestat:l}=_.fds[e].path_filestat_get(t,o);return null!=l&&l.write_bytes(s,a),c}return 8},path_filestat_set_times(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return _.fds[e].path_filestat_set_times(t,c,a,s,i)}return 8},path_link(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]&&null!=_.fds[a]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(o.slice(s,s+i));return _.fds[a].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,a,s,i,o,l){const E=new DataView(_.inst.exports.memory.buffer),p=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const u=new TextDecoder(\"utf-8\").decode(p.slice(r,r+n));c.log(u);const{ret:f,fd_obj:d}=_.fds[e].path_open(t,u,a,s,i,o);if(0!=f)return f;_.fds.push(d);const g=_.fds.length-1;return E.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,a,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(t,t+r));c.log(l);const{ret:E,data:p}=_.fds[e].path_readlink(l);if(null!=p){const e=(new TextEncoder).encode(p);if(e.length>a)return i.setUint32(s,0,!0),8;o.set(e,n),i.setUint32(s,e.length,!0)}return E}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_remove_directory(a)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,a){const s=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[r]){const i=new TextDecoder(\"utf-8\").decode(s.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(s.slice(n,n+a));return _.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_unlink_file(a)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(_.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class d{open(e){const t=new f(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new o(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class g{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class b{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)E=globalThis.setImmediate;else{const e=new b;E=(t,...r)=>e.setImmediate(t,...r)}const y=e=>{const t=new g;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>E(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=(t,n)=>{const _=r.bR.encode(t),a=D(e,_);e.wasm_app(a)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(a,[globalThis,null],null,_.expr),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return D(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function D(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let x={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new p([],[],[new f(new d([])),new f(new d([])),new f(new d([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:y(x)});Object.assign(x,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),c=D(x,o);yield a.exports.wasm_app(c),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=D(x,t);x.wasm_app(n)}))}))},startDev:function(_,a=null){const s=new WebSocket(_),i=t=>e(this,void 0,void 0,(function*(){s.send(r.bR.encode(t))}));s.onopen=e=>{const t=r.bp(a),n=r.bR.encode({tag:r.dB.Start,0:t});s.send(n)},s.onmessage=_=>e(this,void 0,void 0,(function*(){const a=yield(s=_.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(s)})));var s;!function(_,a,s){e(this,void 0,void 0,(function*(){switch(_.tag){case r.I4.EvalExpr:{const e=r.wL(s,n,null,_.expr),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:_.threadId};return s(a,null)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(_)}))}(r.sy.decode(a),0,i)})),s.onerror=e=>{console.error(\"WebSocket error:\",e)},s.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>R,D:()=>C,Gk:()=>A,HA:()=>U,HQ:()=>w,In:()=>L,K2:()=>v,PV:()=>j,Sj:()=>B,Tf:()=>k,YE:()=>m,YO:()=>K,Yj:()=>S,b9:()=>W,g1:()=>V,l8:()=>I,tB:()=>H});var n=r(366);class _{encode(e){const t=M(this,e),r=new Uint8Array(t);return O(this,r,0,e),r}decode(e){const[t,r]=h(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{}class E extends _{}class p extends _{}class u extends _{}class f extends _{}class d extends _{}class g extends _{}class b extends _{constructor(e){super(),this._element=e}}class D extends _{constructor(e){super(),this._description=e}}class x extends _{constructor(e){super(),this._alternatives=e}}class y extends _{constructor(e){super(),this._self=e}}class T extends _{constructor(e){super(),this._tuple=e}}function M(e,t){if(e instanceof a)return 1;if(e instanceof s)return 2;if(e instanceof i)return 4;if(e instanceof o)return 8;if(e instanceof c)return 1;if(e instanceof l)return 2;if(e instanceof E)return 4;if(e instanceof p)return 8;if(e instanceof u)return 4;if(e instanceof f)return 8;if(e instanceof g){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof d)return 8+t.length;if(e instanceof b){const r=8;return t.reduce(((t,r)=>t+M(e._element,r)),r)}if(e instanceof D){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+M(e._description[n],r[n])),0)}if(e instanceof x){const r=t;return P(Object.keys(e._alternatives).length)+M(e._alternatives[r.tag],r)}if(e instanceof y)return M(e._self,t);if(e instanceof T){const r=t;return e._tuple.reduce(((e,t,n)=>e+M(t,r[n])),0)}return(0,n.G)(e)}function h(e,t,r){const _=new DataView(t.buffer);if(e instanceof a)return[_.getInt8(r),r+1];if(e instanceof s)return[_.getInt16(r,!0),r+2];if(e instanceof i)return[_.getInt32(r,!0),r+4];if(e instanceof o)return[_.getBigInt64(r,!0),r+8];if(e instanceof c)return[t[r],r+1];if(e instanceof l)return[_.getUint8(r),r+1];if(e instanceof E)return[_.getUint32(r,!0),r+4];if(e instanceof p)return[_.getBigUint64(r,!0),r+8];if(e instanceof u)return[_.getFloat32(r,!0),r+4];if(e instanceof f)return[_.getFloat64(r,!0),r+8];if(e instanceof g){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof d){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof b){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=h(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof x){const n=P(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=h(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof y)return h(e._self,t,r);if(e instanceof T){let n=r;return[e._tuple.map((e=>{const[r,_]=h(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function O(e,t,r,_){const M=new DataView(t.buffer);if(e instanceof a)return M.setInt8(r,_),r+1;if(e instanceof s)return M.setInt16(r,_,!0),r+2;if(e instanceof i)return M.setInt32(r,_,!0),r+4;if(e instanceof o)return M.setBigInt64(r,_,!0),r+8;if(e instanceof c)return M.setUint8(r,_),r+1;if(e instanceof l)return M.setUint16(r,_,!0),r+2;if(e instanceof E)return M.setUint32(r,_,!0),r+4;if(e instanceof p)return M.setBigUint64(r,_,!0),r+8;if(e instanceof u)return M.setFloat32(r,_,!0),r+4;if(e instanceof f)return M.setFloat64(r,_,!0),r+8;if(e instanceof g){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof d){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof b){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=O(e,t,a,n[r])})),a}return(0,n.G)(e)}function P(e){return Math.ceil(Math.log2(e)/8)}const m=new a,I=new s,U=new i,A=new o,w=new c,B=new l,v=new E,C=new p,L=new u,R=new f,S=new g,W=new d;function K(e){return new b(e)}function V(e){return new D(e)}function k(e){return new x(e)}function j(...e){return new T(e)}function H(e){const t=new y(void 0),r=e(t);return t._self=r,r}var N;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(N||(N={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I8:case ExprTag.I16:case ExprTag.I32:case ExprTag.I64:case ExprTag.U8:case ExprTag.U16:case ExprTag.U32:case ExprTag.U64:case ExprTag.F32:case ExprTag.F64:case ExprTag.Str:return exp[0];case ExprTag.Arr:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Obj:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.U8Arr:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerEvent:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerEventMsg,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function evalUint8Array(e,t,r,n){return evalExpr(e,t,r,expr.decode(n))}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Vbool,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.Vi32,0:e}:{tag:ValueTag.Vf64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.Vstr,0:e};if(\"bigint\"==typeof e)return{tag:ValueTag.Vi64,0:e};if(Array.isArray(e))return{tag:ValueTag.Varr,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Vu8arr,0:e};if(null==e)return{tag:ValueTag.Vnull};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Vobj,0:t}}!function(e){e[e.Vnull=0]=\"Vnull\",e[e.Vbool=1]=\"Vbool\",e[e.Vi8=2]=\"Vi8\",e[e.Vi16=3]=\"Vi16\",e[e.Vi32=4]=\"Vi32\",e[e.Vi64=5]=\"Vi64\",e[e.Vu8=6]=\"Vu8\",e[e.Vu16=7]=\"Vu16\",e[e.Vu32=8]=\"Vu32\",e[e.Vu64=9]=\"Vu64\",e[e.Vf32=10]=\"Vf32\",e[e.Vf64=11]=\"Vf64\",e[e.Vstr=12]=\"Vstr\",e[e.Varr=13]=\"Varr\",e[e.Vobj=14]=\"Vobj\",e[e.Vu8arr=15]=\"Vu8arr\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Vnull]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Vbool]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ValueTag.Vi32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.Vi64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.Vu8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ValueTag.Vu16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ValueTag.Vu32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ValueTag.Vu64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ValueTag.Vf32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ValueTag.Vf64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.Vstr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Varr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Vobj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Vu8arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Plus=19]=\"Plus\",e[e.Subtract=20]=\"Subtract\",e[e.Multiply=21]=\"Multiply\",e[e.Divide=22]=\"Divide\",e[e.Id=23]=\"Id\",e[e.Lam=24]=\"Lam\",e[e.Arg=25]=\"Arg\",e[e.Apply=26]=\"Apply\",e[e.Call=27]=\"Call\",e[e.AssignVar=28]=\"AssignVar\",e[e.FreeVar=29]=\"FreeVar\",e[e.Var=30]=\"Var\",e[e.FreeScope=31]=\"FreeScope\",e[e.InsertNode=32]=\"InsertNode\",e[e.CreateElement=33]=\"CreateElement\",e[e.CreateElementNS=34]=\"CreateElementNS\",e[e.CreateText=35]=\"CreateText\",e[e.ElementProp=36]=\"ElementProp\",e[e.ElementAttr=37]=\"ElementAttr\",e[e.InsertClassList=38]=\"InsertClassList\",e[e.RemoveClassList=39]=\"RemoveClassList\",e[e.UpdateTextNode=40]=\"UpdateTextNode\",e[e.InsertBoundary=41]=\"InsertBoundary\",e[e.ClearBoundary=42]=\"ClearBoundary\",e[e.AddEventListener=43]=\"AddEventListener\",e[e.ConnectResource=44]=\"ConnectResource\",e[e.SetTimeout=45]=\"SetTimeout\",e[e.ApplyFinalizer=46]=\"ApplyFinalizer\",e[e.RevSeq=47]=\"RevSeq\",e[e.Eval=48]=\"Eval\",e[e.TriggerEvent=49]=\"TriggerEvent\",e[e.UncaughtException=50]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ExprTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ExprTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ExprTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ExprTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.Str]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Obj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.U8Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerEventMsg=2]=\"TriggerEventMsg\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerEventMsg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=[window,null],_=58;class a{static read_bytes(e,t){const r=new a;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let _=0;_{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let E,p=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],c.enable(n.debug),this.args=e,this.env=t,this.fds=r;const _=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.args.length,!0);let n=0;for(const e of _.args)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.args.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.args[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},environ_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.env.length,!0);let n=0;for(const e of _.env)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},environ_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.env.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.env[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},clock_res_get(e,t){let r;switch(e){case 1:r=5000n;break;case 0:r=1000000n;break;default:return 52}return new DataView(_.inst.exports.memory.buffer).setBigUint64(t,r,!0),0},clock_time_get(e,t,r){const n=new DataView(_.inst.exports.memory.buffer);if(0===e)n.setBigUint64(r,1000000n*BigInt((new Date).getTime()),!0);else if(1==e){let e;try{e=BigInt(Math.round(1e6*performance.now()))}catch(t){e=0n}n.setBigUint64(r,e,!0)}else n.setBigUint64(r,0n,!0);return 0},fd_advise:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=_.fds[e]){const t=_.fds[e].fd_close();return _.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=_.fds[e]?_.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=_.fds[e]){const{ret:r,fdstat:n}=_.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=_.fds[e]){const{ret:r,filestat:n}=_.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=a.read_bytes_array(i,t,r),{ret:l,nread:E}=_.fds[e].fd_pread(o,c,n);return i.setUint32(s,E,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,prestat:a}=_.fds[e].fd_prestat_get();return null!=a&&a.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=_.fds[e]){const{ret:r,prestat_dir_name:n}=_.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(_.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,a){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=s.read_bytes_array(i,t,r),{ret:l,nwritten:E}=_.fds[e].fd_pwrite(o,c,n);return i.setUint32(a,E,!0),l}return 8},fd_read(e,t,r,n){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=a.read_bytes_array(s,t,r),{ret:c,nread:l}=_.fds[e].fd_read(i,o);return s.setUint32(n,l,!0),c}return 8},fd_readdir(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){let o=0;for(;;){const{ret:c,dirent:l}=_.fds[e].fd_readdir_single(n);if(0!=c)return s.setUint32(a,o,!0),c;if(null==l)break;if(r-onull!=_.fds[e]?_.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,offset:a}=_.fds[e].fd_tell();return r.setBigUint64(t,a,!0),n}return 8},fd_write(e,t,r,n){const a=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=s.read_bytes_array(a,t,r),{ret:c,nwritten:l}=_.fds[e].fd_write(i,o);return a.setUint32(n,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_create_directory(a)}},path_filestat_get(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:c,filestat:l}=_.fds[e].path_filestat_get(t,o);return null!=l&&l.write_bytes(s,a),c}return 8},path_filestat_set_times(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return _.fds[e].path_filestat_set_times(t,c,a,s,i)}return 8},path_link(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]&&null!=_.fds[a]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(o.slice(s,s+i));return _.fds[a].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,a,s,i,o,l){const E=new DataView(_.inst.exports.memory.buffer),p=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const u=new TextDecoder(\"utf-8\").decode(p.slice(r,r+n));c.log(u);const{ret:f,fd_obj:d}=_.fds[e].path_open(t,u,a,s,i,o);if(0!=f)return f;_.fds.push(d);const g=_.fds.length-1;return E.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,a,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(t,t+r));c.log(l);const{ret:E,data:p}=_.fds[e].path_readlink(l);if(null!=p){const e=(new TextEncoder).encode(p);if(e.length>a)return i.setUint32(s,0,!0),8;o.set(e,n),i.setUint32(s,e.length,!0)}return E}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_remove_directory(a)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,a){const s=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[r]){const i=new TextDecoder(\"utf-8\").decode(s.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(s.slice(n,n+a));return _.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_unlink_file(a)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(_.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class d{open(e){const t=new f(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new o(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class g{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class b{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)E=globalThis.setImmediate;else{const e=new b;E=(t,...r)=>e.setImmediate(t,...r)}const D=e=>{const t=new g;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>E(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=(t,n)=>{const _=r.bR.encode(t),a=x(e,_);e.wasm_app(a)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(a,[globalThis,null],null,_.expr),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return x(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function x(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new p([],[],[new f(new d([])),new f(new d([])),new f(new d([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:D(y)});Object.assign(y,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),c=x(y,o);yield a.exports.wasm_app(c),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=x(y,t);y.wasm_app(n)}))}))},startDev:function(_,a=null){const s=new WebSocket(_),i=t=>e(this,void 0,void 0,(function*(){s.send(r.bR.encode(t))}));s.onopen=e=>{const t=r.bp(a),n=r.bR.encode({tag:r.dB.Start,0:t});s.send(n)},s.onmessage=_=>e(this,void 0,void 0,(function*(){const a=yield(s=_.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(s)})));var s;!function(_,a,s){e(this,void 0,void 0,(function*(){switch(_.tag){case r.I4.EvalExpr:{const e=r.wL(s,n,null,_.expr),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:_.threadId};return s(a,null)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(_)}))}(r.sy.decode(a),0,i)})),s.onerror=e=>{console.error(\"WebSocket error:\",e)},s.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" diff --git a/src/Clickable/Main/Wasm.hs b/src/Clickable/Main/Wasm.hs index ebac24e..ea121c2 100644 --- a/src/Clickable/Main/Wasm.hs +++ b/src/Clickable/Main/Wasm.hs @@ -26,7 +26,7 @@ runWasm app p = mdo case jmsg of Just (Start flags) -> launchClickM internalEnv $ app flags - Just (TriggerCallbackMsg arg eid) -> + Just (TriggerEventMsg arg eid) -> launchClickM internalEnv $ modify $ Internal.triggerEvent (unsafeFromEventId eid) arg Just BeforeUnload -> launchClickM internalEnv $ freeScope True $ ResourceScope $ Int32Le Internal.emptyState.next_id diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index 2f74ea1..da7dbf2 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -24,7 +24,7 @@ data HaskellMessage data JavaScriptMessage = Start StartFlags | Return Int32Le Value - | TriggerCallbackMsg Value EventId + | TriggerEventMsg Value EventId | BeforeUnload -- ^ Fired from addEventListener("beforeunload") listener. Won't -- work under the DevServer! @@ -108,23 +108,23 @@ data Expr -- ^ Assign a value to VarId allocated in haskell side. This way -- haskell can save certain values between WASM reactor invocations | FreeVar VarId - -- ^ Free a variable allocated with @AssignVar@ + -- ^ Free variable allocated with @AssignVar@ | Var VarId -- ^ Retrieve the value of the variable | FreeScope ResourceScope -- ^ Free all the resources assosiated with the given ResourceScope - | InsertNode Expr Expr + | InsertNode DomBuilder Expr | CreateElement Text | CreateElementNS Text Text | CreateTextNode Text - | ElementProp Expr Text Expr - | ElementAttr Expr Text Text - | InsertClassList Expr [Text] - | RemoveClassList Expr [Text] - | UpdateTextNode Expr Text - | InsertBoundary Expr - | ClearBoundary Expr Bool + | ElementProp DomBuilder Text Expr + | ElementAttr DomBuilder Text Text + | InsertClassList DomBuilder [Text] + | RemoveClassList DomBuilder [Text] + | UpdateTextNode DomBuilder Text + | InsertBoundary DomBuilder + | ClearBoundary DomBuilder Bool | AddEventListener ResourceScope Expr Expr Expr -- ^ @AddEventListener rscope target eventName listener@ is @@ -150,8 +150,8 @@ data Expr -- ^ Evaluate arbitrary JavaScript code @(Eval "setTimeout(() => -- console.log('Hi!'), 1000)")@ will print a message with one second -- delay - | TriggerCallback EventId Expr - -- ^ As a side-effect emits `TriggerCallbackMsg` message to Haskell + | TriggerEvent EventId Expr + -- ^ Emits `TriggerEventMsg` as a side-effect | UncaughtException Text deriving stock (Generic, Show) deriving anyclass (Binary) @@ -182,11 +182,17 @@ valueToExpr = \case toExpr :: ToValue a => a -> Expr toExpr = valueToExpr . toValue +builderContext :: DomBuilder +builderContext = DomBuilder $ Arg 0 0 + +newtype DomBuilder = DomBuilder {unDomBuilder :: Expr} + deriving newtype (Show, Binary) + data VarId = VarId ResourceScope Int32Le deriving stock (Generic, Show, Ord, Eq) deriving anyclass (Binary) -newtype FinalizerId = FinalizerId { unFinalizerId :: Int32Le } +newtype FinalizerId = FinalizerId {unFinalizerId :: Int32Le} deriving newtype (Show, Ord, Eq, Binary) newtype ResourceScope = ResourceScope {unResourceScope :: Int32Le} From 7a43b214ed839821ad34724be8e6289b26327a40 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 15 Aug 2024 16:48:38 +0400 Subject: [PATCH 50/64] Refactor DOM builder mechanism and some more changes --- examples/charts/App.hs | 80 -------- examples/charts/Charts.hs | 116 ----------- examples/charts/PairSelector.hs | 44 ----- examples/charts/charts.hs | 13 -- examples/charts/dev.hs | 8 - examples/todomvc/App.hs | 2 +- examples/todomvc/TodoItem.hs | 68 +++---- examples/todomvc/TodoList.hs | 55 +++--- jsbits/dev.ts | 17 +- jsbits/protocol.ts | 289 +++++++++++++++++----------- jsbits/wasm.ts | 6 +- src/Clickable/Core.hs | 203 ++++++++++---------- src/Clickable/DOM.hs | 330 ++++++++++++++------------------ src/Clickable/Internal.hs | 40 ++-- src/Clickable/Main/Dev.hs | 2 +- src/Clickable/Main/Wasm.hs | 2 +- src/Clickable/Protocol.hs | 39 ++-- 17 files changed, 527 insertions(+), 787 deletions(-) delete mode 100644 examples/charts/App.hs delete mode 100644 examples/charts/Charts.hs delete mode 100644 examples/charts/PairSelector.hs delete mode 100644 examples/charts/charts.hs delete mode 100644 examples/charts/dev.hs diff --git a/examples/charts/App.hs b/examples/charts/App.hs deleted file mode 100644 index 1d212cb..0000000 --- a/examples/charts/App.hs +++ /dev/null @@ -1,80 +0,0 @@ -module App where - -import Charts qualified as Charts -import Control.Monad.State -import Control.Monad -import Control.Concurrent -import Data.Proxy -import Data.Function ((&)) -import Data.Text (Text) -import Data.Text qualified as Text -import GHC.Generics -import Clickable -import Clickable.Protocol -import Clickable.Protocol.Value qualified as Value -import Clickable.FFI -import Data.Int -import Debug.Trace - - -data AppInstance = AppInstance - { state_var :: DynVar AppTab - } deriving (Generic) - -data AppTab - = ChartsTab Charts.ChartInstance - | HelpTab - -new :: ClickM AppInstance -new = do - charts_instance <- Charts.new - state_var <- newVar $ ChartsTab charts_instance - return AppInstance {state_var} - -html :: AppInstance -> HtmlM () -html self = do - el "style" $ text styles - div_ do - button_ do - text "Open Charts" - on @"click" do - inst <- Charts.new - modifyVar_ self.state_var $ const $ ChartsTab inst - button_ do - text "Open Help" - on @"click" $ modifyVar_ self.state_var $ const HelpTab - button_ do - text "Open Modal" - on @"click" do - mvar <- liftIO newEmptyMVar - attachToBody do - p_ $ text "Content of the modal" - button_ do - text "Close" - on @"click" $ liftIO $ putMVar mvar "dljfhdlsfjh" - syncPoint - answer <- liftIO $ takeMVar mvar - -- consoleLog answer - return () - dyn $ fromVar self.state_var & fmap \case - ChartsTab inst -> Charts.html inst - HelpTab -> p_ $ text - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod \ - \tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim \ - \veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea \ - \commodo consequat. Duis aute irure dolor in reprehenderit in voluptate \ - \velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint \ - \occaecat cupidatat non proident, sunt in culpa qui officia deserunt \ - \mollit anim id est laborum." - button_ do - text "Run computation" - on @"click" do - result <- evalExpr $ F64 2 `Subtract` F64 4 - traceShowM result - let md :: Maybe Int32 = Value.fromValue result - forM_ md \d -> enqueueExpr $ Call (Id "console") "log" [toExpr d] - -styles :: Text -styles = "\ - \ \ - \ " diff --git a/examples/charts/Charts.hs b/examples/charts/Charts.hs deleted file mode 100644 index 41ed7a3..0000000 --- a/examples/charts/Charts.hs +++ /dev/null @@ -1,116 +0,0 @@ -module Charts where - -import Data.Text (Text) -import Data.Text qualified as Text -import Data.Function ((&)) -import GHC.Generics - -import Clickable -import Clickable.FFI -import PairSelector qualified as PairSelector - -------------------------------------------------------- --- EXAMPLE OF APPLICATION FEATURING FINANCIAL CHARTS -- -------------------------------------------------------- - -data ChartState = ChartState - { main_transform :: Transform2D - , mouse_position :: Point - , counter :: Int - } deriving (Show, Eq, Generic) - -data ChartInstance = ChartInstance - { state_var :: DynVar ChartState - , pair_selector_instance :: DynVar PairSelector.PairSelectorState - } deriving (Generic) - -new :: ClickM ChartInstance -new = do - pair_selector_instance <- PairSelector.new - state_var <- newVar ChartState - { main_transform = Transform2D 0 0 0 0 - , mouse_position = Point 0 0 - , counter = 0 - } - return ChartInstance {state_var, pair_selector_instance} - -html :: ChartInstance -> HtmlM () -html self = do - el "style" $ text styles - div_ [class_ "Charts-root"] do - addEventListener mouseMove do - enqueueExpr $ Call (Id "console") "log" [String "jshflkjsdhflasfjhlaskjfhsdaj"] - h1_ $ text "Canvas with candle chart" - div_ do - PairSelector.html self.pair_selector_instance - div_ do - button_ do - text "Clickable this button" - on @"click" do - modifyVar_ self.state_var \s -> s {counter = s.counter + 1 } - button_ do - text "Print state" - on @"click" do - s <- readVar self.state_var - -- consoleLog $ Text.pack $ show s - return () - span_ [] $ dynText $ fromVar self.state_var & fmap \s -> - "You clicked " <> Text.pack (show s.counter) <> " times" - canvas_ [class_ "Charts-canvas"] $ return () - -styles :: Text -styles = "\ - \.Charts-root {\ - \ max-width: 900;\ - \ width: 100%\ - \ padding: 16px;\ - \ margin: 0 auto;\ - \}\ - \.Charts-canvas {\ - \ width: 100%;\ - \ height: 550px;\ - \ border: solid 1px black;\ - \}\ - \ " - -data Transform2D = Transform2D - { a :: Double -- ^ X scaling - , c :: Double -- ^ X translation - , e :: Double -- ^ Y scaling - , f :: Double -- ^ Y translation - } deriving (Show, Eq, Generic) - -data Point = Point - { point_x :: Double - , point_y :: Double - } deriving (Eq, Show, Generic) - --- setMouseCoords :: Point -> Edit ChartState --- setMouseCoords p = Fld (Proxy @"mouse_position") (Ins p) - - --- moveScreen :: Double -> Jet ChartState -> Jet ChartState --- moveScreen dir old = --- let --- beg = negate old.position.main_transform.c / old.position.main_transform.a --- end = (w - old.position.main_transform.c) / old.position.main_transform.a --- inc = (end - beg) * dir --- w = 1000 --- c = old.position.main_transform.c - --- (inc * old.position.main_transform.a) --- new = old.position --- { main_transform = old.position.main_transform {c} --- } --- in --- Jet new (Fld (Proxy @"main_transform") (Fld (Proxy @"c") (Ins c)) : old.velocity) - --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event -mouseMove :: ConnectResourceArgs (ClickM ()) -mouseMove = ConnectResourceArgs - { aquire_resource = \scope sourceId -> - Eval (normalEventWrapper "mousemove" EventListenerOptions - { prevent_default = True - , stop_propagation = True - }) `Apply` [Arg 0 0, Lam (TriggerCallback sourceId (Arg 0 0))] - , mk_callback = \k _ -> k - } diff --git a/examples/charts/PairSelector.hs b/examples/charts/PairSelector.hs deleted file mode 100644 index 77cbf52..0000000 --- a/examples/charts/PairSelector.hs +++ /dev/null @@ -1,44 +0,0 @@ -module PairSelector where - -import Data.Text (Text) -import Data.Text qualified as Text -import Data.Function hiding (on) -import GHC.Generics - -import Clickable - -data TradingPair = TradingPair - { base :: Text - , quote :: Text - , exchange :: Text - } deriving (Show, Eq, Generic) - -data PairSelectorState = PairSelectorState - { selected_pair :: Maybe TradingPair - , options :: [TradingPair] - } deriving (Show, Eq, Generic) - -new :: ClickM (DynVar PairSelectorState) -new = - newVar PairSelectorState - { selected_pair = Nothing - , options = [] - } - -html :: DynVar PairSelectorState -> HtmlM () -html self = do - el "style" $ text styles - div_ [class_ "PairSelector-root"] do - button_ do - text "Select pair" - on @"click" $ modifyVar_ self \s -> case s.selected_pair of - Just _ -> s {selected_pair = Nothing} - Nothing -> s {selected_pair = Just $ TradingPair "BTC" "USDT" "MEXC"} - span_ $ dynText $ fromVar self & fmap \s -> s.selected_pair & maybe - "Nothing selected" - (("Selected pair: " <>) . Text.pack . show) - -styles :: Text -styles = "\ - \ \ - \ " diff --git a/examples/charts/charts.hs b/examples/charts/charts.hs deleted file mode 100644 index 310e418..0000000 --- a/examples/charts/charts.hs +++ /dev/null @@ -1,13 +0,0 @@ -import Control.Monad.Reader -import Clickable -import GHC.Ptr -import GHC.Word -import "this" App qualified as App - -main :: IO () -main = return () - -foreign export ccall wasm_main :: Ptr Word8 -> IO () -wasm_main p = do - _ <- runApp p \_ -> attachToBody $ lift App.new >>= App.html - return () diff --git a/examples/charts/dev.hs b/examples/charts/dev.hs deleted file mode 100644 index e42e9a5..0000000 --- a/examples/charts/dev.hs +++ /dev/null @@ -1,8 +0,0 @@ -import Clickable -import Clickable.Main.DevServer -import Control.Monad.Reader - -import "this" App qualified as App - -main :: IO () -main = runDev \_ -> attachToBody $ lift App.new >>= App.html diff --git a/examples/todomvc/App.hs b/examples/todomvc/App.hs index 5435714..98fac0c 100644 --- a/examples/todomvc/App.hs +++ b/examples/todomvc/App.hs @@ -19,6 +19,6 @@ app _ = do TodoList.html TodoList.TodoListConfig { state_var = stateVar } - lift $ connectResource popstateConnectArgs \loc -> do + lift $ addEventListener popstateEvent \loc -> do let filter = fromMaybe TodoList.All $ TodoList.parseFilter loc.hash modifyVar_ stateVar \s -> s {TodoList.filter} diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs index 1319a85..3a1da61 100644 --- a/examples/todomvc/TodoItem.hs +++ b/examples/todomvc/TodoItem.hs @@ -5,6 +5,7 @@ import Data.List qualified as List import Data.Maybe import Data.Text (Text) import GHC.Int +import GHC.Generics import "this" Utils @@ -18,7 +19,8 @@ data TodoItemState = TodoItemState { title :: Text , completed :: Bool , editing :: Maybe Text - } deriving stock (Show, Eq) + } deriving stock (Show, Eq, Generic) + deriving anyclass (FromValue, ToValue) data TodoItemAction a where CancelAction :: TodoItemAction () @@ -32,31 +34,30 @@ emptyState :: TodoItemState emptyState = TodoItemState "" False Nothing eval :: TodoItemConfig -> TodoItemAction a -> ClickM a -eval cfg = \case - CancelAction -> - modifyVar_ cfg.state_var \s -> s{editing=Nothing} - CommitAction -> do - state <- readVar cfg.state_var - case state.editing of - Just "" -> - cfg.ask_delete_item - Just t -> - modifyVar_ cfg.state_var \s -> s {editing=Nothing, title = t} - Nothing -> - pure () - InputAction newVal -> - modifyVar_ cfg.state_var \s -> s{editing = Just newVal} - DoubleClickAction inpElm -> do - trampoline do - modifyVar_ cfg.state_var \s -> s {editing = Just s.title} - syncPoint - assignFocus inpElm - CheckedAction isChecked -> do - modifyVar_ cfg.state_var \s -> s{completed = isChecked} - KeydownAction key -> case key of - 13 {- Enter -} -> eval cfg CommitAction - 27 {- Escape -} -> eval cfg CancelAction - _ -> return () +eval cfg CancelAction = + modifyVar_ cfg.state_var \s -> s{editing=Nothing} +eval cfg CommitAction = do + state <- readVar cfg.state_var + case state.editing of + Just "" -> + cfg.ask_delete_item + Just t -> + modifyVar_ cfg.state_var \s -> s {editing=Nothing, title = t} + Nothing -> + pure () +eval cfg (InputAction newVal) = + modifyVar_ cfg.state_var \s -> s{editing = Just newVal} +eval cfg (DoubleClickAction inpElm) = do + trampoline do + modifyVar_ cfg.state_var \s -> s {editing = Just s.title} + syncPoint + assignFocus inpElm +eval cfg (CheckedAction isChecked) = + modifyVar_ cfg.state_var \s -> s{completed = isChecked} +eval cfg (KeydownAction key) = case key of + 13 {- Enter -} -> eval cfg CommitAction + 27 {- Escape -} -> eval cfg CancelAction + _ -> return () html :: TodoItemConfig -> HtmlM () html cfg = li_ mdo @@ -79,18 +80,5 @@ html cfg = li_ mdo on @"input" $ eval cfg . InputAction on @"keydown" $ eval cfg . KeydownAction on @"blur" $ eval cfg CommitAction - saveCurrentNode + saveDomBuilder return () - -instance ToValue TodoItemState where - toValue s = Vobj - [ ("title", toValue s.title) - , ("completed", toValue s.completed) - ] - -instance FromValue TodoItemState where - fromValue (Vobj kv) = do - title <- fromValue =<< List.lookup "title" kv - completed <- fromValue =<< List.lookup "completed" kv - return TodoItemState {editing=Nothing, ..} - fromValue _ = Nothing diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index ae7ce72..3369a2b 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -1,12 +1,11 @@ module TodoList where +import Clickable import Control.Monad import Data.List qualified as List import Data.Text (Text) import Data.Text qualified as Text import GHC.Int -import Clickable -import Clickable.FFI import "this" TodoItem qualified as TodoItem @@ -41,39 +40,35 @@ new items = } eval :: TodoListConfig -> TodoListAction a -> ClickM a -eval cfg = \case - ToggleAllAction isChecked -> - modifyVar_ cfg.state_var \s -> s - { items = - fmap (\i -> i {TodoItem.completed = isChecked}) s.items +eval cfg (ToggleAllAction isChecked) = + modifyVar_ cfg.state_var \s -> s + { items = + fmap (\i -> i {TodoItem.completed = isChecked}) s.items + } +eval cfg (InputAction newVal) = + modifyVar_ cfg.state_var \s -> s {title = newVal} +eval cfg CommitAction = do + title <- Text.strip . (.title) <$> readVar cfg.state_var + case title of + "" -> return () + t -> modifyVar_ cfg.state_var \s -> s + { items = s.items <> [newTodo t] + , title = "" } - InputAction newVal -> do - modifyVar_ cfg.state_var \s -> s {title = newVal} - CommitAction -> do - title <- Text.strip . (.title) <$> readVar cfg.state_var - case title of - "" -> return () - t -> modifyVar_ cfg.state_var \s -> s - { items = s.items <> [mkNewTodo t] - , title = "" - } - KeydownAction key -> do - case key of - 13 {- Enter -} -> eval cfg CommitAction - 27 {- Escape -} -> do - s <- readVar cfg.state_var - consoleLog $ Text.pack $ show s - _ -> return () - DeleteItemAction itemIx -> - modifyVar_ cfg.state_var \s -> s {items = deleteIx itemIx s.items} - ClearCompletedAction -> - modifyVar_ cfg.state_var \s -> s - {items = (List.filter (not . TodoItem.completed)) s.items} + where + newTodo t = TodoItem.emptyState {TodoItem.title = t} +eval cfg (KeydownAction key) = case key of + 13 {- Enter -} -> eval cfg CommitAction + _ -> return () +eval cfg (DeleteItemAction itemIx) = + modifyVar_ cfg.state_var \s -> s {items = deleteIx itemIx s.items} where deleteIx :: Int -> [a] -> [a] deleteIx _ [] = [] deleteIx i (a:as) | i == 0 = as | otherwise = a : deleteIx (i-1) as - mkNewTodo t = TodoItem.emptyState {TodoItem.title = t} +eval cfg ClearCompletedAction = + modifyVar_ cfg.state_var \s -> s + {items = (List.filter (not . TodoItem.completed)) s.items} html :: TodoListConfig -> HtmlM () html cfg = do diff --git a/jsbits/dev.ts b/jsbits/dev.ts index 4db6f1f..07be5e9 100644 --- a/jsbits/dev.ts +++ b/jsbits/dev.ts @@ -1,11 +1,11 @@ import { absurd } from './lib'; import * as p from './protocol'; -import { HaskellMessage, JavaScriptMessage, JavaScriptMessageTag, HaskellMessageTag, Bindings, List } from './protocol'; +import { HaskellMessage, JavaScriptMessage, JavaScriptMessageTag, HaskellMessageTag } from './protocol'; export function startDev(devSocketUri: string, startFlags: unknown = null) { const websocket = new WebSocket(devSocketUri); - const sendToHaskell = async (jsMsg: JavaScriptMessage) => { + const haskellCallback = async (jsMsg: JavaScriptMessage) => { websocket.send(p.javascriptMessage.encode(jsMsg)); // const haskMsg = await awaitWebsocketMessage(); // await haskellApp(haskMsg, argScope, sendToHaskell); @@ -24,7 +24,7 @@ export function startDev(devSocketUri: string, startFlags: unknown = null) { websocket.onmessage = async (event) => { const binaryDataReceived = await convertBlobToUint8Array(event.data); const haskMsg = p.haskellMessage.decode(binaryDataReceived); - haskellApp(haskMsg, null, sendToHaskell); + haskellApp(haskMsg, haskellCallback); }; // Event handler for errors @@ -38,19 +38,18 @@ export function startDev(devSocketUri: string, startFlags: unknown = null) { }; } -export type HaskellAsyncCallback = (jsMsg: JavaScriptMessage, argScope: List) => Promise; +export type HaskellAsyncCallback = (jsMsg: JavaScriptMessage) => Promise; export async function haskellApp ( hmsg: HaskellMessage, - argScope: List, - send: HaskellAsyncCallback + haskellCallback: HaskellAsyncCallback ): Promise { switch (hmsg.tag) { case HaskellMessageTag.EvalExpr: { - const result = p.evalExpr(send, globalContext, argScope, hmsg.expr); + const result = p.evalExpr(hmsg.expr, { haskellCallback }); const jvalue = p.unknownToValue(result); const jmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, value: jvalue, threadId: hmsg.threadId }; - return send(jmsg, argScope); + return haskellCallback(jmsg); } case HaskellMessageTag.HotReload: { window.location.reload(); @@ -63,8 +62,6 @@ export async function haskellApp ( absurd(hmsg); } -const globalContext: List = [window as any, null] - export function convertBlobToUint8Array(blob: Blob): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index 40607bd..d4fcce2 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -26,13 +26,39 @@ export function cdr(pair: Cons): List { export type ClickablePublic = { startWasm(wasmUri: string, startFlags?: unknown): void; startDev(devSocketUri: string, startFlags?: unknown): void; - evalExpr(hscb: HaskellCallback, idenScope: List, argScope: List, exp: Expr): unknown; - evalUint8Array(hscb: HaskellCallback, idenScope: List, argScope: List, exp: Uint8Array): unknown; + evalExpr(exp: Expr, options?: EvalOptions): unknown; + evalUint8Array(exp: Uint8Array, options?: EvalOptions): unknown; }; export type HaskellCallback = (jsMsg: JavaScriptMessage, argScope: List) => void; -export function evalExpr(hscb: HaskellCallback, idenScope: List, argScope: List, exp: Expr): unknown { +export type EvalOptions = { + haskellCallback?: HaskellCallback; + idenScope?: List; + argScope?: List; + builderScope?: List; +}; + +export function evalExpr(exp: Expr, options: EvalOptions = {}): unknown { + const haskellCallback = options.haskellCallback || (() => {}); + const idenScope = options.idenScope || globalContext; + const argScope = options.argScope || null; + const builderScope = options.builderScope || null; + return evalLoop(haskellCallback, idenScope, argScope, builderScope, exp); +} + +export function evalUint8Array(exp: Uint8Array, options: EvalOptions = {}): unknown { + const decoded: Expr = expr.decode(exp); + return evalExpr(decoded, options); +} + +export function evalLoop ( + hscb: HaskellCallback, + idenScope: List, + argScope: List, + builderScope: List, + exp: Expr +): unknown { switch(exp.tag) { case ExprTag.Null: { return null; @@ -74,46 +100,46 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc return exp[0]; } case ExprTag.Arr: { - return exp[0].map(evalExpr.bind(undefined, hscb, idenScope, argScope)); + return exp[0].map(evalLoop.bind(undefined, hscb, idenScope, argScope, builderScope)); } case ExprTag.Obj: { - return Object.fromEntries(exp[0].map(([k, e]) => [k, evalExpr(hscb, idenScope, argScope, e)])); + return Object.fromEntries(exp[0].map(([k, e]) => [k, evalLoop(hscb, idenScope, argScope, builderScope, e)])); } case ExprTag.U8Arr: { return exp[0]; } case ExprTag.Dot: { - const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as any; + const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as any; return lhs[exp[1]]; } case ExprTag.SetProp: { - const rhs = evalExpr(hscb, idenScope, argScope, exp[2]); - const obj = evalExpr(hscb, idenScope, argScope, exp[0]) as any; + const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[2]); + const obj = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as any; obj[exp[1]] = rhs; return rhs; } case ExprTag.Ix: { - const rhs: any = evalExpr(hscb, idenScope, argScope, exp.exp); + const rhs: any = evalLoop(hscb, idenScope, argScope, builderScope, exp.exp); return rhs[exp.ix]; } case ExprTag.Plus: { - const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as number; - const rhs = evalExpr(hscb, idenScope, argScope, exp[1]) as number; + const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as number; + const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[1]) as number; return lhs + rhs; } case ExprTag.Subtract: { - const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as number; - const rhs = evalExpr(hscb, idenScope, argScope, exp[1]) as number; + const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as number; + const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[1]) as number; return lhs - rhs; } case ExprTag.Multiply: { - const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as number; - const rhs = evalExpr(hscb, idenScope, argScope, exp[1]) as number; + const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as number; + const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[1]) as number; return lhs * rhs; } case ExprTag.Divide: { - const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as number; - const rhs = evalExpr(hscb, idenScope, argScope, exp[1]) as number; + const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as number; + const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[1]) as number; return lhs / rhs; } case ExprTag.Id: { @@ -129,7 +155,7 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc } case ExprTag.Lam: { return function() { - return evalExpr(hscb, idenScope, Cons(arguments, argScope), exp.body); + return evalLoop(hscb, idenScope, Cons(arguments, argScope), builderScope, exp.body); }; } case ExprTag.Arg: { @@ -146,16 +172,16 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc throw new Error('Argument scope out of a range: ' + exp.scopeIx); } case ExprTag.Apply: { - const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as Function; - return lhs.apply(undefined, exp[1].map(evalExpr.bind(undefined, hscb, idenScope, argScope))); + const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as Function; + return lhs.apply(undefined, exp[1].map(evalLoop.bind(undefined, hscb, idenScope, argScope, builderScope))); } case ExprTag.Call: { - const lhs = evalExpr(hscb, idenScope, argScope, exp[0]) as any; + const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as any; const fn = lhs[exp[1]]; - return fn.apply(lhs, exp[2].map(evalExpr.bind(undefined, hscb, idenScope, argScope))); + return fn.apply(lhs, exp[2].map(evalLoop.bind(undefined, hscb, idenScope, argScope, builderScope))); } case ExprTag.AssignVar: { - const rhs = evalExpr(hscb, idenScope, argScope, exp.rhs); + const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp.rhs); if (varStorage.has(exp.scopeId)) { const scopeMap = varStorage.get(exp.scopeId)!; scopeMap.set(exp.varId, rhs); @@ -168,12 +194,12 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc } case ExprTag.FreeVar: { const scopeStorage = varStorage.get(exp.scopeId); - if (!scopeStorage) return; + if (!scopeStorage) return null; scopeStorage.delete(exp.varId); if (scopeStorage.size == 0) { varStorage.delete(exp.scopeId); } - return; + return null; } case ExprTag.Var: { return varStorage.get(exp.scopeId)?.get(exp.varId); @@ -184,61 +210,88 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc if (scopeFinalizers) scopeFinalizers.forEach(fn => fn ()); return null; } - case ExprTag.InsertNode: { - const parent = evalExpr(hscb, idenScope, argScope, exp.parent) as Element|Comment; - const child = evalExpr(hscb, idenScope, argScope, exp.child) as Node; - domHelpers.insertIntoBuilder(parent, child); - return null; + case ExprTag.AskDomBuilder: { + if (builderScope == null) { + throw new Error('AskDomBuilder called without prior SupplyDomBuilder!'); + } + return builderScope[0]; } - case ExprTag.CreateElement: { - return document.createElement(exp.tagName); + case ExprTag.SupplyDomBuilder: { + const builder = evalLoop(hscb, idenScope, argScope, builderScope, exp.builder) as Element|Comment; + const newBuilderScope = Cons(builder, builderScope); + return evalLoop(hscb, idenScope, argScope, newBuilderScope, exp.expr) } - case ExprTag.CreateElementNS: { - return document.createElementNS(exp.ns, exp.tagName); - } - case ExprTag.CreateText: { - return document.createTextNode(exp.content); + case ExprTag.InsertNode: { + if (builderScope == null) { + throw new Error('InsertNode called without prior SupplyDomBuilder!'); + } + const child = evalLoop(hscb, idenScope, argScope, builderScope, exp.child) as Node; + domHelpers.insertIntoBuilder(builderScope[0], child); + return null; } case ExprTag.ElementProp: { - const parent = evalExpr(hscb, idenScope, argScope, exp.node) as Element|Comment; - const propValue = evalExpr(hscb, idenScope, argScope, exp.propValue); - domHelpers.assignProperty(parent, exp.propName, propValue); + if (builderScope == null) { + throw new Error('ElementProp called without prior SupplyDomBuilder!'); + } + const propValue = evalLoop(hscb, idenScope, argScope, builderScope, exp.propValue); + domHelpers.assignProperty(builderScope[0], exp.propName, propValue); return null; } case ExprTag.ElementAttr: { - const parent = evalExpr(hscb, idenScope, argScope, exp.node) as Element|Comment; - domHelpers.assignAttribute(parent, exp.attrName, exp.attrValue); + if (builderScope == null) { + throw new Error('ElementAttr called without prior SupplyDomBuilder!'); + } + domHelpers.assignAttribute(builderScope[0], exp.attrName, exp.attrValue); return null; } - case ExprTag.InsertClassList: { - const parent = evalExpr(hscb, idenScope, argScope, exp.node) as Element|Comment; - const element = domHelpers.domBuilderElement(parent); + case ExprTag.ClassListAdd: { + if (builderScope == null) { + throw new Error('InsertClassList called without prior SupplyDomBuilder!'); + } + const element = domHelpers.domBuilderElement(builderScope[0]); exp.classList.forEach(className => element.classList.add(className)); return null; } - case ExprTag.RemoveClassList: { - const parent = evalExpr(hscb, idenScope, argScope, exp.node) as Element|Comment; - const element = domHelpers.domBuilderElement(parent); + case ExprTag.ClassListRemove: { + if (builderScope == null) { + throw new Error('RemoveClassList called without prior SupplyDomBuilder!'); + } + const element = domHelpers.domBuilderElement(builderScope[0]); exp.classList.forEach(className => element.classList.remove(className)); return null; } + case ExprTag.InsertBrackets: { + if (builderScope == null) { + throw new Error('InsertBoundary called without prior SupplyDomBuilder!'); + } + return domHelpers.insertBrackets(builderScope[0]); + } + case ExprTag.ClearBrackets: { + if (builderScope == null) { + throw new Error('InsertBoundary called without prior SupplyDomBuilder!'); + } + return domHelpers.clearBrackets(builderScope[0], Boolean(exp.detach)); + } + + case ExprTag.CreateElement: { + return document.createElement(exp.tagName); + } + case ExprTag.CreateElementNS: { + return document.createElementNS(exp.ns, exp.tagName); + } + case ExprTag.CreateTextNode: { + return document.createTextNode(exp.content); + } case ExprTag.UpdateTextNode: { - const node = evalExpr(hscb, idenScope, argScope, exp.node) as Text; + const node = evalLoop(hscb, idenScope, argScope, builderScope, exp.node) as Text; node.textContent = exp.content; return null; } - case ExprTag.InsertBoundary: { - const parent = evalExpr(hscb, idenScope, argScope, exp.parent) as Element|Comment; - return domHelpers.insertBoundary(parent); - } - case ExprTag.ClearBoundary: { - const boundary = evalExpr(hscb, idenScope, argScope, exp.boundary) as Comment; - return domHelpers.clearBoundary(boundary, Boolean(exp.detach)); - } + case ExprTag.AddEventListener: { - const target = evalExpr(hscb, idenScope, argScope, exp.target) as Element|Comment; - const eventName = evalExpr(hscb, idenScope, argScope, exp.eventName) as string; - const listener = evalExpr(hscb, idenScope, argScope, exp.listener) as EventListener; + const target = evalLoop(hscb, idenScope, argScope, builderScope, exp.target) as Element|Comment; + const eventName = evalLoop(hscb, idenScope, argScope, builderScope, exp.eventName) as string; + const listener = evalLoop(hscb, idenScope, argScope, builderScope, exp.listener) as EventListener; domHelpers.addEventListener(target, eventName, listener); const existingScope = finalizers.get(exp.reactiveScope); const scopeFinalizers = existingScope ? existingScope : new IntMap(); @@ -246,14 +299,14 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc return scopeFinalizers.push(() => domHelpers.removeEventListener(target, eventName, listener)); } case ExprTag.ConnectResource: { - const finalizer = evalExpr(hscb, idenScope, argScope, exp.aquire) as Function; + const finalizer = evalLoop(hscb, idenScope, argScope, builderScope, exp.aquire) as Function; const existingScope = finalizers.get(exp.reactiveScope); const scopeFinalizers = existingScope ? existingScope : new IntMap(); if (!existingScope) finalizers.set(exp.reactiveScope, scopeFinalizers); return scopeFinalizers.push(finalizer); } case ExprTag.SetTimeout: { - const callback = evalExpr(hscb, idenScope, argScope, exp.callback) as Function; + const callback = evalLoop(hscb, idenScope, argScope, builderScope, exp.callback) as Function; const existingScope = finalizers.get(exp.reactiveScope); const scopeFinalizers = existingScope ? existingScope : new IntMap(); if (!existingScope) finalizers.set(exp.reactiveScope, scopeFinalizers); @@ -268,7 +321,7 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc } case ExprTag.ApplyFinalizer: { const existingScope = finalizers.get(exp.reactiveScope); - const finalizerId = evalExpr(hscb, idenScope, argScope, exp.finalizerId) as number; + const finalizerId = evalLoop(hscb, idenScope, argScope, builderScope, exp.finalizerId) as number; if (!existingScope) return false; const cancellerFn = existingScope.get(finalizerId); if (!cancellerFn) return false; @@ -277,13 +330,13 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc return true; } case ExprTag.RevSeq: { - return exp.exprs.reduceRight((_, e) => evalExpr(hscb, idenScope, argScope, e), null); + return exp.exprs.reduceRight((_, e) => evalLoop(hscb, idenScope, argScope, builderScope, e), null); } case ExprTag.Eval: { return eval(exp.rawJavaScript); } case ExprTag.TriggerEvent: { - const arg = evalExpr(hscb, idenScope, argScope, exp.arg); + const arg = evalLoop(hscb, idenScope, argScope, builderScope, exp.arg); const jsMsg: JavaScriptMessage = { tag: JavaScriptMessageTag.TriggerEventMsg, arg: unknownToValue(arg), @@ -298,11 +351,6 @@ export function evalExpr(hscb: HaskellCallback, idenScope: List, argSc absurd(exp); } -export function evalUint8Array(hscb: HaskellCallback, idenScope: List, argScope: List, exp: Uint8Array): unknown { - const decoded: Expr = expr.decode(exp); - return evalExpr(hscb, idenScope, argScope, decoded); -} - export function unknownToValue(inp: unknown): Value { if (typeof(inp) === 'boolean') { return { tag: ValueTag.Vbool, 0: inp ? 1 : 0 }; @@ -440,17 +488,21 @@ export enum ExprTag { Var, FreeScope, + AskDomBuilder, + SupplyDomBuilder, + InsertNode, - CreateElement, - CreateElementNS, - CreateText, ElementProp, ElementAttr, - InsertClassList, - RemoveClassList, + ClassListAdd, + ClassListRemove, + InsertBrackets, + ClearBrackets, + + CreateElement, + CreateElementNS, + CreateTextNode, UpdateTextNode, - InsertBoundary, - ClearBoundary, AddEventListener, ConnectResource, @@ -505,17 +557,21 @@ export type Expr = | { tag: ExprTag.Var, scopeId: number, varId: number } | { tag: ExprTag.FreeScope, scopeId: number } - | { tag: ExprTag.InsertNode, parent: Expr, child: Expr } + | { tag: ExprTag.AskDomBuilder } + | { tag: ExprTag.SupplyDomBuilder, builder: Expr, expr: Expr } + + | { tag: ExprTag.InsertNode, child: Expr } + | { tag: ExprTag.ElementProp, propName: string, propValue: Expr } + | { tag: ExprTag.ElementAttr, attrName: string, attrValue: string } + | { tag: ExprTag.ClassListAdd, classList: string[] } + | { tag: ExprTag.ClassListRemove, classList: string[] } + | { tag: ExprTag.InsertBrackets } + | { tag: ExprTag.ClearBrackets, detach: number } + | { tag: ExprTag.CreateElement, tagName: string } | { tag: ExprTag.CreateElementNS, ns: string, tagName: string } - | { tag: ExprTag.CreateText, content: string } - | { tag: ExprTag.ElementProp, node: Expr, propName: string, propValue: Expr } - | { tag: ExprTag.ElementAttr, node: Expr, attrName: string, attrValue: string } - | { tag: ExprTag.InsertClassList, node: Expr, classList: string[] } - | { tag: ExprTag.RemoveClassList, node: Expr, classList: string[] } + | { tag: ExprTag.CreateTextNode, content: string } | { tag: ExprTag.UpdateTextNode, node: Expr, content: string } - | { tag: ExprTag.InsertBoundary, parent: Expr } - | { tag: ExprTag.ClearBoundary, boundary: Expr, detach: number } | { tag: ExprTag.AddEventListener, reactiveScope: number, target: Expr, eventName: Expr, listener: Expr } | { tag: ExprTag.ConnectResource, reactiveScope: number, aquire: Expr } @@ -570,17 +626,21 @@ export const expr = b.recursive(self => b.discriminate({ [ExprTag.Var]: b.record({ scopeId: b.int32, varId: b.int32 }), [ExprTag.FreeScope]: b.record({ scopeId: b.int32 }), - [ExprTag.InsertNode]: b.record({ parent: self, child: self }), + [ExprTag.AskDomBuilder]: b.record({ }), + [ExprTag.SupplyDomBuilder]: b.record({ builder: self, expr: self }), + + [ExprTag.InsertNode]: b.record({ child: self }), + [ExprTag.ElementProp]: b.record({ propName: b.string, propValue: self }), + [ExprTag.ElementAttr]: b.record({ attrName: b.string, attrValue: b.string }), + [ExprTag.ClassListAdd]: b.record({ classList: b.array(b.string) }), + [ExprTag.ClassListRemove]: b.record({ classList: b.array(b.string) }), + [ExprTag.InsertBrackets]: b.record({ }), + [ExprTag.ClearBrackets]: b.record({ detach: b.int8 }), + [ExprTag.CreateElement]: b.record({ tagName: b.string }), [ExprTag.CreateElementNS]: b.record({ ns: b.string, tagName: b.string }), - [ExprTag.CreateText]: b.record({ content: b.string }), - [ExprTag.ElementProp]: b.record({ node: self, propName: b.string, propValue: self }), - [ExprTag.ElementAttr]: b.record({ node: self, attrName: b.string, attrValue: b.string }), - [ExprTag.InsertClassList]: b.record({ node: self, classList: b.array(b.string) }), - [ExprTag.RemoveClassList]: b.record({ node: self, classList: b.array(b.string) }), + [ExprTag.CreateTextNode]: b.record({ content: b.string }), [ExprTag.UpdateTextNode]: b.record({ node: self, content: b.string }), - [ExprTag.InsertBoundary]: b.record({ parent: self }), - [ExprTag.ClearBoundary]: b.record({ boundary: self, detach: b.int8 }), [ExprTag.AddEventListener]: b.record({ reactiveScope: b.int32, target: self, eventName: self, listener: self }), [ExprTag.ConnectResource]: b.record({ reactiveScope: b.int32, aquire: self }), @@ -628,6 +688,8 @@ export type VarId = number; export const varStorage = new Map>(); export const finalizers = new Map>; +export const globalContext: List = [window as any, null] + namespace domHelpers { export function insertIntoBuilder(builder: Element|Comment, child: Node): void { if (builder instanceof Comment) { @@ -660,28 +722,31 @@ namespace domHelpers { element.removeEventListener(eventName, listener); } - export function insertBoundary(builder: Element|Comment): Comment { - const begin = document.createComment('ContentBoundary {{'); + export function insertBrackets(builder: Element|Comment): Comment { + const begin = document.createComment('ContentBrackets {{'); const end = document.createComment('}}'); insertIntoBuilder(builder, begin); insertIntoBuilder(builder, end); return end; } - export function clearBoundary(boundary: Comment, detach: boolean): void { - const end = boundary; - let nestedCounter = 0; - for (;;){ - if (!end.previousSibling || - (nestedCounter == 0 && isOpeningBoundary(end.previousSibling)) - ) break; - if (isClosingBoundary(end.previousSibling)) nestedCounter++; - else if (isOpeningBoundary(end.previousSibling)) nestedCounter--; - end.previousSibling!.parentNode!.removeChild(end.previousSibling!); - } - if (detach) { - end.previousSibling!.parentNode!.removeChild(end.previousSibling!); - end.parentNode!.removeChild(end); + export function clearBrackets(bracket: Comment|Element, detach: boolean): void { + if (bracket instanceof Comment) { + let nestedCounter = 0; + for (;;){ + if (!bracket.previousSibling || + (nestedCounter == 0 && isOpenBracket(bracket.previousSibling)) + ) break; + if (isClosingBracket(bracket.previousSibling)) nestedCounter++; + else if (isOpenBracket(bracket.previousSibling)) nestedCounter--; + bracket.previousSibling!.parentNode!.removeChild(bracket.previousSibling!); + } + if (detach) { + bracket.previousSibling!.parentNode!.removeChild(bracket.previousSibling!); + bracket.parentNode!.removeChild(bracket); + } + } else { + bracket.innerHTML = ''; } } @@ -692,14 +757,14 @@ namespace domHelpers { return builder; } - function isOpeningBoundary(node: Node): boolean { - if (node instanceof Comment && node.textContent == 'ContentBoundary {{') { + function isOpenBracket(node: Node): boolean { + if (node instanceof Comment && node.textContent == 'ContentBrackets {{') { return true; } return false; } - function isClosingBoundary(node: Node): boolean { + function isClosingBracket(node: Node): boolean { if (node instanceof Comment && node.textContent == '}}') { return true; } diff --git a/jsbits/wasm.ts b/jsbits/wasm.ts index 5803230..07707a9 100644 --- a/jsbits/wasm.ts +++ b/jsbits/wasm.ts @@ -2,7 +2,7 @@ import { WASI, File, OpenFile } from '@bjorn3/browser_wasi_shim'; // @ts-ignore import * as jsffi from './jsffi'; import * as p from './protocol'; -import { JavaScriptMessage, HaskellMessageTag, List, JavaScriptMessageTag } from './protocol'; +import { JavaScriptMessage, HaskellMessageTag, JavaScriptMessageTag } from './protocol'; export type HaskellPointer = number; @@ -43,14 +43,14 @@ export function storeBuffer(exports: HaskellExports, u8array: Uint8Array): Haske export function evalMessage(exports: HaskellExports, ptr: HaskellPointer): HaskellPointer { const inbuf = loadBuffer(exports, ptr); const hmsg = p.haskellMessage.decode(inbuf); - const jsCallback = (jsmsg: JavaScriptMessage, _argScope: List) => { + const haskellCallback = (jsmsg: JavaScriptMessage) => { const outbuf = p.javascriptMessage.encode(jsmsg); const ptr = storeBuffer(exports, outbuf); exports.wasm_app(ptr); }; switch (hmsg.tag) { case HaskellMessageTag.EvalExpr: { - const result = p.evalExpr(jsCallback, [globalThis, null], null, hmsg.expr); + const result = p.evalExpr(hmsg.expr, { haskellCallback }); const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, value: p.unknownToValue(result), threadId: hmsg.threadId }; const outbuf = p.javascriptMessage.encode(jsmsg); return storeBuffer(exports, outbuf); diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs index cf21fae..c8ad8d7 100644 --- a/src/Clickable/Core.hs +++ b/src/Clickable/Core.hs @@ -30,7 +30,7 @@ import Clickable.Protocol.Value newVar :: a -> ClickM (DynVar a) newVar a = do ref <- liftIO $ newIORef a - let mkEv s = unsafeFromEventId $ EventId $ Int32Le s.next_id + let mkEv s = unsafeFromEventId $ EventId s.next_id state \s -> (SourceVar (mkEv s) ref, s {next_id = s.next_id + 1}) overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a @@ -140,72 +140,72 @@ newCallback k = reactive $ Internal.newCallback k ------------------ el :: Text -> HtmlM a -> HtmlM a -el t = lift . insertHtml (DomBuilder (CreateElement t)) +el t = lift . customizeHtml True (DomBuilder (CreateElement t)) elns :: Text -> Text -> HtmlM a -> HtmlM a -elns ns t = lift . insertHtml (DomBuilder (CreateElementNS ns t)) +elns ns t = lift . customizeHtml True (DomBuilder (CreateElementNS ns t)) property :: ToValue a => Text -> a -> HtmlM () property k v = lift $ modify f where f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = ElementProp builderContext k (toExpr v) + expr = ElementProp k (toExpr v) attribute :: Text -> Text -> HtmlM () attribute k v = lift $ modify f where f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = ElementAttr builderContext k v + expr = ElementAttr k v text :: Text -> HtmlM () text t = lift $ modify f where f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = InsertNode builderContext $ CreateTextNode t + expr = InsertNode $ CreateTextNode t dynText :: DynVal Text -> HtmlM () dynText val = do t <- lift $ readVal val v <- lift $ newVarId lift $ modify $ f v t - lift $ subscribe val $ enqueueExpr . UpdateTextNode (DomBuilder (Var v)) + lift $ subscribe val $ enqueueExpr . UpdateTextNode (Var v) where f v t s = s {evaluation_queue = expr v t : s.evaluation_queue } - expr v t = InsertNode builderContext $ AssignVar v $ CreateTextNode t + expr v t = InsertNode $ AssignVar v $ CreateTextNode t dynProp :: ToValue a => Text -> DynVal a -> HtmlM () dynProp k val = do t <- lift $ readVal val - v <- saveCurrentBuilder + v <- saveDomBuilder lift $ modify $ f t - lift $ subscribe val $ enqueueExpr . ElementProp (DomBuilder (Var v)) k . toExpr + lift $ subscribe val $ enqueueExpr . SupplyDomBuilder (DomBuilder (Var v)) . ElementProp k . toExpr where f v s = s {evaluation_queue = expr v : s.evaluation_queue } - expr v = ElementProp builderContext k (toExpr v) + expr v = ElementProp k (toExpr v) dynAttr :: Text -> DynVal Text -> HtmlM () dynAttr k val = do t <- lift $ readVal val - v <- saveCurrentBuilder + v <- saveDomBuilder lift $ modify $ f t - lift $ subscribe val $ enqueueExpr . ElementAttr (DomBuilder (Var v)) k + lift $ subscribe val $ enqueueExpr . SupplyDomBuilder (DomBuilder (Var v)) . ElementAttr k where f v s = s {evaluation_queue = expr v : s.evaluation_queue } - expr v = ElementAttr builderContext k v + expr v = ElementAttr k v toggleClass :: Text -> DynVal Bool -> HtmlM () toggleClass className val = do scope <- lift $ asks (.scope) v <- lift $ readVal val - n <- saveCurrentBuilder + n <- saveDomBuilder let initCmd False queue = queue - initCmd True queue = InsertClassList builderContext [className] : queue - updateCmd False = RemoveClassList (DomBuilder (Var n)) [className] - updateCmd True = InsertClassList (DomBuilder (Var n)) [className] + initCmd True queue = ClassListAdd [className] : queue + updateCmd False = SupplyDomBuilder (DomBuilder (Var n)) $ ClassListRemove [className] + updateCmd True = SupplyDomBuilder (DomBuilder (Var n)) $ ClassListAdd [className] lift $ modify \s -> s {evaluation_queue = initCmd v s.evaluation_queue} lift $ subscribe val $ enqueueExpr . updateCmd dynClassList :: DynVal [Text] -> HtmlM () dynClassList dynList = do - n <- saveCurrentBuilder + n <- saveDomBuilder scope <- lift $ asks (.scope) initVal <- lift $ readVal dynList let @@ -219,15 +219,15 @@ dynClassList dynList = do return (added, removed, newList) updateCmd ([], [], _) queue = queue updateCmd (added, [], _) queue = - InsertClassList (DomBuilder (Var n)) added : queue + SupplyDomBuilder (DomBuilder (Var n)) (ClassListAdd added) : queue updateCmd ([], removed, _) queue = - RemoveClassList (DomBuilder (Var n)) removed : queue - updateCmd (added, removed, _) queue = - RemoveClassList (DomBuilder (Var n)) removed : InsertClassList (DomBuilder (Var n)) added : queue - modQueue f = modify \s -> s - { evaluation_queue = f s.evaluation_queue - } - lift $ enqueueExpr $ InsertClassList builderContext initVal + SupplyDomBuilder (DomBuilder (Var n)) (ClassListRemove removed) : queue + updateCmd (added, removed, _) queue + = SupplyDomBuilder (DomBuilder (Var n)) (ClassListRemove removed) + : SupplyDomBuilder (DomBuilder (Var n)) (ClassListAdd added) + : queue + modQueue f = modify \s -> s {evaluation_queue = f s.evaluation_queue} + lift $ enqueueExpr $ ClassListAdd initVal lift $ Internal.subscribeAccum dynList k ([], [], initVal) --------------------- @@ -236,15 +236,15 @@ dynClassList dynList = do dyn :: DynVal (HtmlM ()) -> HtmlM () dyn val = do - boundary <- lift insertBoundary + brackets <- lift insertBrackets scope <- lift newScope initialVal <- lift $ readVal val let update html = do - lift $ clearBoundary boundary + lift $ clearBrackets brackets html exec h = - customizeHtml (DomBuilder (Var boundary)) h + customizeHtml False (DomBuilder (Var brackets)) h & local (\s -> s {scope}) lift $ exec $ update initialVal lift $ subscribe val $ \newVal -> do @@ -253,7 +253,7 @@ dyn val = do -- | Auxilliary datatype used in 'simpleList' implementation data ElemEnv a = ElemEnv - { boundary :: VarId + { brackets :: VarId , state_var :: DynVar a , elem_scope :: ResourceScope } @@ -270,12 +270,12 @@ simpleList -> HtmlM () simpleList listDyn h = lift do internalStateRef <- liftIO $ newIORef ([] :: [ElemEnv a]) - boundary <- insertBoundary + brackets <- insertBrackets let - exec boundary scope h = - customizeHtml (DomBuilder (Var boundary)) h - & local (\s -> s {scope}) - exec1 boundary = customizeHtml (DomBuilder (Var boundary)) + exec brackets scope h = + customizeHtml False (DomBuilder (Var brackets)) h + & local (\s -> s {scope}) + exec1 brackets = customizeHtml False (DomBuilder (Var brackets)) setup :: Int -> [a] -> [ElemEnv a] -> ClickM [ElemEnv a] setup idx new existing = case (existing, new) of @@ -283,7 +283,7 @@ simpleList listDyn h = lift do -- New list is longer, append new elements ([], x:xs) -> do e <- newElem idx x - exec e.boundary e.elem_scope $ h idx e.state_var + exec e.brackets e.elem_scope $ h idx e.state_var fmap (e:) $ setup (idx + 1) xs [] -- New list is shorter, delete the elements that no longer -- present in the new list @@ -299,62 +299,62 @@ simpleList listDyn h = lift do elem_scope <- newScope local (\s -> s {scope = elem_scope}) do state_var <- newVar a - boundary <- insertBoundary - return ElemEnv {elem_scope, state_var, boundary} + brackets <- insertBrackets + return ElemEnv {elem_scope, state_var, brackets} finalizeElems :: Bool -> [ElemEnv a] -> ClickM () finalizeElems remove = mapM_ \ee -> do - when remove $ destroyBoundary ee.boundary + when remove $ detachBrackets ee.brackets freeScope True ee.elem_scope updateList new = do eenvs <- liftIO $ readIORef internalStateRef newEenvs <- setup 0 new eenvs liftIO $ writeIORef internalStateRef newEenvs initialVal <- readVal listDyn - exec1 boundary $ lift $ updateList initialVal - subscribe listDyn $ exec1 boundary . lift . updateList + exec1 brackets $ lift $ updateList initialVal + subscribe listDyn $ exec1 brackets . lift . updateList + +-- | Parse given text as HTML and attach the resulting tree to +-- 'html_current_element'. This way you can create not only HTML but +-- anything that @innerHTML@ property can create (e.g. SVG) +-- +-- > -- Create a div with an SVG image inside that shows a black +-- > -- circle +-- > div_ [] do +-- > unsafeHtml "\ +-- > \\ +-- > \" +unsafeHtml :: Text -> HtmlM () +unsafeHtml rawHtml = lift $ enqueueExpr (Internal.unsafeInsertHtml rawHtml) + +-- | Attach resulting DOM to the given node instead of where it +-- supposed to go given the cotext it used in. Might be useful for +-- implementing modal dialogs, tooltips etc. Similar to what called +-- portals in React ecosystem +portal :: DomBuilder -> HtmlM a -> HtmlM a +portal newRootEl html = + lift $ customizeHtml False newRootEl do + brackets <- lift insertBrackets + result <- lift $ customizeHtml False (DomBuilder (Var brackets)) html + lift $ installFinalizer $ detachBrackets brackets + return result + +blank :: Applicative m => m () +blank = pure () ---------------------------- -- AUXILLIARY DEFINITIONS -- ---------------------------- -insertHtml :: DomBuilder -> HtmlM a -> ClickM a -insertHtml builder content = do - prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - result <- evalStateT content.unHtmlT Nothing - let mkExpr revSeq = InsertNode builderContext (Lam (RevSeq (Arg 0 0 : revSeq)) `Apply` [builder.unDomBuilder]) - modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} - return result - -customizeHtml :: DomBuilder -> HtmlM a -> ClickM a -customizeHtml builder content = do +customizeHtml :: Bool -> DomBuilder -> HtmlM a -> ClickM a +customizeHtml doInsert builder content = do prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) result <- evalStateT content.unHtmlT Nothing - let mkExpr revSeq = Lam (RevSeq (Arg 0 0 : revSeq)) `Apply` [builder.unDomBuilder] modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} return result - -saveCurrentBuilder :: HtmlM VarId -saveCurrentBuilder = do - alreadySaved <- HtmlT get - case alreadySaved of - Nothing -> do - varId <- lift newVarId - HtmlT $ put $ Just varId - lift $ enqueueExpr $ AssignVar varId builderContext.unDomBuilder - return varId - Just saved -> return saved - -insertBoundary :: ClickM VarId -insertBoundary = do - boundary <- newVarId - enqueueExpr $ AssignVar boundary (InsertBoundary builderContext) - return boundary - -clearBoundary :: VarId -> ClickM () -clearBoundary boundary = enqueueExpr (ClearBoundary (DomBuilder (Var boundary)) False) - -destroyBoundary :: VarId -> ClickM () -destroyBoundary boundary = enqueueExpr (ClearBoundary (DomBuilder (Var boundary)) True) + where + mkExpr seq + | doInsert = InsertNode $ SupplyDomBuilder builder $ RevSeq (AskDomBuilder : seq) + | otherwise = SupplyDomBuilder builder $ RevSeq (AskDomBuilder : seq) attachHtml :: DomBuilder -> HtmlM a -> ClickM a attachHtml rootEl contents = do @@ -363,40 +363,37 @@ attachHtml rootEl contents = do modify (enqueueHtml savedQueue) where enqueueHtml saved s = s {evaluation_queue = e : saved} where - e = Lam (RevSeq (Arg 0 0 : s.evaluation_queue)) `Apply` [rootEl.unDomBuilder] + e = SupplyDomBuilder rootEl (RevSeq s.evaluation_queue) saveQueue s = (s.evaluation_queue, s {evaluation_queue = []}) attachToBody :: HtmlM a -> ClickM a -attachToBody = attachHtml (DomBuilder (Id "document" `Dot` "body")) +attachToBody = attachHtml $ DomBuilder $ Id "document" `Dot` "body" -blank :: Applicative m => m () -blank = pure () +saveDomBuilder :: HtmlM VarId +saveDomBuilder = do + alreadySaved <- HtmlT get + case alreadySaved of + Nothing -> do + varId <- lift newVarId + HtmlT $ put $ Just varId + lift $ enqueueExpr $ AssignVar varId AskDomBuilder + return varId + Just saved -> return saved --- | Parse given text as HTML and attach the resulting tree to --- 'html_current_element'. This way you can create not only HTML but --- anything that @innerHTML@ property can create (e.g. SVG) --- --- > -- Create a div with an SVG image inside that shows a black --- > -- circle --- > div_ [] do --- > unsafeHtml "\ --- > \\ --- > \" -unsafeHtml :: Text -> HtmlM () -unsafeHtml rawHtml = lift $ enqueueExpr (Internal.unsafeInsertHtml rawHtml) +insertBrackets :: ClickM VarId +insertBrackets = do + brackets <- newVarId + enqueueExpr $ AssignVar brackets InsertBrackets + return brackets --- | Attach resulting DOM to the given node instead of where it --- supposed to go given the cotext it used in. Might be useful for --- implementing modal dialogs, tooltips etc. Similar to what called --- portals in React ecosystem -portal :: DomBuilder -> HtmlM a -> HtmlM a -portal newRootEl html = - lift $ customizeHtml newRootEl do - boundary <- lift $ insertBoundary - result <- lift $ customizeHtml (DomBuilder (Var boundary)) html - lift $ installFinalizer $ destroyBoundary boundary - return result +clearBrackets :: VarId -> ClickM () +clearBrackets n = + enqueueExpr $ SupplyDomBuilder (DomBuilder (Var n)) $ ClearBrackets False + +detachBrackets :: VarId -> ClickM () +detachBrackets n = + enqueueExpr $ SupplyDomBuilder (DomBuilder (Var n)) $ ClearBrackets True instance (a ~ ()) => IsString (HtmlM a) where fromString = text . Text.pack diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index 729dc33..99f969a 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -1,17 +1,16 @@ module Clickable.DOM where import Control.Monad.Reader -import Data.Foldable import Data.Int import Data.Kind import Data.Text (Text) import GHC.Generics import Unsafe.Coerce -import Clickable.Types +import Clickable.Internal import Clickable.Protocol import Clickable.Protocol.Value -import Clickable.Internal +import Clickable.Types data EventListenerOptions = EventListenerOptions @@ -25,211 +24,174 @@ defaultEventListenerOptions = EventListenerOptions , stop_propagation = False } -addEventListener :: ConnectResourceArgs callback -> callback -> HtmlM () -addEventListener args k = lift $ connectResource args k - -data ConnectResourceArgs callback = ConnectResourceArgs - { aquire_resource :: ResourceScope -> EventId -> Expr - -- ^ When evaluated, as a side-effect resulting `Expr` must - -- initialize some resource (could be DOM event, WebSocket - -- connection etc) also must return a function that frees that - -- resource - , mk_callback :: callback -> Value -> ClickM () +-- | A snippet of JavaScript that subscribes to certain event. It +-- should return a function that revokes the subscribtion. The typical +-- usage will involve addEventListener/removeEventListener but it's +-- not limited to this use case. Same method can be used to establish +-- WebSocket connection or any other source of events in browser +newtype ConnectEventScript a = ConnectEventScript + { unConnectEventScript :: Event a -> Expr } -connectResource :: ConnectResourceArgs callback -> callback -> ClickM () -connectResource args k = reactive_ \scope s -> - let - k' :: Value -> ClickM () - k' = local (\e -> e {scope}) . args.mk_callback k - event = unsafeFromEventId eventId - eventId = EventId $ Int32Le s.next_id - newSub = SubscriptionSimple scope event (k' . unsafeCoerce) - connectExpr = ConnectResource scope $ args.aquire_resource scope eventId - in - s { evaluation_queue = connectExpr : s.evaluation_queue - , subscriptions = newSub : s.subscriptions - , next_id = s.next_id + 1 - } - -on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HtmlM () -on k = addEventListener (addEventListenerArgs @eventName) k +addEventListener :: FromValue a => ConnectEventScript a -> (a -> ClickM ()) -> ClickM () +addEventListener (ConnectEventScript ces) k = reactive_ \scope s -> + let k' :: Value -> ClickM () + k' = local (\e -> e {scope}) . mapM_ k . fromValue + eventId = EventId s.next_id + newSub = SubscriptionSimple scope (unsafeFromEventId eventId) (k' . unsafeCoerce) + connectExpr = ConnectResource scope $ ces $ unsafeFromEventId eventId + in s { evaluation_queue = connectExpr : s.evaluation_queue + , subscriptions = newSub : s.subscriptions + , next_id = s.next_id + 1 + } class IsEventName eventName where type EventListenerCb eventName :: Type - addEventListenerArgs :: ConnectResourceArgs (EventListenerCb eventName) + connectEventName :: EventListenerCb eventName -> ClickM () + +on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HtmlM () +on k = lift $ connectEventName @eventName k instance IsEventName "click" where type EventListenerCb "click" = ClickM () - addEventListenerArgs = pointerConnectArgs "click" + connectEventName k = addEventListener + (genericEvent defaultEventListenerOptions "click") (const k) instance IsEventName "mousedown" where type EventListenerCb "mousedown" = ClickM () - addEventListenerArgs = pointerConnectArgs "mousedown" + connectEventName k = addEventListener + (genericEvent defaultEventListenerOptions "mousedown") (const k) instance IsEventName "mouseup" where type EventListenerCb "mouseup" = ClickM () - addEventListenerArgs = pointerConnectArgs "mouseup" + connectEventName k = addEventListener + (genericEvent defaultEventListenerOptions "mouseup") (const k) instance IsEventName "dblclick" where type EventListenerCb "dblclick" = ClickM () - addEventListenerArgs = pointerConnectArgs "dblclick" + connectEventName k = addEventListener + (genericEvent defaultEventListenerOptions "dblclick") (const k) instance IsEventName "submit" where type EventListenerCb "submit" = ClickM () - addEventListenerArgs = submitConnectArgs + connectEventName k = addEventListener (genericEvent opt "submit") (const k) + where + opt = EventListenerOptions + { prevent_default = True + , stop_propagation = True + } instance IsEventName "input" where type EventListenerCb "input" = Text -> ClickM () - addEventListenerArgs = inputConnectArgs "input" + connectEventName = addEventListener (inputEvent "input") instance IsEventName "keydown" where type EventListenerCb "keydown" = Int32 -> ClickM () - addEventListenerArgs = keyboardConnectArgs "keydown" + connectEventName = addEventListener (keyboardEvent "keydown") instance IsEventName "keyup" where type EventListenerCb "keyup" = Int32 -> ClickM () - addEventListenerArgs = keyboardConnectArgs "keyup" + connectEventName = addEventListener (keyboardEvent "keyup") instance IsEventName "focus" where type EventListenerCb "focus" = ClickM () - addEventListenerArgs = pointerConnectArgs "focus" + connectEventName k = addEventListener + (genericEvent defaultEventListenerOptions "focus") (const k) instance IsEventName "blur" where type EventListenerCb "blur" = ClickM () - addEventListenerArgs = pointerConnectArgs "blur" + connectEventName k = addEventListener + (genericEvent defaultEventListenerOptions "blur") (const k) instance IsEventName "input/blur" where type EventListenerCb "input/blur" = Text -> ClickM () - addEventListenerArgs = inputConnectArgs "blur" + connectEventName = addEventListener (inputEvent "blur") instance IsEventName "input/focus" where type EventListenerCb "input/focus" = Text -> ClickM () - addEventListenerArgs = inputConnectArgs "focus" + connectEventName = addEventListener (inputEvent "focus") instance IsEventName "checkbox/change" where type EventListenerCb "checkbox/change" = Bool -> ClickM () - addEventListenerArgs = checkboxChangeConnectArgs + connectEventName = addEventListener checkboxChangeEvent instance IsEventName "select/change" where type EventListenerCb "select/change" = Text -> ClickM () - addEventListenerArgs = selectChangeConnectArgs + connectEventName = addEventListener selectChangeEvent instance IsEventName "mousewheel" where type EventListenerCb "mousewheel" = MouseWheel -> ClickM () - addEventListenerArgs = mouseWheelConnectArgs - -eventListenerOptions :: Text -> Bool -> Bool -> ConnectResourceArgs (ClickM ()) -eventListenerOptions eventName preventDef stopProp = ConnectResourceArgs - { aquire_resource = \scope sourceId -> - Eval (normalEventWrapper eventName $ EventListenerOptions preventDef stopProp) - `Apply` [Arg 0 0, Lam (TriggerEvent sourceId Null)] - , mk_callback = \k _ -> k - } + connectEventName = addEventListener mouseWheelEvent -- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event -pointerConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) -pointerConnectArgs eventName = ConnectResourceArgs - { aquire_resource = \scope sourceId -> - Eval (normalEventWrapper eventName defaultEventListenerOptions) - `Apply` [Arg 0 0, Lam (TriggerEvent sourceId Null)] - , mk_callback = \k _ -> k - } - --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event -submitConnectArgs :: ConnectResourceArgs (ClickM ()) -submitConnectArgs = ConnectResourceArgs - { aquire_resource = \scope sourceId -> - Eval (normalEventWrapper "submit" EventListenerOptions - { prevent_default = True - , stop_propagation = True - }) `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] - , mk_callback = \k _ -> k - } +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event +genericEvent :: EventListenerOptions -> Text -> ConnectEventScript () +genericEvent opt eventName = ConnectEventScript \(Event eventId) -> + Eval + ("(function(target, trigger){\n\ + \ function listener(event){\n\ + \ " <> preventDefaultStmt <> "\n\ + \ " <> stopPropagationStmt <> "\n\ + \ trigger();\n\ + \ }\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \})") `Apply` [AskDomBuilder, Lam (TriggerEvent eventId Null)] + where + preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" + stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event -inputConnectArgs :: Text -> ConnectResourceArgs (Text -> ClickM ()) -inputConnectArgs eventName = ConnectResourceArgs - { aquire_resource = \scope sourceId -> Eval - ("(function(target, haskellCb){\n\ - \ function listener(event){\n\ - \ haskellCb(event.target.value);\n\ - \ }\n\ - \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \ return () => window.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromValue event) k - } +inputEvent :: Text -> ConnectEventScript Text +inputEvent eventName = ConnectEventScript \(Event eventId) -> + Eval + ("(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger(event.target.value);\n\ + \ }\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \})") `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardConnectArgs :: Text -> ConnectResourceArgs (Int32 -> ClickM ()) -keyboardConnectArgs eventName = ConnectResourceArgs - { aquire_resource = \scope sourceId -> Eval ( - "(function(target, haskellCb){\n\ - \ function listener(event){\n\ - \ haskellCb(event.keyCode);\n\ - \ }\n\ - \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromValue event) k - } - --- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event -focusConnectArgs :: Text -> ConnectResourceArgs (ClickM ()) -focusConnectArgs eventName = ConnectResourceArgs - { aquire_resource = \scope sourceId -> - Eval (normalEventWrapper eventName defaultEventListenerOptions) - `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] - , mk_callback = \k _ -> k - } +keyboardEvent :: Text -> ConnectEventScript Int32 +keyboardEvent eventName = ConnectEventScript \(Event eventId) -> + Eval + ("(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger(event.keyCode);\n\ + \ }\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \})") `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -checkboxChangeConnectArgs :: ConnectResourceArgs (Bool -> ClickM ()) -checkboxChangeConnectArgs = ConnectResourceArgs - { aquire_resource = \scope sourceId -> Eval - "(function(target, haskellCb){\n\ - \ function listener(event){\n\ - \ haskellCb(event.target.checked);\n\ - \ }\n\ - \ target.addEventListener('change', listener);\n\ - \ return () => window.removeEventListener('change', listener);\n\ - \})" `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromValue event) k - } +checkboxChangeEvent :: ConnectEventScript Bool +checkboxChangeEvent = ConnectEventScript \(Event eventId) -> + Eval + "(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger(event.target.checked);\n\ + \ }\n\ + \ target.addEventListener('change', listener);\n\ + \ return () => target.removeEventListener('change', listener);\n\ + \})" `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -selectChangeConnectArgs :: ConnectResourceArgs (Text -> ClickM ()) -selectChangeConnectArgs = ConnectResourceArgs - { aquire_resource = \scope sourceId -> Eval - "(function(target, haskellCb){\n\ - \ function listener(event){\n\ - \ haskellCb(event.target.value);\n\ - \ }\n\ - \ target.addEventListener('change', listener);\n\ - \ return () => target.removeEventListener('change', listener);\n\ - \})" `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromValue event) k - } - -normalEventWrapper :: Text -> EventListenerOptions -> UnsafeJavaScript -normalEventWrapper eventName opt = - "(function(target, haskellCb){\n\ - \ function listener(event){\n\ - \ " <> preventDefaultStmt <> "\n\ - \ " <> stopPropagationStmt <> "\n\ - \ haskellCb(event);\n\ - \ }\n\ - \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})" - where - preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" - stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" +selectChangeEvent :: ConnectEventScript Text +selectChangeEvent = ConnectEventScript \(Event eventId) -> + Eval + "(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger(event.target.value);\n\ + \ }\n\ + \ target.addEventListener('change', listener);\n\ + \ return () => target.removeEventListener('change', listener);\n\ + \})" `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] data Location = Location { protocol :: Text @@ -252,25 +214,23 @@ data Location = Location deriving anyclass (FromValue, ToValue) -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event -popstateConnectArgs :: ConnectResourceArgs (Location -> ClickM ()) -popstateConnectArgs = ConnectResourceArgs - { aquire_resource = \scope sourceId -> Eval - "(function(target, haskellCb){\n\ - \ function listener(){\n\ - \ haskellCb({\n\ - \ protocol: location.protocol,\n\ - \ hostname: location.hostname,\n\ - \ port: location.port,\n\ - \ pathname: location.pathname,\n\ - \ search: location.search,\n\ - \ hash: location.hash\n\ - \ });\n\ - \ }\n\ - \ target.addEventListener('popstate', listener);\n\ - \ return () => target.removeEventListener('popstate', listener);\n\ - \})" `Apply` [Id "window", Lam (TriggerEvent sourceId (Arg 0 0))] - , mk_callback = \k event -> forM_ (fromValue event) k - } +popstateEvent :: ConnectEventScript Location +popstateEvent = ConnectEventScript \(Event eventId) -> + Eval + "(function(target, trigger){\n\ + \ function listener(){\n\ + \ trigger({\n\ + \ protocol: location.protocol,\n\ + \ hostname: location.hostname,\n\ + \ port: location.port,\n\ + \ pathname: location.pathname,\n\ + \ search: location.search,\n\ + \ hash: location.hash\n\ + \ });\n\ + \ }\n\ + \ target.addEventListener('popstate', listener);\n\ + \ return () => target.removeEventListener('popstate', listener);\n\ + \})" `Apply` [Id "window", Lam (TriggerEvent eventId (Arg 0 0))] -- | Collection of deltaX, deltaY and deltaZ properties from WheelEvent -- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent @@ -286,23 +246,21 @@ data MouseWheel = MouseWheel deriving anyclass (FromValue, ToValue) -- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent -mouseWheelConnectArgs :: ConnectResourceArgs (MouseWheel -> ClickM ()) -mouseWheelConnectArgs = ConnectResourceArgs - { mk_callback = \k j -> forM_ (fromValue j) k - , aquire_resource = \scope sourceId -> Eval - "(function(target, haskellCb){\n\ - \ function listener(event){\n\ - \ haskellCb({\n\ - \ mw_delta_x: event.deltaX,\n\ - \ mw_delta_y: event.deltaY,\n\ - \ mw_delta_z: event.deltaZ,\n\ - \ mw_alt_key: event.altKey,\n\ - \ mw_ctrl_key: event.ctrlKey,\n\ - \ mw_meta_key: event.metaKey,\n\ - \ mw_shift_key: event.shiftKey\n\ - \ });\n\ - \ }\n\ - \ target.addEventListener('popstate', listener);\n\ - \ return () => target.removeEventListener('popstate', listener);\n\ - \})" `Apply` [Arg 0 0, Lam (TriggerEvent sourceId (Arg 0 0))] - } +mouseWheelEvent :: ConnectEventScript MouseWheel +mouseWheelEvent = ConnectEventScript \(Event eventId) -> + Eval + "(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger({\n\ + \ mw_delta_x: event.deltaX,\n\ + \ mw_delta_y: event.deltaY,\n\ + \ mw_delta_z: event.deltaZ,\n\ + \ mw_alt_key: event.altKey,\n\ + \ mw_ctrl_key: event.ctrlKey,\n\ + \ mw_meta_key: event.metaKey,\n\ + \ mw_shift_key: event.shiftKey\n\ + \ });\n\ + \ }\n\ + \ target.addEventListener('mousewheel', listener);\n\ + \ return () => target.removeEventListener('mousewheel', listener);\n\ + \})" `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs index cfaa65f..686c430 100644 --- a/src/Clickable/Internal.hs +++ b/src/Clickable/Internal.hs @@ -20,7 +20,7 @@ emptyState = InternalState [] [] Map.empty [] 0 newInternalEnv :: (Expr -> IO Value) -> IO InternalEnv newInternalEnv eval_expr = do - let scope = ResourceScope $ Int32Le emptyState.next_id + let scope = ResourceScope $ emptyState.next_id internal_state_ref <- newIORef emptyState {next_id = emptyState.next_id + 1} return InternalEnv {internal_state_ref, scope, eval_expr} @@ -47,12 +47,10 @@ triggerEvent eventId a = newScope :: ResourceScope -> InternalState -> (InternalState, ResourceScope) newScope p s = - let - scopeId = ResourceScope $ Int32Le s.next_id - finalizers = ScopeFinalizer p scopeId : s.finalizers - s' = s {finalizers, next_id = s.next_id + 1} - in - (s', scopeId) + let scopeId = ResourceScope $ s.next_id + finalizers = ScopeFinalizer p scopeId : s.finalizers + s' = s {finalizers, next_id = s.next_id + 1} + in (s', scopeId) newVarId :: ResourceScope -> InternalState -> (InternalState, VarId) newVarId e s = (s {next_id = s.next_id + 1}, VarId e $ Int32Le s.next_id) @@ -62,16 +60,14 @@ freeScope :: ResourceScope -> InternalState -> (InternalState, [Finalizer]) freeScope unlink rscope s = - let - chkSub s = subscriptionScope s /= rscope - chkFin True ScopeFinalizer{sf_resource_scope, sf_linked_scope} = - sf_resource_scope /= rscope && sf_linked_scope /= rscope - chkFin True CustomFinalizer{cf_resource_scope} = cf_resource_scope /= rscope - chkFin False f = finalizerScope f /= rscope - (finalizers, scopeFns) = List.partition (chkFin unlink) s.finalizers - subscriptions = List.filter chkSub s.subscriptions - in - (s {subscriptions, finalizers}, scopeFns) + let chkSub s = subscriptionScope s /= rscope + chkFin True ScopeFinalizer{sf_resource_scope, sf_linked_scope} = + sf_resource_scope /= rscope && sf_linked_scope /= rscope + chkFin True CustomFinalizer{cf_resource_scope} = cf_resource_scope /= rscope + chkFin False f = finalizerScope f /= rscope + (finalizers, scopeFns) = List.partition (chkFin unlink) s.finalizers + subscriptions = List.filter chkSub s.subscriptions + in (s {subscriptions, finalizers}, scopeFns) installFinalizer :: ClickM () -> ResourceScope -> InternalState -> InternalState installFinalizer k scope s = s {finalizers = CustomFinalizer scope k : s.finalizers} @@ -97,7 +93,7 @@ subscribe (SplatVal fv av) k = do { subscriptions = newsub : s.subscriptions , next_id = s.next_id + 1 } - event = unsafeFromEventId $ EventId $ Int32Le s.next_id + event = unsafeFromEventId $ EventId s.next_id newsub = SubscriptionSimple scope event (k . unsafeCoerce) f src fv' = do av' <- readVal av @@ -134,7 +130,7 @@ subscribeAccum (SplatVal fv av) k b = do { subscriptions = newsub : s.subscriptions , next_id = s.next_id + 1 } - event = unsafeFromEventId $ EventId $ Int32Le s.next_id + event = unsafeFromEventId $ EventId s.next_id newsub = SubscriptionAccum scope event (k . unsafeCoerce) ref f src fv' = do av' <- readVal av @@ -166,7 +162,7 @@ newCallback :: InternalState -> (InternalState, Event a) newCallback k rscope s = let - event = unsafeFromEventId $ EventId $ Int32Le s.next_id + event = unsafeFromEventId $ EventId s.next_id new = SubscriptionSimple rscope (coerce event) (k . unsafeCoerce) subscriptions = new : s.subscriptions in @@ -229,7 +225,7 @@ mapHoldVal f da = do reactive $ g ref where g ref scope s = (s', val) where - event = unsafeFromEventId $ EventId $ Int32Le s.next_id + event = unsafeFromEventId $ EventId s.next_id newSub = SubscriptionSimple scope (coerce event) (k . unsafeCoerce) k a = do let b = f a @@ -252,4 +248,4 @@ unsafeInsertHtml rawHtml = Eval \ builder.appendChild(iter);\ \ }\ \}\ - \})" `Apply` [Arg 0 0, Str rawHtml] + \})" `Apply` [AskDomBuilder, Str rawHtml] diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 04dbc04..7033c85 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -318,4 +318,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>R,D:()=>C,Gk:()=>A,HA:()=>U,HQ:()=>w,In:()=>L,K2:()=>v,PV:()=>j,Sj:()=>B,Tf:()=>k,YE:()=>m,YO:()=>K,Yj:()=>S,b9:()=>W,g1:()=>V,l8:()=>I,tB:()=>H});var n=r(366);class _{encode(e){const t=M(this,e),r=new Uint8Array(t);return O(this,r,0,e),r}decode(e){const[t,r]=h(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class c extends _{}class l extends _{}class E extends _{}class p extends _{}class u extends _{}class f extends _{}class d extends _{}class g extends _{}class b extends _{constructor(e){super(),this._element=e}}class D extends _{constructor(e){super(),this._description=e}}class x extends _{constructor(e){super(),this._alternatives=e}}class y extends _{constructor(e){super(),this._self=e}}class T extends _{constructor(e){super(),this._tuple=e}}function M(e,t){if(e instanceof a)return 1;if(e instanceof s)return 2;if(e instanceof i)return 4;if(e instanceof o)return 8;if(e instanceof c)return 1;if(e instanceof l)return 2;if(e instanceof E)return 4;if(e instanceof p)return 8;if(e instanceof u)return 4;if(e instanceof f)return 8;if(e instanceof g){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof d)return 8+t.length;if(e instanceof b){const r=8;return t.reduce(((t,r)=>t+M(e._element,r)),r)}if(e instanceof D){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+M(e._description[n],r[n])),0)}if(e instanceof x){const r=t;return P(Object.keys(e._alternatives).length)+M(e._alternatives[r.tag],r)}if(e instanceof y)return M(e._self,t);if(e instanceof T){const r=t;return e._tuple.reduce(((e,t,n)=>e+M(t,r[n])),0)}return(0,n.G)(e)}function h(e,t,r){const _=new DataView(t.buffer);if(e instanceof a)return[_.getInt8(r),r+1];if(e instanceof s)return[_.getInt16(r,!0),r+2];if(e instanceof i)return[_.getInt32(r,!0),r+4];if(e instanceof o)return[_.getBigInt64(r,!0),r+8];if(e instanceof c)return[t[r],r+1];if(e instanceof l)return[_.getUint8(r),r+1];if(e instanceof E)return[_.getUint32(r,!0),r+4];if(e instanceof p)return[_.getBigUint64(r,!0),r+8];if(e instanceof u)return[_.getFloat32(r,!0),r+4];if(e instanceof f)return[_.getFloat64(r,!0),r+8];if(e instanceof g){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof d){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof b){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=h(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof x){const n=P(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=h(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof y)return h(e._self,t,r);if(e instanceof T){let n=r;return[e._tuple.map((e=>{const[r,_]=h(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function O(e,t,r,_){const M=new DataView(t.buffer);if(e instanceof a)return M.setInt8(r,_),r+1;if(e instanceof s)return M.setInt16(r,_,!0),r+2;if(e instanceof i)return M.setInt32(r,_,!0),r+4;if(e instanceof o)return M.setBigInt64(r,_,!0),r+8;if(e instanceof c)return M.setUint8(r,_),r+1;if(e instanceof l)return M.setUint16(r,_,!0),r+2;if(e instanceof E)return M.setUint32(r,_,!0),r+4;if(e instanceof p)return M.setBigUint64(r,_,!0),r+8;if(e instanceof u)return M.setFloat32(r,_,!0),r+4;if(e instanceof f)return M.setFloat64(r,_,!0),r+8;if(e instanceof g){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof d){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof b){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=O(e,t,a,n[r])})),a}return(0,n.G)(e)}function P(e){return Math.ceil(Math.log2(e)/8)}const m=new a,I=new s,U=new i,A=new o,w=new c,B=new l,v=new E,C=new p,L=new u,R=new f,S=new g,W=new d;function K(e){return new b(e)}function V(e){return new D(e)}function k(e){return new x(e)}function j(...e){return new T(e)}function H(e){const t=new y(void 0),r=e(t);return t._self=r,r}var N;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(N||(N={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(hscb,idenScope,argScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I8:case ExprTag.I16:case ExprTag.I32:case ExprTag.I64:case ExprTag.U8:case ExprTag.U16:case ExprTag.U32:case ExprTag.U64:case ExprTag.F32:case ExprTag.F64:case ExprTag.Str:return exp[0];case ExprTag.Arr:return exp[0].map(evalExpr.bind(void 0,hscb,idenScope,argScope));case ExprTag.Obj:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalExpr(hscb,idenScope,argScope,t)])));case ExprTag.U8Arr:return exp[0];case ExprTag.Dot:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalExpr(hscb,idenScope,argScope,exp[2]),t=evalExpr(hscb,idenScope,argScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalExpr(hscb,idenScope,argScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=evalExpr(hscb,idenScope,argScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalExpr(hscb,idenScope,Cons(arguments,argScope),exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalExpr(hscb,idenScope,argScope,exp[0]);return e.apply(void 0,exp[1].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.Call:{const e=evalExpr(hscb,idenScope,argScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalExpr.bind(void 0,hscb,idenScope,argScope)))}case ExprTag.AssignVar:{const e=evalExpr(hscb,idenScope,argScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);if(!e)return;return e.delete(exp.varId),void(0==e.size&&varStorage.delete(exp.scopeId))}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.InsertNode:{const e=evalExpr(hscb,idenScope,argScope,exp.parent),t=evalExpr(hscb,idenScope,argScope,exp.child);return domHelpers.insertIntoBuilder(e,t),null}case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateText:return document.createTextNode(exp.content);case ExprTag.ElementProp:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=evalExpr(hscb,idenScope,argScope,exp.propValue);return domHelpers.assignProperty(e,exp.propName,t),null}case ExprTag.ElementAttr:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return domHelpers.assignAttribute(e,exp.attrName,exp.attrValue),null}case ExprTag.InsertClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.add(e))),null}case ExprTag.RemoveClassList:{const e=evalExpr(hscb,idenScope,argScope,exp.node),t=domHelpers.domBuilderElement(e);return exp.classList.forEach((e=>t.classList.remove(e))),null}case ExprTag.UpdateTextNode:{const e=evalExpr(hscb,idenScope,argScope,exp.node);return e.textContent=exp.content,null}case ExprTag.InsertBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.parent);return domHelpers.insertBoundary(e)}case ExprTag.ClearBoundary:{const e=evalExpr(hscb,idenScope,argScope,exp.boundary);return domHelpers.clearBoundary(e,Boolean(exp.detach))}case ExprTag.AddEventListener:{const e=evalExpr(hscb,idenScope,argScope,exp.target),t=evalExpr(hscb,idenScope,argScope,exp.eventName),r=evalExpr(hscb,idenScope,argScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalExpr(hscb,idenScope,argScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalExpr(hscb,idenScope,argScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalExpr(hscb,idenScope,argScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalExpr(hscb,idenScope,argScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerEvent:{const e=evalExpr(hscb,idenScope,argScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerEventMsg,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function evalUint8Array(e,t,r,n){return evalExpr(e,t,r,expr.decode(n))}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Vbool,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.Vi32,0:e}:{tag:ValueTag.Vf64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.Vstr,0:e};if(\"bigint\"==typeof e)return{tag:ValueTag.Vi64,0:e};if(Array.isArray(e))return{tag:ValueTag.Varr,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Vu8arr,0:e};if(null==e)return{tag:ValueTag.Vnull};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Vobj,0:t}}!function(e){e[e.Vnull=0]=\"Vnull\",e[e.Vbool=1]=\"Vbool\",e[e.Vi8=2]=\"Vi8\",e[e.Vi16=3]=\"Vi16\",e[e.Vi32=4]=\"Vi32\",e[e.Vi64=5]=\"Vi64\",e[e.Vu8=6]=\"Vu8\",e[e.Vu16=7]=\"Vu16\",e[e.Vu32=8]=\"Vu32\",e[e.Vu64=9]=\"Vu64\",e[e.Vf32=10]=\"Vf32\",e[e.Vf64=11]=\"Vf64\",e[e.Vstr=12]=\"Vstr\",e[e.Varr=13]=\"Varr\",e[e.Vobj=14]=\"Vobj\",e[e.Vu8arr=15]=\"Vu8arr\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Vnull]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Vbool]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ValueTag.Vi32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.Vi64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.Vu8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ValueTag.Vu16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ValueTag.Vu32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ValueTag.Vu64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ValueTag.Vf32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ValueTag.Vf64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.Vstr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Varr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Vobj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Vu8arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Plus=19]=\"Plus\",e[e.Subtract=20]=\"Subtract\",e[e.Multiply=21]=\"Multiply\",e[e.Divide=22]=\"Divide\",e[e.Id=23]=\"Id\",e[e.Lam=24]=\"Lam\",e[e.Arg=25]=\"Arg\",e[e.Apply=26]=\"Apply\",e[e.Call=27]=\"Call\",e[e.AssignVar=28]=\"AssignVar\",e[e.FreeVar=29]=\"FreeVar\",e[e.Var=30]=\"Var\",e[e.FreeScope=31]=\"FreeScope\",e[e.InsertNode=32]=\"InsertNode\",e[e.CreateElement=33]=\"CreateElement\",e[e.CreateElementNS=34]=\"CreateElementNS\",e[e.CreateText=35]=\"CreateText\",e[e.ElementProp=36]=\"ElementProp\",e[e.ElementAttr=37]=\"ElementAttr\",e[e.InsertClassList=38]=\"InsertClassList\",e[e.RemoveClassList=39]=\"RemoveClassList\",e[e.UpdateTextNode=40]=\"UpdateTextNode\",e[e.InsertBoundary=41]=\"InsertBoundary\",e[e.ClearBoundary=42]=\"ClearBoundary\",e[e.AddEventListener=43]=\"AddEventListener\",e[e.ConnectResource=44]=\"ConnectResource\",e[e.SetTimeout=45]=\"SetTimeout\",e[e.ApplyFinalizer=46]=\"ApplyFinalizer\",e[e.RevSeq=47]=\"RevSeq\",e[e.Eval=48]=\"Eval\",e[e.TriggerEvent=49]=\"TriggerEvent\",e[e.UncaughtException=50]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ExprTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ExprTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ExprTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ExprTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.Str]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Obj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.U8Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e,child:e}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateText]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.RemoveClassList]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.InsertBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({parent:e}),[ExprTag.ClearBoundary]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({boundary:e,detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerEventMsg=2]=\"TriggerEventMsg\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerEventMsg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map;var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBoundary {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBoundary=function(e){const r=document.createComment(\"ContentBoundary {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBoundary=function(e,t){const r=e;let _=0;for(;r.previousSibling&&(0!=_||!n(r.previousSibling));)(a=r.previousSibling)instanceof Comment&&\"}}\"==a.textContent?_++:n(r.previousSibling)&&_--,r.previousSibling.parentNode.removeChild(r.previousSibling);var a;t&&(r.previousSibling.parentNode.removeChild(r.previousSibling),r.parentNode.removeChild(r))},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=[window,null],_=58;class a{static read_bytes(e,t){const r=new a;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let _=0;_{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let E,p=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],c.enable(n.debug),this.args=e,this.env=t,this.fds=r;const _=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.args.length,!0);let n=0;for(const e of _.args)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.args.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.args[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},environ_sizes_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);r.setUint32(e,_.env.length,!0);let n=0;for(const e of _.env)n+=e.length+1;return r.setUint32(t,n,!0),c.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},environ_get(e,t){const r=new DataView(_.inst.exports.memory.buffer),n=new Uint8Array(_.inst.exports.memory.buffer),a=t;for(let a=0;a<_.env.length;a++){r.setUint32(e,t,!0),e+=4;const s=(new TextEncoder).encode(_.env[a]);n.set(s,t),r.setUint8(t+s.length,0),t+=s.length+1}return c.enabled&&c.log(new TextDecoder(\"utf-8\").decode(n.slice(a,t))),0},clock_res_get(e,t){let r;switch(e){case 1:r=5000n;break;case 0:r=1000000n;break;default:return 52}return new DataView(_.inst.exports.memory.buffer).setBigUint64(t,r,!0),0},clock_time_get(e,t,r){const n=new DataView(_.inst.exports.memory.buffer);if(0===e)n.setBigUint64(r,1000000n*BigInt((new Date).getTime()),!0);else if(1==e){let e;try{e=BigInt(Math.round(1e6*performance.now()))}catch(t){e=0n}n.setBigUint64(r,e,!0)}else n.setBigUint64(r,0n,!0);return 0},fd_advise:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=_.fds[e]){const t=_.fds[e].fd_close();return _.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=_.fds[e]?_.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=_.fds[e]){const{ret:r,fdstat:n}=_.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=_.fds[e]?_.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=_.fds[e]){const{ret:r,filestat:n}=_.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(_.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=_.fds[e]?_.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=a.read_bytes_array(i,t,r),{ret:l,nread:E}=_.fds[e].fd_pread(o,c,n);return i.setUint32(s,E,!0),l}return 8},fd_prestat_get(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,prestat:a}=_.fds[e].fd_prestat_get();return null!=a&&a.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=_.fds[e]){const{ret:r,prestat_dir_name:n}=_.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(_.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,a){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=s.read_bytes_array(i,t,r),{ret:l,nwritten:E}=_.fds[e].fd_pwrite(o,c,n);return i.setUint32(a,E,!0),l}return 8},fd_read(e,t,r,n){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=a.read_bytes_array(s,t,r),{ret:c,nread:l}=_.fds[e].fd_read(i,o);return s.setUint32(n,l,!0),c}return 8},fd_readdir(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){let o=0;for(;;){const{ret:c,dirent:l}=_.fds[e].fd_readdir_single(n);if(0!=c)return s.setUint32(a,o,!0),c;if(null==l)break;if(r-onull!=_.fds[e]?_.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const{ret:n,offset:a}=_.fds[e].fd_tell();return r.setBigUint64(t,a,!0),n}return 8},fd_write(e,t,r,n){const a=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=s.read_bytes_array(a,t,r),{ret:c,nwritten:l}=_.fds[e].fd_write(i,o);return a.setUint32(n,l,!0),c}return 8},path_create_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_create_directory(a)}},path_filestat_get(e,t,r,n,a){const s=new DataView(_.inst.exports.memory.buffer),i=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:c,filestat:l}=_.fds[e].path_filestat_get(t,o);return null!=l&&l.write_bytes(s,a),c}return 8},path_filestat_set_times(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return _.fds[e].path_filestat_set_times(t,c,a,s,i)}return 8},path_link(e,t,r,n,a,s,i){const o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]&&null!=_.fds[a]){const c=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),l=new TextDecoder(\"utf-8\").decode(o.slice(s,s+i));return _.fds[a].path_link(e,t,c,l)}return 8},path_open(e,t,r,n,a,s,i,o,l){const E=new DataView(_.inst.exports.memory.buffer),p=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const u=new TextDecoder(\"utf-8\").decode(p.slice(r,r+n));c.log(u);const{ret:f,fd_obj:d}=_.fds[e].path_open(t,u,a,s,i,o);if(0!=f)return f;_.fds.push(d);const g=_.fds.length-1;return E.setUint32(l,g,!0),0}return 8},path_readlink(e,t,r,n,a,s){const i=new DataView(_.inst.exports.memory.buffer),o=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(t,t+r));c.log(l);const{ret:E,data:p}=_.fds[e].path_readlink(l);if(null!=p){const e=(new TextEncoder).encode(p);if(e.length>a)return i.setUint32(s,0,!0),8;o.set(e,n),i.setUint32(s,e.length,!0)}return E}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_remove_directory(a)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,a){const s=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[r]){const i=new TextDecoder(\"utf-8\").decode(s.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(s.slice(n,n+a));return _.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(_.inst.exports.memory.buffer);if(null!=_.fds[e]){const a=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return _.fds[e].path_unlink_file(a)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(_.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class d{open(e){const t=new f(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new o(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class g{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class b{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)E=globalThis.setImmediate;else{const e=new b;E=(t,...r)=>e.setImmediate(t,...r)}const D=e=>{const t=new g;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>E(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=(t,n)=>{const _=r.bR.encode(t),a=x(e,_);e.wasm_app(a)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(a,[globalThis,null],null,_.expr),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return x(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function x(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let y={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new p([],[],[new f(new d([])),new f(new d([])),new f(new d([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:D(y)});Object.assign(y,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),c=x(y,o);yield a.exports.wasm_app(c),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=x(y,t);y.wasm_app(n)}))}))},startDev:function(_,a=null){const s=new WebSocket(_),i=t=>e(this,void 0,void 0,(function*(){s.send(r.bR.encode(t))}));s.onopen=e=>{const t=r.bp(a),n=r.bR.encode({tag:r.dB.Start,0:t});s.send(n)},s.onmessage=_=>e(this,void 0,void 0,(function*(){const a=yield(s=_.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(s)})));var s;!function(_,a,s){e(this,void 0,void 0,(function*(){switch(_.tag){case r.I4.EvalExpr:{const e=r.wL(s,n,null,_.expr),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:_.threadId};return s(a,null)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(_)}))}(r.sy.decode(a),0,i)})),s.onerror=e=>{console.error(\"WebSocket error:\",e)},s.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>v,D:()=>C,Gk:()=>U,HA:()=>I,HQ:()=>A,In:()=>S,K2:()=>L,PV:()=>j,Sj:()=>B,Tf:()=>k,YE:()=>m,YO:()=>K,Yj:()=>R,b9:()=>W,g1:()=>V,l8:()=>w,tB:()=>H});var n=r(366);class _{encode(e){const t=h(this,e),r=new Uint8Array(t);return P(this,r,0,e),r}decode(e){const[t,r]=O(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class l extends _{}class c extends _{}class u extends _{}class p extends _{}class E extends _{}class d extends _{}class f extends _{}class g extends _{}class b extends _{constructor(e){super(),this._element=e}}class D extends _{constructor(e){super(),this._description=e}}class T extends _{constructor(e){super(),this._alternatives=e}}class y extends _{constructor(e){super(),this._self=e}}class M extends _{constructor(e){super(),this._tuple=e}}function h(e,t){if(e instanceof a)return 1;if(e instanceof s)return 2;if(e instanceof i)return 4;if(e instanceof o)return 8;if(e instanceof l)return 1;if(e instanceof c)return 2;if(e instanceof u)return 4;if(e instanceof p)return 8;if(e instanceof E)return 4;if(e instanceof d)return 8;if(e instanceof g){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof f)return 8+t.length;if(e instanceof b){const r=8;return t.reduce(((t,r)=>t+h(e._element,r)),r)}if(e instanceof D){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+h(e._description[n],r[n])),0)}if(e instanceof T){const r=t;return x(Object.keys(e._alternatives).length)+h(e._alternatives[r.tag],r)}if(e instanceof y)return h(e._self,t);if(e instanceof M){const r=t;return e._tuple.reduce(((e,t,n)=>e+h(t,r[n])),0)}return(0,n.G)(e)}function O(e,t,r){const _=new DataView(t.buffer);if(e instanceof a)return[_.getInt8(r),r+1];if(e instanceof s)return[_.getInt16(r,!0),r+2];if(e instanceof i)return[_.getInt32(r,!0),r+4];if(e instanceof o)return[_.getBigInt64(r,!0),r+8];if(e instanceof l)return[t[r],r+1];if(e instanceof c)return[_.getUint8(r),r+1];if(e instanceof u)return[_.getUint32(r,!0),r+4];if(e instanceof p)return[_.getBigUint64(r,!0),r+8];if(e instanceof E)return[_.getFloat32(r,!0),r+4];if(e instanceof d)return[_.getFloat64(r,!0),r+8];if(e instanceof g){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof f){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof b){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=O(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof T){const n=x(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=O(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof y)return O(e._self,t,r);if(e instanceof M){let n=r;return[e._tuple.map((e=>{const[r,_]=O(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function P(e,t,r,_){const h=new DataView(t.buffer);if(e instanceof a)return h.setInt8(r,_),r+1;if(e instanceof s)return h.setInt16(r,_,!0),r+2;if(e instanceof i)return h.setInt32(r,_,!0),r+4;if(e instanceof o)return h.setBigInt64(r,_,!0),r+8;if(e instanceof l)return h.setUint8(r,_),r+1;if(e instanceof c)return h.setUint16(r,_,!0),r+2;if(e instanceof u)return h.setUint32(r,_,!0),r+4;if(e instanceof p)return h.setBigUint64(r,_,!0),r+8;if(e instanceof E)return h.setFloat32(r,_,!0),r+4;if(e instanceof d)return h.setFloat64(r,_,!0),r+8;if(e instanceof g){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof f){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof b){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=P(e,t,a,n[r])})),a}return(0,n.G)(e)}function x(e){return Math.ceil(Math.log2(e)/8)}const m=new a,w=new s,I=new i,U=new o,A=new l,B=new c,L=new u,C=new p,S=new E,v=new d,R=new g,W=new f;function K(e){return new b(e)}function V(e){return new D(e)}function k(e){return new T(e)}function j(...e){return new M(e)}function H(e){const t=new y(void 0),r=e(t);return t._self=r,r}var N;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(N||(N={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(e,t={}){return evalLoop(t.haskellCallback||(()=>{}),t.idenScope||globalContext,t.argScope||null,t.builderScope||null,e)}function evalUint8Array(e,t={}){return evalExpr(expr.decode(e),t)}function evalLoop(hscb,idenScope,argScope,builderScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I8:case ExprTag.I16:case ExprTag.I32:case ExprTag.I64:case ExprTag.U8:case ExprTag.U16:case ExprTag.U32:case ExprTag.U64:case ExprTag.F32:case ExprTag.F64:case ExprTag.Str:return exp[0];case ExprTag.Arr:return exp[0].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope));case ExprTag.Obj:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalLoop(hscb,idenScope,argScope,builderScope,t)])));case ExprTag.U8Arr:return exp[0];case ExprTag.Dot:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[2]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalLoop(hscb,idenScope,Cons(arguments,argScope),builderScope,exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return e.apply(void 0,exp[1].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope)))}case ExprTag.Call:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope)))}case ExprTag.AssignVar:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);return e?(e.delete(exp.varId),0==e.size&&varStorage.delete(exp.scopeId),null):null}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.AskDomBuilder:if(null==builderScope)throw new Error(\"AskDomBuilder called without prior SupplyDomBuilder!\");return builderScope[0];case ExprTag.SupplyDomBuilder:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.builder),t=Cons(e,builderScope);return evalLoop(hscb,idenScope,argScope,t,exp.expr)}case ExprTag.InsertNode:{if(null==builderScope)throw new Error(\"InsertNode called without prior SupplyDomBuilder!\");const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.child);return domHelpers.insertIntoBuilder(builderScope[0],e),null}case ExprTag.ElementProp:{if(null==builderScope)throw new Error(\"ElementProp called without prior SupplyDomBuilder!\");const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.propValue);return domHelpers.assignProperty(builderScope[0],exp.propName,e),null}case ExprTag.ElementAttr:if(null==builderScope)throw new Error(\"ElementAttr called without prior SupplyDomBuilder!\");return domHelpers.assignAttribute(builderScope[0],exp.attrName,exp.attrValue),null;case ExprTag.ClassListAdd:{if(null==builderScope)throw new Error(\"InsertClassList called without prior SupplyDomBuilder!\");const e=domHelpers.domBuilderElement(builderScope[0]);return exp.classList.forEach((t=>e.classList.add(t))),null}case ExprTag.ClassListRemove:{if(null==builderScope)throw new Error(\"RemoveClassList called without prior SupplyDomBuilder!\");const e=domHelpers.domBuilderElement(builderScope[0]);return exp.classList.forEach((t=>e.classList.remove(t))),null}case ExprTag.InsertBrackets:if(null==builderScope)throw new Error(\"InsertBoundary called without prior SupplyDomBuilder!\");return domHelpers.insertBrackets(builderScope[0]);case ExprTag.ClearBrackets:if(null==builderScope)throw new Error(\"InsertBoundary called without prior SupplyDomBuilder!\");return domHelpers.clearBrackets(builderScope[0],Boolean(exp.detach));case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateTextNode:return document.createTextNode(exp.content);case ExprTag.UpdateTextNode:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.node);return e.textContent=exp.content,null}case ExprTag.AddEventListener:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.target),t=evalLoop(hscb,idenScope,argScope,builderScope,exp.eventName),r=evalLoop(hscb,idenScope,argScope,builderScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalLoop(hscb,idenScope,argScope,builderScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalLoop(hscb,idenScope,argScope,builderScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerEvent:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerEventMsg,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Vbool,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.Vi32,0:e}:{tag:ValueTag.Vf64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.Vstr,0:e};if(\"bigint\"==typeof e)return{tag:ValueTag.Vi64,0:e};if(Array.isArray(e))return{tag:ValueTag.Varr,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Vu8arr,0:e};if(null==e)return{tag:ValueTag.Vnull};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Vobj,0:t}}!function(e){e[e.Vnull=0]=\"Vnull\",e[e.Vbool=1]=\"Vbool\",e[e.Vi8=2]=\"Vi8\",e[e.Vi16=3]=\"Vi16\",e[e.Vi32=4]=\"Vi32\",e[e.Vi64=5]=\"Vi64\",e[e.Vu8=6]=\"Vu8\",e[e.Vu16=7]=\"Vu16\",e[e.Vu32=8]=\"Vu32\",e[e.Vu64=9]=\"Vu64\",e[e.Vf32=10]=\"Vf32\",e[e.Vf64=11]=\"Vf64\",e[e.Vstr=12]=\"Vstr\",e[e.Varr=13]=\"Varr\",e[e.Vobj=14]=\"Vobj\",e[e.Vu8arr=15]=\"Vu8arr\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Vnull]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Vbool]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ValueTag.Vi32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.Vi64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.Vu8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ValueTag.Vu16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ValueTag.Vu32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ValueTag.Vu64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ValueTag.Vf32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ValueTag.Vf64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.Vstr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Varr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Vobj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Vu8arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Plus=19]=\"Plus\",e[e.Subtract=20]=\"Subtract\",e[e.Multiply=21]=\"Multiply\",e[e.Divide=22]=\"Divide\",e[e.Id=23]=\"Id\",e[e.Lam=24]=\"Lam\",e[e.Arg=25]=\"Arg\",e[e.Apply=26]=\"Apply\",e[e.Call=27]=\"Call\",e[e.AssignVar=28]=\"AssignVar\",e[e.FreeVar=29]=\"FreeVar\",e[e.Var=30]=\"Var\",e[e.FreeScope=31]=\"FreeScope\",e[e.AskDomBuilder=32]=\"AskDomBuilder\",e[e.SupplyDomBuilder=33]=\"SupplyDomBuilder\",e[e.InsertNode=34]=\"InsertNode\",e[e.ElementProp=35]=\"ElementProp\",e[e.ElementAttr=36]=\"ElementAttr\",e[e.ClassListAdd=37]=\"ClassListAdd\",e[e.ClassListRemove=38]=\"ClassListRemove\",e[e.InsertBrackets=39]=\"InsertBrackets\",e[e.ClearBrackets=40]=\"ClearBrackets\",e[e.CreateElement=41]=\"CreateElement\",e[e.CreateElementNS=42]=\"CreateElementNS\",e[e.CreateTextNode=43]=\"CreateTextNode\",e[e.UpdateTextNode=44]=\"UpdateTextNode\",e[e.AddEventListener=45]=\"AddEventListener\",e[e.ConnectResource=46]=\"ConnectResource\",e[e.SetTimeout=47]=\"SetTimeout\",e[e.ApplyFinalizer=48]=\"ApplyFinalizer\",e[e.RevSeq=49]=\"RevSeq\",e[e.Eval=50]=\"Eval\",e[e.TriggerEvent=51]=\"TriggerEvent\",e[e.UncaughtException=52]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ExprTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ExprTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ExprTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ExprTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.Str]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Obj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.U8Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.AskDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.SupplyDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({builder:e,expr:e}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({child:e}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ClassListAdd]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.ClassListRemove]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.InsertBrackets]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.ClearBrackets]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerEventMsg=2]=\"TriggerEventMsg\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerEventMsg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map,globalContext=[window,null];var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBrackets=function(e){const r=document.createComment(\"ContentBrackets {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBrackets=function(e,t){if(e instanceof Comment){let _=0;for(;e.previousSibling&&(0!=_||!n(e.previousSibling));)(r=e.previousSibling)instanceof Comment&&\"}}\"==r.textContent?_++:n(e.previousSibling)&&_--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var r},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=58;class _{static read_bytes(e,t){const r=new _;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let c,u=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],o.enable(n.debug),this.args=e,this.env=t,this.fds=r;const s=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(s.inst.exports.memory.buffer);r.setUint32(e,s.args.length,!0);let n=0;for(const e of s.args)n+=e.length+1;return r.setUint32(t,n,!0),o.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(s.inst.exports.memory.buffer),n=new Uint8Array(s.inst.exports.memory.buffer),_=t;for(let _=0;_null!=s.fds[e]?s.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:r,fdstat:n}=s.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(s.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:r,filestat:n}=s.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(s.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,a){const i=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=_.read_bytes_array(i,t,r),{ret:c,nread:u}=s.fds[e].fd_pread(o,l,n);return i.setUint32(a,u,!0),c}return 8},fd_prestat_get(e,t){const r=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:n,prestat:_}=s.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=s.fds[e]){const{ret:r,prestat_dir_name:n}=s.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(s.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,_){const i=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=a.read_bytes_array(i,t,r),{ret:c,nwritten:u}=s.fds[e].fd_pwrite(o,l,n);return i.setUint32(_,u,!0),c}return 8},fd_read(e,t,r,n){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=_.read_bytes_array(a,t,r),{ret:l,nread:c}=s.fds[e].fd_read(i,o);return a.setUint32(n,c,!0),l}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:l,dirent:c}=s.fds[e].fd_readdir_single(n);if(0!=l)return a.setUint32(_,o,!0),l;if(null==c)break;if(r-onull!=s.fds[e]?s.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:n,offset:_}=s.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,n){const _=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=a.read_bytes_array(_,t,r),{ret:l,nwritten:c}=s.fds[e].fd_write(i,o);return _.setUint32(n,c,!0),l}return 8},path_create_directory(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:l,filestat:c}=s.fds[e].path_filestat_get(t,o);return null!=c&&c.write_bytes(a,_),l}return 8},path_filestat_set_times(e,t,r,n,_,a,i){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return s.fds[e].path_filestat_set_times(t,l,_,a,i)}return 8},path_link(e,t,r,n,_,a,i){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[_]){const l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),c=new TextDecoder(\"utf-8\").decode(o.slice(a,a+i));return s.fds[_].path_link(e,t,l,c)}return 8},path_open(e,t,r,n,_,a,i,l,c){const u=new DataView(s.inst.exports.memory.buffer),p=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const E=new TextDecoder(\"utf-8\").decode(p.slice(r,r+n));o.log(E);const{ret:d,fd_obj:f}=s.fds[e].path_open(t,E,_,a,i,l);if(0!=d)return d;s.fds.push(f);const g=s.fds.length-1;return u.setUint32(c,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(l.slice(t,t+r));o.log(c);const{ret:u,data:p}=s.fds[e].path_readlink(c);if(null!=p){const e=(new TextEncoder).encode(p);if(e.length>_)return i.setUint32(a,0,!0),8;l.set(e,n),i.setUint32(a,e.length,!0)}return u}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[r]){const i=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return s.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(s.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class d{open(e){const t=new E(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new i(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class g{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)c=globalThis.setImmediate;else{const e=new g;c=(t,...r)=>e.setImmediate(t,...r)}const b=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>c(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=t=>{const n=r.bR.encode(t),_=D(e,n);e.wasm_app(_)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(_.expr,{haskellCallback:a}),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return D(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function D(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let T={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new u([],[],[new E(new d([])),new E(new d([])),new E(new d([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:b(T)});Object.assign(T,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),l=D(T,o);yield a.exports.wasm_app(l),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=D(T,t);T.wasm_app(n)}))}))},startDev:function(n,_=null){const a=new WebSocket(n),s=t=>e(this,void 0,void 0,(function*(){a.send(r.bR.encode(t))}));a.onopen=e=>{const t=r.bp(_),n=r.bR.encode({tag:r.dB.Start,0:t});a.send(n)},a.onmessage=n=>e(this,void 0,void 0,(function*(){const _=yield(a=n.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(a)})));var a;!function(n,_){e(this,void 0,void 0,(function*(){switch(n.tag){case r.I4.EvalExpr:{const e=r.wL(n.expr,{haskellCallback:_}),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:n.threadId};return _(a)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(n)}))}(r.sy.decode(_),s)})),a.onerror=e=>{console.error(\"WebSocket error:\",e)},a.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" diff --git a/src/Clickable/Main/Wasm.hs b/src/Clickable/Main/Wasm.hs index ea121c2..352abe1 100644 --- a/src/Clickable/Main/Wasm.hs +++ b/src/Clickable/Main/Wasm.hs @@ -29,7 +29,7 @@ runWasm app p = mdo Just (TriggerEventMsg arg eid) -> launchClickM internalEnv $ modify $ Internal.triggerEvent (unsafeFromEventId eid) arg Just BeforeUnload -> - launchClickM internalEnv $ freeScope True $ ResourceScope $ Int32Le Internal.emptyState.next_id + launchClickM internalEnv $ freeScope True $ ResourceScope Internal.emptyState.next_id _ -> return () diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index da7dbf2..8878eb4 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE DerivingVia #-} module Clickable.Protocol where import Data.Binary (Binary) @@ -114,17 +115,21 @@ data Expr | FreeScope ResourceScope -- ^ Free all the resources assosiated with the given ResourceScope - | InsertNode DomBuilder Expr + | AskDomBuilder + | SupplyDomBuilder DomBuilder Expr + + | InsertNode Expr + | ElementProp Text Expr + | ElementAttr Text Text + | ClassListAdd [Text] + | ClassListRemove [Text] + | InsertBrackets + | ClearBrackets Bool + | CreateElement Text | CreateElementNS Text Text | CreateTextNode Text - | ElementProp DomBuilder Text Expr - | ElementAttr DomBuilder Text Text - | InsertClassList DomBuilder [Text] - | RemoveClassList DomBuilder [Text] - | UpdateTextNode DomBuilder Text - | InsertBoundary DomBuilder - | ClearBoundary DomBuilder Bool + | UpdateTextNode Expr Text | AddEventListener ResourceScope Expr Expr Expr -- ^ @AddEventListener rscope target eventName listener@ is @@ -182,9 +187,6 @@ valueToExpr = \case toExpr :: ToValue a => a -> Expr toExpr = valueToExpr . toValue -builderContext :: DomBuilder -builderContext = DomBuilder $ Arg 0 0 - newtype DomBuilder = DomBuilder {unDomBuilder :: Expr} deriving newtype (Show, Binary) @@ -192,14 +194,17 @@ data VarId = VarId ResourceScope Int32Le deriving stock (Generic, Show, Ord, Eq) deriving anyclass (Binary) -newtype FinalizerId = FinalizerId {unFinalizerId :: Int32Le} - deriving newtype (Show, Ord, Eq, Binary) +newtype FinalizerId = FinalizerId {unFinalizerId :: Int32} + deriving newtype (Show, Ord, Eq) + deriving Binary via Int32Le -newtype ResourceScope = ResourceScope {unResourceScope :: Int32Le} - deriving newtype (Show, Ord, Eq, Binary) +newtype ResourceScope = ResourceScope {unResourceScope :: Int32} + deriving newtype (Show, Ord, Eq) + deriving Binary via Int32Le -newtype EventId = EventId {unEventId :: Int32Le} - deriving newtype (Show, Ord, Eq, Binary) +newtype EventId = EventId {unEventId :: Int32} + deriving newtype (Show, Ord, Eq) + deriving Binary via Int32Le newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} deriving newtype (IsString, Show, Semigroup, Monoid, Binary) From 1d049df295d98c09ab4c4f63974828fa0eea6614 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sun, 22 Sep 2024 17:21:54 +0400 Subject: [PATCH 51/64] Reload the tab once WebSocket connection is re-established --- default.nix | 5 +++++ jsbits/dev.ts | 14 ++++++++++++-- jsbits/protocol.ts | 7 ++++--- src/Clickable/DOM.hs | 10 ++++++++++ src/Clickable/Main/Dev.hs | 33 +++++++++++++++++++-------------- 5 files changed, 50 insertions(+), 19 deletions(-) diff --git a/default.nix b/default.nix index 904fd94..c219a45 100644 --- a/default.nix +++ b/default.nix @@ -44,6 +44,11 @@ let # fails to build, you have to have cabal installed on your system # buildDepends = [haskellPackages.cabal-install]; }; + javascript = pkgs.mkShell { + buildInputs = [ + pkgs.pkgsCross.ghcjs.buildPackages.haskell.compiler.ghcHEAD + ]; + }; }; in result diff --git a/jsbits/dev.ts b/jsbits/dev.ts index 07be5e9..1c3b548 100644 --- a/jsbits/dev.ts +++ b/jsbits/dev.ts @@ -33,8 +33,18 @@ export function startDev(devSocketUri: string, startFlags: unknown = null) { }; // Event handler for when the connection is closed - websocket.onclose = (event) => { - console.log("WebSocket connection closed:", event); + websocket.onclose = (_event) => { + console.log("WebSocket connection closed, reloading the tab…"); + + function backoffLoop(timeout: number) { + // Assuming the server went down because it was re-compiled, wait + // until it comes back and reload the tab + const websocketTest = new WebSocket(devSocketUri); + const nextTimeout = Math.min(30_000, timeout * 2); + websocketTest.onopen = (_event) => window.location.reload(); + websocketTest.onclose = (_event) => { setTimeout(() => backoffLoop(nextTimeout), timeout); } + } + backoffLoop(100); }; } diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts index d4fcce2..1e0c5d8 100644 --- a/jsbits/protocol.ts +++ b/jsbits/protocol.ts @@ -207,6 +207,7 @@ export function evalLoop ( case ExprTag.FreeScope: { varStorage.delete(exp.scopeId); const scopeFinalizers = finalizers.get(exp.scopeId); + finalizers.delete(exp.scopeId); if (scopeFinalizers) scopeFinalizers.forEach(fn => fn ()); return null; } @@ -682,11 +683,11 @@ export const javascriptMessage = b.discriminate({ export type HaskellMessage = typeof haskellMessage['_A']; export type JavaScriptMessage = typeof javascriptMessage['_A']; -export type ReactiveScope = number; +export type ResourceScope = number; export type VarId = number; -export const varStorage = new Map>(); -export const finalizers = new Map>; +export const varStorage = new Map>(); +export const finalizers = new Map>; export const globalContext: List = [window as any, null] diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs index 99f969a..2cf720f 100644 --- a/src/Clickable/DOM.hs +++ b/src/Clickable/DOM.hs @@ -67,6 +67,16 @@ instance IsEventName "mouseup" where connectEventName k = addEventListener (genericEvent defaultEventListenerOptions "mouseup") (const k) +instance IsEventName "mouseenter" where + type EventListenerCb "mouseenter" = ClickM () + connectEventName k = addEventListener + (genericEvent defaultEventListenerOptions "mouseenter") (const k) + +instance IsEventName "mouseleave" where + type EventListenerCb "mouseleave" = ClickM () + connectEventName k = addEventListener + (genericEvent defaultEventListenerOptions "mouseleave") (const k) + instance IsEventName "dblclick" where type EventListenerCb "dblclick" = ClickM () connectEventName k = addEventListener diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index 7033c85..f0d8c23 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -48,12 +48,13 @@ data DevConfig a = DevConfig , reload_app :: a -> IO ApplicationSpec -- ^ Given resource of type 'a', initialize instances of client and -- server applications. Runs each time ghci session reloads - , html_template :: ByteString -> Builder + , html_template :: HtmlTemplateArgs -> Builder -- ^ Template for index.html, receives the current URL origin -- (protocol + host) , docroots :: [FilePath] -- ^ List of directories to use with wai-static middleware, could be -- empty, usually be used like docroots = ["./public"] + , warp_settings :: Warp.Settings } deriving Generic data ApplicationSpec = ApplicationSpec @@ -70,10 +71,11 @@ defaultConfig clientApp = DevConfig , reload_app = \_ -> pure $ ApplicationSpec clientApp fallbackApp (const (pure ())) , html_template = htmlTemplate , docroots = [] + , warp_settings = Warp.defaultSettings } -runSettings :: Typeable resource => Warp.Settings -> DevConfig resource -> IO () -runSettings settings cfg = do +runSettings :: Typeable resource => DevConfig resource -> IO () +runSettings cfg = do -- Using a random constant as the key for Foreign.Store let storeId = 183 hSetBuffering stderr LineBuffering @@ -85,7 +87,7 @@ runSettings settings cfg = do useCurrentApp req resp = do RunningApp{devserver_config, server_app} <- readIORef inst.app_state_ref withStaticApp devserver_config.docroots server_app req resp - forkIfRepl $ tryPort settings $ + forkIfRepl $ tryPort cfg.warp_settings $ middleware inst useCurrentApp Just store -> do oldInst <- readStore store @@ -115,10 +117,8 @@ runSettings settings cfg = do isRepl <- (== "") <$> getProgName if isRepl then void (forkIO action) else action -runDev :: (StartFlags -> ClickM ()) -> IO () -runDev clientApp = runSettings - (Warp.setPort 8080 Warp.defaultSettings) - (defaultConfig (const clientApp)) +runDev :: (ConnectionInfo -> StartFlags -> ClickM ()) -> IO () +runDev clientApp = runSettings $ defaultConfig clientApp middleware :: DevInstance -> Middleware middleware opts next req resp = @@ -136,7 +136,7 @@ middleware opts next req resp = RunningApp{devserver_config} <- readIORef opts.app_state_ref resp $ responseBuilder status200 [(hContentType, "text/html; charset=utf-8")] $ - devserver_config.html_template devSocket + devserver_config.html_template $ HtmlTemplateArgs indexBundleJs devSocket mkWebsocketUrl :: WAI.Request -> ByteString mkWebsocketUrl req = @@ -146,13 +146,18 @@ mkWebsocketUrl req = & ((if WAI.isSecure req then "wss://" else "ws://") <>) & (<> "/dev.sock") -htmlTemplate :: ByteString -> Builder -htmlTemplate devUrl = +data HtmlTemplateArgs = HtmlTemplateArgs + { js_runtime :: ByteString + , ws_url :: ByteString + } + +htmlTemplate :: HtmlTemplateArgs -> Builder +htmlTemplate hta = "\n\ \ \n\ \ \n\ \ \n\ \\n" @@ -318,4 +323,4 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} -- | Run @yarn run webpack --mode production@ and copy contents here -- from @./dist-newstyle/index.bundle.js@ indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>v,D:()=>C,Gk:()=>U,HA:()=>I,HQ:()=>A,In:()=>S,K2:()=>L,PV:()=>j,Sj:()=>B,Tf:()=>k,YE:()=>m,YO:()=>K,Yj:()=>R,b9:()=>W,g1:()=>V,l8:()=>w,tB:()=>H});var n=r(366);class _{encode(e){const t=h(this,e),r=new Uint8Array(t);return P(this,r,0,e),r}decode(e){const[t,r]=O(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class l extends _{}class c extends _{}class u extends _{}class p extends _{}class E extends _{}class d extends _{}class f extends _{}class g extends _{}class b extends _{constructor(e){super(),this._element=e}}class D extends _{constructor(e){super(),this._description=e}}class T extends _{constructor(e){super(),this._alternatives=e}}class y extends _{constructor(e){super(),this._self=e}}class M extends _{constructor(e){super(),this._tuple=e}}function h(e,t){if(e instanceof a)return 1;if(e instanceof s)return 2;if(e instanceof i)return 4;if(e instanceof o)return 8;if(e instanceof l)return 1;if(e instanceof c)return 2;if(e instanceof u)return 4;if(e instanceof p)return 8;if(e instanceof E)return 4;if(e instanceof d)return 8;if(e instanceof g){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof f)return 8+t.length;if(e instanceof b){const r=8;return t.reduce(((t,r)=>t+h(e._element,r)),r)}if(e instanceof D){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+h(e._description[n],r[n])),0)}if(e instanceof T){const r=t;return x(Object.keys(e._alternatives).length)+h(e._alternatives[r.tag],r)}if(e instanceof y)return h(e._self,t);if(e instanceof M){const r=t;return e._tuple.reduce(((e,t,n)=>e+h(t,r[n])),0)}return(0,n.G)(e)}function O(e,t,r){const _=new DataView(t.buffer);if(e instanceof a)return[_.getInt8(r),r+1];if(e instanceof s)return[_.getInt16(r,!0),r+2];if(e instanceof i)return[_.getInt32(r,!0),r+4];if(e instanceof o)return[_.getBigInt64(r,!0),r+8];if(e instanceof l)return[t[r],r+1];if(e instanceof c)return[_.getUint8(r),r+1];if(e instanceof u)return[_.getUint32(r,!0),r+4];if(e instanceof p)return[_.getBigUint64(r,!0),r+8];if(e instanceof E)return[_.getFloat32(r,!0),r+4];if(e instanceof d)return[_.getFloat64(r,!0),r+8];if(e instanceof g){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof f){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof b){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=O(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof T){const n=x(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=O(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof y)return O(e._self,t,r);if(e instanceof M){let n=r;return[e._tuple.map((e=>{const[r,_]=O(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function P(e,t,r,_){const h=new DataView(t.buffer);if(e instanceof a)return h.setInt8(r,_),r+1;if(e instanceof s)return h.setInt16(r,_,!0),r+2;if(e instanceof i)return h.setInt32(r,_,!0),r+4;if(e instanceof o)return h.setBigInt64(r,_,!0),r+8;if(e instanceof l)return h.setUint8(r,_),r+1;if(e instanceof c)return h.setUint16(r,_,!0),r+2;if(e instanceof u)return h.setUint32(r,_,!0),r+4;if(e instanceof p)return h.setBigUint64(r,_,!0),r+8;if(e instanceof E)return h.setFloat32(r,_,!0),r+4;if(e instanceof d)return h.setFloat64(r,_,!0),r+8;if(e instanceof g){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof f){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof b){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=P(e,t,a,n[r])})),a}return(0,n.G)(e)}function x(e){return Math.ceil(Math.log2(e)/8)}const m=new a,w=new s,I=new i,U=new o,A=new l,B=new c,L=new u,C=new p,S=new E,v=new d,R=new g,W=new f;function K(e){return new b(e)}function V(e){return new D(e)}function k(e){return new T(e)}function j(...e){return new M(e)}function H(e){const t=new y(void 0),r=e(t);return t._self=r,r}var N;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(N||(N={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(e,t={}){return evalLoop(t.haskellCallback||(()=>{}),t.idenScope||globalContext,t.argScope||null,t.builderScope||null,e)}function evalUint8Array(e,t={}){return evalExpr(expr.decode(e),t)}function evalLoop(hscb,idenScope,argScope,builderScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I8:case ExprTag.I16:case ExprTag.I32:case ExprTag.I64:case ExprTag.U8:case ExprTag.U16:case ExprTag.U32:case ExprTag.U64:case ExprTag.F32:case ExprTag.F64:case ExprTag.Str:return exp[0];case ExprTag.Arr:return exp[0].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope));case ExprTag.Obj:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalLoop(hscb,idenScope,argScope,builderScope,t)])));case ExprTag.U8Arr:return exp[0];case ExprTag.Dot:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[2]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalLoop(hscb,idenScope,Cons(arguments,argScope),builderScope,exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return e.apply(void 0,exp[1].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope)))}case ExprTag.Call:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope)))}case ExprTag.AssignVar:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);return e?(e.delete(exp.varId),0==e.size&&varStorage.delete(exp.scopeId),null):null}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return e&&e.forEach((e=>e())),null}case ExprTag.AskDomBuilder:if(null==builderScope)throw new Error(\"AskDomBuilder called without prior SupplyDomBuilder!\");return builderScope[0];case ExprTag.SupplyDomBuilder:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.builder),t=Cons(e,builderScope);return evalLoop(hscb,idenScope,argScope,t,exp.expr)}case ExprTag.InsertNode:{if(null==builderScope)throw new Error(\"InsertNode called without prior SupplyDomBuilder!\");const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.child);return domHelpers.insertIntoBuilder(builderScope[0],e),null}case ExprTag.ElementProp:{if(null==builderScope)throw new Error(\"ElementProp called without prior SupplyDomBuilder!\");const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.propValue);return domHelpers.assignProperty(builderScope[0],exp.propName,e),null}case ExprTag.ElementAttr:if(null==builderScope)throw new Error(\"ElementAttr called without prior SupplyDomBuilder!\");return domHelpers.assignAttribute(builderScope[0],exp.attrName,exp.attrValue),null;case ExprTag.ClassListAdd:{if(null==builderScope)throw new Error(\"InsertClassList called without prior SupplyDomBuilder!\");const e=domHelpers.domBuilderElement(builderScope[0]);return exp.classList.forEach((t=>e.classList.add(t))),null}case ExprTag.ClassListRemove:{if(null==builderScope)throw new Error(\"RemoveClassList called without prior SupplyDomBuilder!\");const e=domHelpers.domBuilderElement(builderScope[0]);return exp.classList.forEach((t=>e.classList.remove(t))),null}case ExprTag.InsertBrackets:if(null==builderScope)throw new Error(\"InsertBoundary called without prior SupplyDomBuilder!\");return domHelpers.insertBrackets(builderScope[0]);case ExprTag.ClearBrackets:if(null==builderScope)throw new Error(\"InsertBoundary called without prior SupplyDomBuilder!\");return domHelpers.clearBrackets(builderScope[0],Boolean(exp.detach));case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateTextNode:return document.createTextNode(exp.content);case ExprTag.UpdateTextNode:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.node);return e.textContent=exp.content,null}case ExprTag.AddEventListener:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.target),t=evalLoop(hscb,idenScope,argScope,builderScope,exp.eventName),r=evalLoop(hscb,idenScope,argScope,builderScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalLoop(hscb,idenScope,argScope,builderScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalLoop(hscb,idenScope,argScope,builderScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerEvent:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerEventMsg,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Vbool,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.Vi32,0:e}:{tag:ValueTag.Vf64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.Vstr,0:e};if(\"bigint\"==typeof e)return{tag:ValueTag.Vi64,0:e};if(Array.isArray(e))return{tag:ValueTag.Varr,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Vu8arr,0:e};if(null==e)return{tag:ValueTag.Vnull};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Vobj,0:t}}!function(e){e[e.Vnull=0]=\"Vnull\",e[e.Vbool=1]=\"Vbool\",e[e.Vi8=2]=\"Vi8\",e[e.Vi16=3]=\"Vi16\",e[e.Vi32=4]=\"Vi32\",e[e.Vi64=5]=\"Vi64\",e[e.Vu8=6]=\"Vu8\",e[e.Vu16=7]=\"Vu16\",e[e.Vu32=8]=\"Vu32\",e[e.Vu64=9]=\"Vu64\",e[e.Vf32=10]=\"Vf32\",e[e.Vf64=11]=\"Vf64\",e[e.Vstr=12]=\"Vstr\",e[e.Varr=13]=\"Varr\",e[e.Vobj=14]=\"Vobj\",e[e.Vu8arr=15]=\"Vu8arr\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Vnull]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Vbool]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ValueTag.Vi32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.Vi64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.Vu8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ValueTag.Vu16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ValueTag.Vu32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ValueTag.Vu64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ValueTag.Vf32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ValueTag.Vf64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.Vstr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Varr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Vobj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Vu8arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Plus=19]=\"Plus\",e[e.Subtract=20]=\"Subtract\",e[e.Multiply=21]=\"Multiply\",e[e.Divide=22]=\"Divide\",e[e.Id=23]=\"Id\",e[e.Lam=24]=\"Lam\",e[e.Arg=25]=\"Arg\",e[e.Apply=26]=\"Apply\",e[e.Call=27]=\"Call\",e[e.AssignVar=28]=\"AssignVar\",e[e.FreeVar=29]=\"FreeVar\",e[e.Var=30]=\"Var\",e[e.FreeScope=31]=\"FreeScope\",e[e.AskDomBuilder=32]=\"AskDomBuilder\",e[e.SupplyDomBuilder=33]=\"SupplyDomBuilder\",e[e.InsertNode=34]=\"InsertNode\",e[e.ElementProp=35]=\"ElementProp\",e[e.ElementAttr=36]=\"ElementAttr\",e[e.ClassListAdd=37]=\"ClassListAdd\",e[e.ClassListRemove=38]=\"ClassListRemove\",e[e.InsertBrackets=39]=\"InsertBrackets\",e[e.ClearBrackets=40]=\"ClearBrackets\",e[e.CreateElement=41]=\"CreateElement\",e[e.CreateElementNS=42]=\"CreateElementNS\",e[e.CreateTextNode=43]=\"CreateTextNode\",e[e.UpdateTextNode=44]=\"UpdateTextNode\",e[e.AddEventListener=45]=\"AddEventListener\",e[e.ConnectResource=46]=\"ConnectResource\",e[e.SetTimeout=47]=\"SetTimeout\",e[e.ApplyFinalizer=48]=\"ApplyFinalizer\",e[e.RevSeq=49]=\"RevSeq\",e[e.Eval=50]=\"Eval\",e[e.TriggerEvent=51]=\"TriggerEvent\",e[e.UncaughtException=52]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ExprTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ExprTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ExprTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ExprTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.Str]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Obj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.U8Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.AskDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.SupplyDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({builder:e,expr:e}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({child:e}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ClassListAdd]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.ClassListRemove]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.InsertBrackets]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.ClearBrackets]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerEventMsg=2]=\"TriggerEventMsg\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerEventMsg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map,globalContext=[window,null];var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBrackets=function(e){const r=document.createComment(\"ContentBrackets {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBrackets=function(e,t){if(e instanceof Comment){let _=0;for(;e.previousSibling&&(0!=_||!n(e.previousSibling));)(r=e.previousSibling)instanceof Comment&&\"}}\"==r.textContent?_++:n(e.previousSibling)&&_--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var r},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=58;class _{static read_bytes(e,t){const r=new _;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let c,u=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],o.enable(n.debug),this.args=e,this.env=t,this.fds=r;const s=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(s.inst.exports.memory.buffer);r.setUint32(e,s.args.length,!0);let n=0;for(const e of s.args)n+=e.length+1;return r.setUint32(t,n,!0),o.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(s.inst.exports.memory.buffer),n=new Uint8Array(s.inst.exports.memory.buffer),_=t;for(let _=0;_null!=s.fds[e]?s.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:r,fdstat:n}=s.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(s.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:r,filestat:n}=s.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(s.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,a){const i=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=_.read_bytes_array(i,t,r),{ret:c,nread:u}=s.fds[e].fd_pread(o,l,n);return i.setUint32(a,u,!0),c}return 8},fd_prestat_get(e,t){const r=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:n,prestat:_}=s.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=s.fds[e]){const{ret:r,prestat_dir_name:n}=s.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(s.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,_){const i=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=a.read_bytes_array(i,t,r),{ret:c,nwritten:u}=s.fds[e].fd_pwrite(o,l,n);return i.setUint32(_,u,!0),c}return 8},fd_read(e,t,r,n){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=_.read_bytes_array(a,t,r),{ret:l,nread:c}=s.fds[e].fd_read(i,o);return a.setUint32(n,c,!0),l}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:l,dirent:c}=s.fds[e].fd_readdir_single(n);if(0!=l)return a.setUint32(_,o,!0),l;if(null==c)break;if(r-onull!=s.fds[e]?s.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:n,offset:_}=s.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,n){const _=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=a.read_bytes_array(_,t,r),{ret:l,nwritten:c}=s.fds[e].fd_write(i,o);return _.setUint32(n,c,!0),l}return 8},path_create_directory(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:l,filestat:c}=s.fds[e].path_filestat_get(t,o);return null!=c&&c.write_bytes(a,_),l}return 8},path_filestat_set_times(e,t,r,n,_,a,i){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return s.fds[e].path_filestat_set_times(t,l,_,a,i)}return 8},path_link(e,t,r,n,_,a,i){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[_]){const l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),c=new TextDecoder(\"utf-8\").decode(o.slice(a,a+i));return s.fds[_].path_link(e,t,l,c)}return 8},path_open(e,t,r,n,_,a,i,l,c){const u=new DataView(s.inst.exports.memory.buffer),p=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const E=new TextDecoder(\"utf-8\").decode(p.slice(r,r+n));o.log(E);const{ret:d,fd_obj:f}=s.fds[e].path_open(t,E,_,a,i,l);if(0!=d)return d;s.fds.push(f);const g=s.fds.length-1;return u.setUint32(c,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(l.slice(t,t+r));o.log(c);const{ret:u,data:p}=s.fds[e].path_readlink(c);if(null!=p){const e=(new TextEncoder).encode(p);if(e.length>_)return i.setUint32(a,0,!0),8;l.set(e,n),i.setUint32(a,e.length,!0)}return u}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[r]){const i=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return s.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(s.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class d{open(e){const t=new E(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new i(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class g{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)c=globalThis.setImmediate;else{const e=new g;c=(t,...r)=>e.setImmediate(t,...r)}const b=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>c(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=t=>{const n=r.bR.encode(t),_=D(e,n);e.wasm_app(_)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(_.expr,{haskellCallback:a}),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return D(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function D(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let T={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new u([],[],[new E(new d([])),new E(new d([])),new E(new d([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:b(T)});Object.assign(T,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),l=D(T,o);yield a.exports.wasm_app(l),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=D(T,t);T.wasm_app(n)}))}))},startDev:function(n,_=null){const a=new WebSocket(n),s=t=>e(this,void 0,void 0,(function*(){a.send(r.bR.encode(t))}));a.onopen=e=>{const t=r.bp(_),n=r.bR.encode({tag:r.dB.Start,0:t});a.send(n)},a.onmessage=n=>e(this,void 0,void 0,(function*(){const _=yield(a=n.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(a)})));var a;!function(n,_){e(this,void 0,void 0,(function*(){switch(n.tag){case r.I4.EvalExpr:{const e=r.wL(n.expr,{haskellCallback:_}),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:n.threadId};return _(a)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(n)}))}(r.sy.decode(_),s)})),a.onerror=e=>{console.error(\"WebSocket error:\",e)},a.onclose=e=>{console.log(\"WebSocket connection closed:\",e)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" +indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>v,D:()=>C,Gk:()=>U,HA:()=>I,HQ:()=>A,In:()=>S,K2:()=>L,PV:()=>j,Sj:()=>B,Tf:()=>k,YE:()=>m,YO:()=>K,Yj:()=>R,b9:()=>W,g1:()=>V,l8:()=>w,tB:()=>H});var n=r(366);class _{encode(e){const t=h(this,e),r=new Uint8Array(t);return P(this,r,0,e),r}decode(e){const[t,r]=O(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class l extends _{}class c extends _{}class u extends _{}class p extends _{}class d extends _{}class E extends _{}class f extends _{}class g extends _{}class b extends _{constructor(e){super(),this._element=e}}class D extends _{constructor(e){super(),this._description=e}}class T extends _{constructor(e){super(),this._alternatives=e}}class y extends _{constructor(e){super(),this._self=e}}class M extends _{constructor(e){super(),this._tuple=e}}function h(e,t){if(e instanceof a)return 1;if(e instanceof s)return 2;if(e instanceof i)return 4;if(e instanceof o)return 8;if(e instanceof l)return 1;if(e instanceof c)return 2;if(e instanceof u)return 4;if(e instanceof p)return 8;if(e instanceof d)return 4;if(e instanceof E)return 8;if(e instanceof g){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof f)return 8+t.length;if(e instanceof b){const r=8;return t.reduce(((t,r)=>t+h(e._element,r)),r)}if(e instanceof D){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+h(e._description[n],r[n])),0)}if(e instanceof T){const r=t;return x(Object.keys(e._alternatives).length)+h(e._alternatives[r.tag],r)}if(e instanceof y)return h(e._self,t);if(e instanceof M){const r=t;return e._tuple.reduce(((e,t,n)=>e+h(t,r[n])),0)}return(0,n.G)(e)}function O(e,t,r){const _=new DataView(t.buffer);if(e instanceof a)return[_.getInt8(r),r+1];if(e instanceof s)return[_.getInt16(r,!0),r+2];if(e instanceof i)return[_.getInt32(r,!0),r+4];if(e instanceof o)return[_.getBigInt64(r,!0),r+8];if(e instanceof l)return[t[r],r+1];if(e instanceof c)return[_.getUint8(r),r+1];if(e instanceof u)return[_.getUint32(r,!0),r+4];if(e instanceof p)return[_.getBigUint64(r,!0),r+8];if(e instanceof d)return[_.getFloat32(r,!0),r+4];if(e instanceof E)return[_.getFloat64(r,!0),r+8];if(e instanceof g){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof f){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof b){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=O(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof T){const n=x(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=O(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof y)return O(e._self,t,r);if(e instanceof M){let n=r;return[e._tuple.map((e=>{const[r,_]=O(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function P(e,t,r,_){const h=new DataView(t.buffer);if(e instanceof a)return h.setInt8(r,_),r+1;if(e instanceof s)return h.setInt16(r,_,!0),r+2;if(e instanceof i)return h.setInt32(r,_,!0),r+4;if(e instanceof o)return h.setBigInt64(r,_,!0),r+8;if(e instanceof l)return h.setUint8(r,_),r+1;if(e instanceof c)return h.setUint16(r,_,!0),r+2;if(e instanceof u)return h.setUint32(r,_,!0),r+4;if(e instanceof p)return h.setBigUint64(r,_,!0),r+8;if(e instanceof d)return h.setFloat32(r,_,!0),r+4;if(e instanceof E)return h.setFloat64(r,_,!0),r+8;if(e instanceof g){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof f){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof b){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=P(e,t,a,n[r])})),a}return(0,n.G)(e)}function x(e){return Math.ceil(Math.log2(e)/8)}const m=new a,w=new s,I=new i,U=new o,A=new l,B=new c,L=new u,C=new p,S=new d,v=new E,R=new g,W=new f;function K(e){return new b(e)}function V(e){return new D(e)}function k(e){return new T(e)}function j(...e){return new M(e)}function H(e){const t=new y(void 0),r=e(t);return t._self=r,r}var N;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(N||(N={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(e,t={}){return evalLoop(t.haskellCallback||(()=>{}),t.idenScope||globalContext,t.argScope||null,t.builderScope||null,e)}function evalUint8Array(e,t={}){return evalExpr(expr.decode(e),t)}function evalLoop(hscb,idenScope,argScope,builderScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I8:case ExprTag.I16:case ExprTag.I32:case ExprTag.I64:case ExprTag.U8:case ExprTag.U16:case ExprTag.U32:case ExprTag.U64:case ExprTag.F32:case ExprTag.F64:case ExprTag.Str:return exp[0];case ExprTag.Arr:return exp[0].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope));case ExprTag.Obj:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalLoop(hscb,idenScope,argScope,builderScope,t)])));case ExprTag.U8Arr:return exp[0];case ExprTag.Dot:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[2]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalLoop(hscb,idenScope,Cons(arguments,argScope),builderScope,exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return e.apply(void 0,exp[1].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope)))}case ExprTag.Call:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope)))}case ExprTag.AssignVar:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);return e?(e.delete(exp.varId),0==e.size&&varStorage.delete(exp.scopeId),null):null}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return finalizers.delete(exp.scopeId),e&&e.forEach((e=>e())),null}case ExprTag.AskDomBuilder:if(null==builderScope)throw new Error(\"AskDomBuilder called without prior SupplyDomBuilder!\");return builderScope[0];case ExprTag.SupplyDomBuilder:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.builder),t=Cons(e,builderScope);return evalLoop(hscb,idenScope,argScope,t,exp.expr)}case ExprTag.InsertNode:{if(null==builderScope)throw new Error(\"InsertNode called without prior SupplyDomBuilder!\");const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.child);return domHelpers.insertIntoBuilder(builderScope[0],e),null}case ExprTag.ElementProp:{if(null==builderScope)throw new Error(\"ElementProp called without prior SupplyDomBuilder!\");const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.propValue);return domHelpers.assignProperty(builderScope[0],exp.propName,e),null}case ExprTag.ElementAttr:if(null==builderScope)throw new Error(\"ElementAttr called without prior SupplyDomBuilder!\");return domHelpers.assignAttribute(builderScope[0],exp.attrName,exp.attrValue),null;case ExprTag.ClassListAdd:{if(null==builderScope)throw new Error(\"InsertClassList called without prior SupplyDomBuilder!\");const e=domHelpers.domBuilderElement(builderScope[0]);return exp.classList.forEach((t=>e.classList.add(t))),null}case ExprTag.ClassListRemove:{if(null==builderScope)throw new Error(\"RemoveClassList called without prior SupplyDomBuilder!\");const e=domHelpers.domBuilderElement(builderScope[0]);return exp.classList.forEach((t=>e.classList.remove(t))),null}case ExprTag.InsertBrackets:if(null==builderScope)throw new Error(\"InsertBoundary called without prior SupplyDomBuilder!\");return domHelpers.insertBrackets(builderScope[0]);case ExprTag.ClearBrackets:if(null==builderScope)throw new Error(\"InsertBoundary called without prior SupplyDomBuilder!\");return domHelpers.clearBrackets(builderScope[0],Boolean(exp.detach));case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateTextNode:return document.createTextNode(exp.content);case ExprTag.UpdateTextNode:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.node);return e.textContent=exp.content,null}case ExprTag.AddEventListener:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.target),t=evalLoop(hscb,idenScope,argScope,builderScope,exp.eventName),r=evalLoop(hscb,idenScope,argScope,builderScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalLoop(hscb,idenScope,argScope,builderScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalLoop(hscb,idenScope,argScope,builderScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerEvent:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerEventMsg,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Vbool,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.Vi32,0:e}:{tag:ValueTag.Vf64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.Vstr,0:e};if(\"bigint\"==typeof e)return{tag:ValueTag.Vi64,0:e};if(Array.isArray(e))return{tag:ValueTag.Varr,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Vu8arr,0:e};if(null==e)return{tag:ValueTag.Vnull};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Vobj,0:t}}!function(e){e[e.Vnull=0]=\"Vnull\",e[e.Vbool=1]=\"Vbool\",e[e.Vi8=2]=\"Vi8\",e[e.Vi16=3]=\"Vi16\",e[e.Vi32=4]=\"Vi32\",e[e.Vi64=5]=\"Vi64\",e[e.Vu8=6]=\"Vu8\",e[e.Vu16=7]=\"Vu16\",e[e.Vu32=8]=\"Vu32\",e[e.Vu64=9]=\"Vu64\",e[e.Vf32=10]=\"Vf32\",e[e.Vf64=11]=\"Vf64\",e[e.Vstr=12]=\"Vstr\",e[e.Varr=13]=\"Varr\",e[e.Vobj=14]=\"Vobj\",e[e.Vu8arr=15]=\"Vu8arr\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Vnull]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Vbool]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ValueTag.Vi32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.Vi64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.Vu8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ValueTag.Vu16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ValueTag.Vu32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ValueTag.Vu64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ValueTag.Vf32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ValueTag.Vf64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.Vstr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Varr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Vobj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Vu8arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Plus=19]=\"Plus\",e[e.Subtract=20]=\"Subtract\",e[e.Multiply=21]=\"Multiply\",e[e.Divide=22]=\"Divide\",e[e.Id=23]=\"Id\",e[e.Lam=24]=\"Lam\",e[e.Arg=25]=\"Arg\",e[e.Apply=26]=\"Apply\",e[e.Call=27]=\"Call\",e[e.AssignVar=28]=\"AssignVar\",e[e.FreeVar=29]=\"FreeVar\",e[e.Var=30]=\"Var\",e[e.FreeScope=31]=\"FreeScope\",e[e.AskDomBuilder=32]=\"AskDomBuilder\",e[e.SupplyDomBuilder=33]=\"SupplyDomBuilder\",e[e.InsertNode=34]=\"InsertNode\",e[e.ElementProp=35]=\"ElementProp\",e[e.ElementAttr=36]=\"ElementAttr\",e[e.ClassListAdd=37]=\"ClassListAdd\",e[e.ClassListRemove=38]=\"ClassListRemove\",e[e.InsertBrackets=39]=\"InsertBrackets\",e[e.ClearBrackets=40]=\"ClearBrackets\",e[e.CreateElement=41]=\"CreateElement\",e[e.CreateElementNS=42]=\"CreateElementNS\",e[e.CreateTextNode=43]=\"CreateTextNode\",e[e.UpdateTextNode=44]=\"UpdateTextNode\",e[e.AddEventListener=45]=\"AddEventListener\",e[e.ConnectResource=46]=\"ConnectResource\",e[e.SetTimeout=47]=\"SetTimeout\",e[e.ApplyFinalizer=48]=\"ApplyFinalizer\",e[e.RevSeq=49]=\"RevSeq\",e[e.Eval=50]=\"Eval\",e[e.TriggerEvent=51]=\"TriggerEvent\",e[e.UncaughtException=52]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ExprTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ExprTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ExprTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ExprTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.Str]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Obj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.U8Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.AskDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.SupplyDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({builder:e,expr:e}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({child:e}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ClassListAdd]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.ClassListRemove]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.InsertBrackets]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.ClearBrackets]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerEventMsg=2]=\"TriggerEventMsg\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerEventMsg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map,globalContext=[window,null];var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBrackets=function(e){const r=document.createComment(\"ContentBrackets {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBrackets=function(e,t){if(e instanceof Comment){let _=0;for(;e.previousSibling&&(0!=_||!n(e.previousSibling));)(r=e.previousSibling)instanceof Comment&&\"}}\"==r.textContent?_++:n(e.previousSibling)&&_--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var r},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=58;class _{static read_bytes(e,t){const r=new _;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let c,u=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],o.enable(n.debug),this.args=e,this.env=t,this.fds=r;const s=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(s.inst.exports.memory.buffer);r.setUint32(e,s.args.length,!0);let n=0;for(const e of s.args)n+=e.length+1;return r.setUint32(t,n,!0),o.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(s.inst.exports.memory.buffer),n=new Uint8Array(s.inst.exports.memory.buffer),_=t;for(let _=0;_null!=s.fds[e]?s.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:r,fdstat:n}=s.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(s.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:r,filestat:n}=s.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(s.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,a){const i=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=_.read_bytes_array(i,t,r),{ret:c,nread:u}=s.fds[e].fd_pread(o,l,n);return i.setUint32(a,u,!0),c}return 8},fd_prestat_get(e,t){const r=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:n,prestat:_}=s.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=s.fds[e]){const{ret:r,prestat_dir_name:n}=s.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(s.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,_){const i=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=a.read_bytes_array(i,t,r),{ret:c,nwritten:u}=s.fds[e].fd_pwrite(o,l,n);return i.setUint32(_,u,!0),c}return 8},fd_read(e,t,r,n){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=_.read_bytes_array(a,t,r),{ret:l,nread:c}=s.fds[e].fd_read(i,o);return a.setUint32(n,c,!0),l}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:l,dirent:c}=s.fds[e].fd_readdir_single(n);if(0!=l)return a.setUint32(_,o,!0),l;if(null==c)break;if(r-onull!=s.fds[e]?s.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:n,offset:_}=s.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,n){const _=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=a.read_bytes_array(_,t,r),{ret:l,nwritten:c}=s.fds[e].fd_write(i,o);return _.setUint32(n,c,!0),l}return 8},path_create_directory(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:l,filestat:c}=s.fds[e].path_filestat_get(t,o);return null!=c&&c.write_bytes(a,_),l}return 8},path_filestat_set_times(e,t,r,n,_,a,i){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return s.fds[e].path_filestat_set_times(t,l,_,a,i)}return 8},path_link(e,t,r,n,_,a,i){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[_]){const l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),c=new TextDecoder(\"utf-8\").decode(o.slice(a,a+i));return s.fds[_].path_link(e,t,l,c)}return 8},path_open(e,t,r,n,_,a,i,l,c){const u=new DataView(s.inst.exports.memory.buffer),p=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const d=new TextDecoder(\"utf-8\").decode(p.slice(r,r+n));o.log(d);const{ret:E,fd_obj:f}=s.fds[e].path_open(t,d,_,a,i,l);if(0!=E)return E;s.fds.push(f);const g=s.fds.length-1;return u.setUint32(c,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(l.slice(t,t+r));o.log(c);const{ret:u,data:p}=s.fds[e].path_readlink(c);if(null!=p){const e=(new TextEncoder).encode(p);if(e.length>_)return i.setUint32(a,0,!0),8;l.set(e,n),i.setUint32(a,e.length,!0)}return u}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[r]){const i=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return s.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(s.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class E{open(e){const t=new d(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new i(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class g{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)c=globalThis.setImmediate;else{const e=new g;c=(t,...r)=>e.setImmediate(t,...r)}const b=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>c(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=t=>{const n=r.bR.encode(t),_=D(e,n);e.wasm_app(_)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(_.expr,{haskellCallback:a}),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return D(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function D(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let T={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new u([],[],[new d(new E([])),new d(new E([])),new d(new E([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:b(T)});Object.assign(T,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),l=D(T,o);yield a.exports.wasm_app(l),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=D(T,t);T.wasm_app(n)}))}))},startDev:function(n,_=null){const a=new WebSocket(n),s=t=>e(this,void 0,void 0,(function*(){a.send(r.bR.encode(t))}));a.onopen=e=>{const t=r.bp(_),n=r.bR.encode({tag:r.dB.Start,0:t});a.send(n)},a.onmessage=n=>e(this,void 0,void 0,(function*(){const _=yield(a=n.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(a)})));var a;!function(n,_){e(this,void 0,void 0,(function*(){switch(n.tag){case r.I4.EvalExpr:{const e=r.wL(n.expr,{haskellCallback:_}),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:n.threadId};return _(a)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(n)}))}(r.sy.decode(_),s)})),a.onerror=e=>{console.error(\"WebSocket error:\",e)},a.onclose=e=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function e(t){const r=new WebSocket(n),_=Math.min(3e4,2*t);r.onopen=e=>window.location.reload(),r.onclose=r=>{setTimeout((()=>e(_)),t)}}(100)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" From f3f2f8b077dcc6315c4019adabd08f6fa740428c Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 4 Oct 2024 18:45:38 +0400 Subject: [PATCH 52/64] WIP --- benchmarks/benchmarks.hs | 27 ----- src/Clickable/#Protocol.hs# | 210 ++++++++++++++++++++++++++++++++++++ src/Clickable/FFI.hs | 2 +- src/Clickable/Main/Dev.hs | 6 +- src/Clickable/Protocol.hs | 30 +++--- 5 files changed, 230 insertions(+), 45 deletions(-) delete mode 100644 benchmarks/benchmarks.hs create mode 100644 src/Clickable/#Protocol.hs# diff --git a/benchmarks/benchmarks.hs b/benchmarks/benchmarks.hs deleted file mode 100644 index eb22cc2..0000000 --- a/benchmarks/benchmarks.hs +++ /dev/null @@ -1,27 +0,0 @@ -import Control.Monad -import Gauge -import HtmlT - -main = defaultMain - [ bench "benchDynamics 100 10 10" $ whnfIO (benchDynamics 100 10 10) - , bench "benchDynamics 10 100 10" $ whnfIO (benchDynamics 10 100 10) - , bench "benchDynamics 10 10 100" $ whnfIO (benchDynamics 10 10 100) - ] - -benchDynamics :: Int -> Int -> Int -> IO () -benchDynamics eventsNum subsNum fireNum = reactive do - -- Create a bunch of 'DynRef's - refsList <- forM [1..eventsNum] $ const (newRef (0 :: Int)) - outputRef <- newRef Nothing - -- Sum all of their values into a single 'Dynamic' using - -- 'Applicative' instance - let sumDyn = fmap sum . sequenceA . fmap fromRef $ refsList - -- Attach subsNum amount of subscriptions - sequence_ $ take subsNum $ repeat $ subscribeAndWrite sumDyn outputRef - -- And fire modification event for each 'DynRef' fireNum times - forM_ [1..fireNum] $ const $ - forM_ refsList $ dynStep . flip modifyRef succ - where - subscribeAndWrite from to = void $ subscribe (updates from) $ - writeRef to . Just - reactive act = newReactiveEnv >>= runReactiveT act diff --git a/src/Clickable/#Protocol.hs# b/src/Clickable/#Protocol.hs# new file mode 100644 index 0000000..8878eb4 --- /dev/null +++ b/src/Clickable/#Protocol.hs# @@ -0,0 +1,210 @@ +{-# LANGUAGE DerivingVia #-} +module Clickable.Protocol where + +import Data.Binary (Binary) +import Data.ByteString (ByteString) +import Data.Int +import Data.Text (Text) +import Data.String +import Data.Word +import GHC.Generics + +import Clickable.Protocol.Value + +data HaskellMessage + = EvalExpr Int32Le Expr + -- ^ Evaluate expression, expect the result to be returned by + -- 'Return' message + | HotReload + -- ^ Used under dev server, won't return anything + | Halt + -- ^ Signal that current process completed, won't return anything + deriving stock (Generic, Show) + deriving anyclass (Binary) + +data JavaScriptMessage + = Start StartFlags + | Return Int32Le Value + | TriggerEventMsg Value EventId + | BeforeUnload + -- ^ Fired from addEventListener("beforeunload") listener. Won't + -- work under the DevServer! + deriving (Generic, Show) + deriving anyclass (Binary) + +newtype StartFlags = StartFlags {unStartFlags :: Value} + deriving newtype (Generic, Show, Binary) + +-- | Strict Lambda calculus with arbitrary side-effects, meant to be +-- used as commands executed in the JavaScript side, optimized for +-- non-blocking execution and minimizing round-trips. +data Expr + = Null + -- ^ null or undefined values + | Bool Bool + -- ^ JavaScript boolean value + | I8 Int8 + | I16 Int16Le + | I32 Int32Le + | I64 Int64Le + + | U8 Word8 + | U16 Word16Le + | U32 Word32Le + | U64 Word64Le + + | F32 Float32Le + | F64 Float64Le + + | Str Text -- ^ JavaScript string + | Arr [Expr] -- ^ JavaScript array + | Obj [(Text, Expr)] -- ^ JavaScript object + | U8Arr ByteString -- ^ Raw byte array + + | Dot Expr Text + -- ^ Read string property of an object. @(Dot (Id "document") + -- "body")@ is equivalent to @document.body@ JavaScript expression + | SetProp Expr Text Expr + -- ^ Assign a value to a string property of an object @(AssignProp + -- (Id "foo") "bar" (Str "baz"))@ is equivalent to @foo['bar'] = + -- baz;@ JavaScript expression. Evaluates into its right-hand side + -- expression. + | Ix Expr Int64 + -- ^ Read value from an integer index of an object. @(Ix (Id + -- "foo") 0)@ is equivalent to @foo[0]@ JavaScript expression + + | Plus Expr Expr + -- ^ Binary addition @(Add 256 5647)@ is equivalent to @256 + 5647@ + | Subtract Expr Expr + -- ^ Binary substraction @(Subtract 256 5647)@ is equivalent to @256 - 5647@ + | Multiply Expr Expr + -- ^ Binary multiplication @(Multiply 256 5647)@ is equivalent to @256 * 5647@ + | Divide Expr Expr + -- ^ Binary division @(Divide 256 5647)@ is equivalent to @256 / 5647@ + + | Id Text -- ^ Lookup an identifier in current lexical scope + | Lam Expr + -- ^ Introduce a lambda function. Arguments can be accessed via 'Arg + -- 0 0' + | Arg Word8 Word8 + -- ^ Lookup an argument in the current argument scope. Separate + -- scope for argument from regular lexical scope required for + -- performance reasons. First field is "De Bruijn index" pointing to + -- nth-lambda counting outward from current expression. Second + -- number is positional argument for that lambda (each lambda + -- receives multiple arguments in a vector, see + -- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments) + -- De Bruijn indicies are notoriously hard to write manually, it's + -- one of the reasons this protocol is much less convenient than FFI + -- with JavaScript. One solution I found is that for complex code I + -- write regular JavaScript and run it with 'Eval'. + | Apply Expr [Expr] + -- ^ Apply a function to arbitrary length arguments. @Apply (Id + -- "encodeURIComponent") [Str "#"]@ going to evaluate to @String "%23"@ + | Call Expr Text [Expr] + -- ^ Call a method of an object @Call (Id "console") "log" [Str + -- "Hi!"]@ is equivalent to @console.log('Hi!')@ JavaScript code + + | AssignVar VarId Expr + -- ^ Assign a value to VarId allocated in haskell side. This way + -- haskell can save certain values between WASM reactor invocations + | FreeVar VarId + -- ^ Free variable allocated with @AssignVar@ + | Var VarId + -- ^ Retrieve the value of the variable + | FreeScope ResourceScope + -- ^ Free all the resources assosiated with the given ResourceScope + + | AskDomBuilder + | SupplyDomBuilder DomBuilder Expr + + | InsertNode Expr + | ElementProp Text Expr + | ElementAttr Text Text + | ClassListAdd [Text] + | ClassListRemove [Text] + | InsertBrackets + | ClearBrackets Bool + + | CreateElement Text + | CreateElementNS Text Text + | CreateTextNode Text + | UpdateTextNode Expr Text + + | AddEventListener ResourceScope Expr Expr Expr + -- ^ @AddEventListener rscope target eventName listener@ is + -- equivalent to @target.addEventListener(eventName, listener)@ it + -- returns @FinalizerId@ integer identifier that can be used in + -- 'RemoveEventListener', but calling 'RemoveEventListener' is not + -- required, it'll be called authomatically when given ResourceScope + -- will be freed with 'FreeScope' + | ConnectResource ResourceScope Expr + -- ^ Returns FinalizerId + | SetTimeout ResourceScope Expr Int32Le + -- ^ Returns FinalizerId + | ApplyFinalizer ResourceScope Expr + -- ^ Actuate given finalizer before the ResourceScope is freed + + | RevSeq [Expr] + -- ^ Sequence of the expressions in reverse order. It will be + -- evaluated from the end to the beggining of the list. Returns + -- whatever the last expression (from the head of the list) + -- evaluates into. Order is reversed to support fast insertion of + -- new instructions + | Eval UnsafeJavaScript + -- ^ Evaluate arbitrary JavaScript code @(Eval "setTimeout(() => + -- console.log('Hi!'), 1000)")@ will print a message with one second + -- delay + | TriggerEvent EventId Expr + -- ^ Emits `TriggerEventMsg` as a side-effect + | UncaughtException Text + deriving stock (Generic, Show) + deriving anyclass (Binary) + +valueToExpr :: Value -> Expr +valueToExpr = \case + Vnull -> Null + Vbool a -> Bool a + + Vi8 a -> I8 a + Vi16 a -> I16 a + Vi32 a -> I32 a + Vi64 a -> I64 a + + Vu8 a -> U8 a + Vu16 a -> U16 a + Vu32 a -> U32 a + Vu64 a -> U64 a + + Vf64 a -> F64 a + Vf32 a -> F32 a + + Vstr a -> Str a + Varr xs -> Arr $ fmap valueToExpr xs + Vobj kv -> Obj $ fmap (\(k, v) -> (k, valueToExpr v)) kv + Vu8arr a -> U8Arr a + +toExpr :: ToValue a => a -> Expr +toExpr = valueToExpr . toValue + +newtype DomBuilder = DomBuilder {unDomBuilder :: Expr} + deriving newtype (Show, Binary) + +data VarId = VarId ResourceScope Int32Le + deriving stock (Generic, Show, Ord, Eq) + deriving anyclass (Binary) + +newtype FinalizerId = FinalizerId {unFinalizerId :: Int32} + deriving newtype (Show, Ord, Eq) + deriving Binary via Int32Le + +newtype ResourceScope = ResourceScope {unResourceScope :: Int32} + deriving newtype (Show, Ord, Eq) + deriving Binary via Int32Le + +newtype EventId = EventId {unEventId :: Int32} + deriving newtype (Show, Ord, Eq) + deriving Binary via Int32Le + +newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} + deriving newtype (IsString, Show, Semigroup, Monoid, Binary) diff --git a/src/Clickable/FFI.hs b/src/Clickable/FFI.hs index 20c3c8f..f4c6608 100644 --- a/src/Clickable/FFI.hs +++ b/src/Clickable/FFI.hs @@ -29,7 +29,7 @@ js_consoleLog :: Ptr Word8 -> Int -> IO () js_consoleLog = undefined #else foreign import javascript unsafe - "evalMessage(__exports, $1)" + "clickable.evalMessage(__exports, $1)" js_evalMessage :: Ptr Word8 {- HaskellMessage -} -> IO (Ptr Word8 {- JavaScriptMessage -}) foreign import javascript unsafe "console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));" diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs index f0d8c23..72e7f81 100644 --- a/src/Clickable/Main/Dev.hs +++ b/src/Clickable/Main/Dev.hs @@ -41,8 +41,10 @@ import "this" Clickable.Types data DevConfig a = DevConfig { aquire_resource :: IO a - -- ^ Usualy runs once just after ghci session is loaded, - -- e.g. establish connection to database etc + -- ^ Called once the GHCi session is loaded. Returns a polymorphic + -- resource that typically contains a database connection and other + -- long-lived entities that persist across versions when the + -- application is reloaded. , release_resource :: a -> IO () -- ^ Runs before the ghci session is unloaded , reload_app :: a -> IO ApplicationSpec diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs index 8878eb4..754d449 100644 --- a/src/Clickable/Protocol.hs +++ b/src/Clickable/Protocol.hs @@ -12,7 +12,7 @@ import GHC.Generics import Clickable.Protocol.Value data HaskellMessage - = EvalExpr Int32Le Expr + = EvalExpr I32 Expr -- ^ Evaluate expression, expect the result to be returned by -- 'Return' message | HotReload @@ -24,7 +24,7 @@ data HaskellMessage data JavaScriptMessage = Start StartFlags - | Return Int32Le Value + | Return I32 Value | TriggerEventMsg Value EventId | BeforeUnload -- ^ Fired from addEventListener("beforeunload") listener. Won't @@ -44,17 +44,17 @@ data Expr | Bool Bool -- ^ JavaScript boolean value | I8 Int8 - | I16 Int16Le - | I32 Int32Le - | I64 Int64Le + | I16 I16 + | I32 I32 + | I64 I64 | U8 Word8 - | U16 Word16Le - | U32 Word32Le - | U64 Word64Le + | U16 U16 + | U32 U32 + | U64 U64 - | F32 Float32Le - | F64 Float64Le + | F32 F32 + | F64 F64 | Str Text -- ^ JavaScript string | Arr [Expr] -- ^ JavaScript array @@ -140,7 +140,7 @@ data Expr -- will be freed with 'FreeScope' | ConnectResource ResourceScope Expr -- ^ Returns FinalizerId - | SetTimeout ResourceScope Expr Int32Le + | SetTimeout ResourceScope Expr I32 -- ^ Returns FinalizerId | ApplyFinalizer ResourceScope Expr -- ^ Actuate given finalizer before the ResourceScope is freed @@ -190,21 +190,21 @@ toExpr = valueToExpr . toValue newtype DomBuilder = DomBuilder {unDomBuilder :: Expr} deriving newtype (Show, Binary) -data VarId = VarId ResourceScope Int32Le +data VarId = VarId ResourceScope I32 deriving stock (Generic, Show, Ord, Eq) deriving anyclass (Binary) newtype FinalizerId = FinalizerId {unFinalizerId :: Int32} deriving newtype (Show, Ord, Eq) - deriving Binary via Int32Le + deriving Binary via I32 newtype ResourceScope = ResourceScope {unResourceScope :: Int32} deriving newtype (Show, Ord, Eq) - deriving Binary via Int32Le + deriving Binary via I32 newtype EventId = EventId {unEventId :: Int32} deriving newtype (Show, Ord, Eq) - deriving Binary via Int32Le + deriving Binary via I32 newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} deriving newtype (IsString, Show, Semigroup, Monoid, Binary) From ad89c9cb12f50ef9b6a07286c74867ae29f317ca Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 8 Oct 2024 18:35:03 +0400 Subject: [PATCH 53/64] WIP: new version --- .dir-locals.el | 18 + .gitignore | 32 +- 9.6.5.nix | 26 + Clickable.hs | 8 + Clickable/Float.hs | 27 + Clickable/Html.hs | 102 ++++ Clickable/Internal.hs | 346 +++++++++++ Clickable/Types.hs | 475 +++++++++++++++ Clickable/Wasm.hs | 71 +++ Clickable/WebSocket.hs | 169 ++++++ LICENSE | 42 +- README.md | 202 ------- bin/README.md | 57 ++ bin/nix-bins | 55 ++ cabal.project | 4 +- clickable.cabal | 42 ++ default.nix | 54 -- examples/examples.cabal | 44 -- examples/todomvc/App.hs | 24 - examples/todomvc/TodoItem.hs | 84 --- examples/todomvc/TodoList.hs | 568 ------------------ examples/todomvc/Utils.hs | 18 - examples/todomvc/dev.hs | 5 - examples/todomvc/wasm.hs | 10 - ghc-wasm-meta | 1 - hie.yaml | 4 + htmlt.cabal | 73 --- jsbits/#wasm.ts# | 66 +++ jsbits/#websocket.ts# | 82 +++ jsbits/binary.ts | 467 --------------- jsbits/dev.ts | 91 --- jsbits/index.js | 10 +- jsbits/jsffi.js | 106 ---- jsbits/lib.ts | 100 ---- jsbits/post-link.mjs | 100 ---- jsbits/prelude.js | 93 --- jsbits/proto.ts | 985 ++++++++++++++++++++++++++++++++ jsbits/protocol.ts | 774 ------------------------- jsbits/wasm.ts | 141 ++--- jsbits/websocket.ts | 82 +++ package.json | 10 + shell.nix | 98 +++- src/Clickable.hs | 10 - src/Clickable/#Protocol.hs# | 210 ------- src/Clickable/Core.hs | 399 ------------- src/Clickable/DOM.hs | 276 --------- src/Clickable/Element.hs | 402 ------------- src/Clickable/FFI.hs | 37 -- src/Clickable/Internal.hs | 251 -------- src/Clickable/Main/Dev.hs | 328 ----------- src/Clickable/Main/Wasm.hs | 67 --- src/Clickable/Property.hs | 366 ------------ src/Clickable/Protocol.hs | 210 ------- src/Clickable/Protocol/Value.hs | 296 ---------- src/Clickable/Types.hs | 115 ---- src/Wasm/Compat/Prim.hs | 76 --- wasm.hs | 59 ++ websocket.hs | 62 ++ yarn.lock | 895 +++++++++++++++++++++++++++++ 59 files changed, 3817 insertions(+), 6008 deletions(-) create mode 100644 .dir-locals.el create mode 100644 9.6.5.nix create mode 100644 Clickable.hs create mode 100644 Clickable/Float.hs create mode 100644 Clickable/Html.hs create mode 100644 Clickable/Internal.hs create mode 100644 Clickable/Types.hs create mode 100644 Clickable/Wasm.hs create mode 100644 Clickable/WebSocket.hs delete mode 100644 README.md create mode 100644 bin/README.md create mode 100755 bin/nix-bins create mode 100644 clickable.cabal delete mode 100644 default.nix delete mode 100644 examples/examples.cabal delete mode 100644 examples/todomvc/App.hs delete mode 100644 examples/todomvc/TodoItem.hs delete mode 100644 examples/todomvc/TodoList.hs delete mode 100644 examples/todomvc/Utils.hs delete mode 100644 examples/todomvc/dev.hs delete mode 100644 examples/todomvc/wasm.hs delete mode 160000 ghc-wasm-meta create mode 100644 hie.yaml delete mode 100644 htmlt.cabal create mode 100644 jsbits/#wasm.ts# create mode 100644 jsbits/#websocket.ts# delete mode 100644 jsbits/binary.ts delete mode 100644 jsbits/dev.ts delete mode 100644 jsbits/jsffi.js delete mode 100644 jsbits/lib.ts delete mode 100755 jsbits/post-link.mjs delete mode 100644 jsbits/prelude.js create mode 100644 jsbits/proto.ts delete mode 100644 jsbits/protocol.ts create mode 100644 jsbits/websocket.ts create mode 100644 package.json delete mode 100644 src/Clickable.hs delete mode 100644 src/Clickable/#Protocol.hs# delete mode 100644 src/Clickable/Core.hs delete mode 100644 src/Clickable/DOM.hs delete mode 100644 src/Clickable/Element.hs delete mode 100644 src/Clickable/FFI.hs delete mode 100644 src/Clickable/Internal.hs delete mode 100644 src/Clickable/Main/Dev.hs delete mode 100644 src/Clickable/Main/Wasm.hs delete mode 100644 src/Clickable/Property.hs delete mode 100644 src/Clickable/Protocol.hs delete mode 100644 src/Clickable/Protocol/Value.hs delete mode 100644 src/Clickable/Types.hs delete mode 100644 src/Wasm/Compat/Prim.hs create mode 100644 wasm.hs create mode 100644 websocket.hs create mode 100644 yarn.lock diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..998faf6 --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,18 @@ +((nil + (eval . + (setq my-proj-dir + (file-name-directory + (let ((d (dir-locals-find-file "."))) + (if (stringp d) d (car d)))) + lsp-haskell-server-path (concat my-proj-dir "/bin/haskell-language-server")))) + + (haskell-mode + (eval . + (setq my-proj-dir + (file-name-directory + (let ((d (dir-locals-find-file "."))) + (if (stringp d) d (car d)))) + haskell-hoogle-server-command + (lambda (port) + (list (concat my-proj-dir "bin/hoogle") "server" + "--local" "-p" (number-to-string port))))))) diff --git a/.gitignore b/.gitignore index 4191b2b..47c63dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,27 +1,7 @@ -**/tags -**/TAGS -**/.#* -**/dist-newstyle -/examples/dist-newstyle -**/*~ -**/*.kate-swp -**/.directory -**/.dir-locals.el -**/.envrc -**/.envrc-ghcjs -/dist -/tmp -**/.stack-work -**/.cabal-sandbox -**/*.db -**/.ghc.environment* -/.*-env -result -dist -bin -out +bin/** +!bin/nix-bins +!bin/README.md +shell.nix doc -locals.nix -node_modules -package.json -yarn.lock +dist-newstyle +node_modules \ No newline at end of file diff --git a/9.6.5.nix b/9.6.5.nix new file mode 100644 index 0000000..340b5e3 --- /dev/null +++ b/9.6.5.nix @@ -0,0 +1,26 @@ +let + sources = { + nixpkgs = builtins.fetchTarball { + url = "https://github.com/NixOS/nixpkgs/archive/refs/tags/24.05.tar.gz"; + }; + ghc-wasm-meta = "gitlab:ghc/ghc-wasm-meta?host=gitlab.haskell.org&ref=108e4693cd147777e8d93683e58c8a5e1da74c96"; + }; + + pkgs = import sources.nixpkgs {}; + + haskellPackages = pkgs.haskellPackages.override { + overrides = final: prev: { + clickable = final.callCabal2nix "clickable" ./. {}; + }; + }; + + ghc-wasm-meta = builtins.getFlake sources.ghc-wasm-meta; +in + pkgs.mkShell { + inputsFrom = [ + haskellPackages.clickable.env + ]; + nativeBuildInputs = [ + ghc-wasm-meta.packages.x86_64-linux.default + ]; + } diff --git a/Clickable.hs b/Clickable.hs new file mode 100644 index 0000000..8a36d21 --- /dev/null +++ b/Clickable.hs @@ -0,0 +1,8 @@ +{-| Fast and Lightweight Frontend library for WASM, JavaScript and +Native GHC -} +module Clickable (module Exports) where + +import Clickable.Html as Exports +import Clickable.Internal as Exports +import Clickable.Types as Exports +import Clickable.WebSocket as Exports diff --git a/Clickable/Float.hs b/Clickable/Float.hs new file mode 100644 index 0000000..470e6b9 --- /dev/null +++ b/Clickable/Float.hs @@ -0,0 +1,27 @@ +{-# LANGUAGE StrictData #-} +{-# LANGUAGE DerivingStrategies #-} +{-| Normal `Data.Binary.Binary` instances for floating-point numbers +replacing the impractical and unnatural encoding in the default +instances for `Float` and `Double` +-} +module Clickable.Float where + +import Data.Binary +import Data.Binary.Get +import Data.Binary.Put + + +newtype Float64 = Float64 {unFloat64 :: Double} + deriving newtype (Show, Ord, Eq) + +instance Binary Float64 where + put = putDoublele . unFloat64 + get = fmap Float64 getDoublele + + +newtype Float32 = Float32 {unFloat32 :: Float} + deriving newtype (Show, Ord, Eq) + +instance Binary Float32 where + put = putFloatle . unFloat32 + get = fmap Float32 getFloatle diff --git a/Clickable/Html.hs b/Clickable/Html.hs new file mode 100644 index 0000000..474f146 --- /dev/null +++ b/Clickable/Html.hs @@ -0,0 +1,102 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE DataKinds #-} +module Clickable.Html where + +import Clickable.Internal ( subscribe, readVal, reactive, newRefId, enqueueExpr, newRefIdOp ) +import Clickable.Types +import Control.Monad.Reader +import Data.Binary qualified as Binary +import Data.Binary.Put (execPut) +import Data.Kind (Type) +import Data.Text (Text) +import GHC.Generics (Generic) +import Unsafe.Coerce (unsafeCoerce) + +el :: Text -> ClickM a -> ClickM a +el tagName child = ClickM \e -> do + e.hte_send $ execPut $ Binary.put $ PushStack $ CreateElement tagName + r <- child.unClickM e + e.hte_send $ execPut $ Binary.put PopIns + pure r +{-# INLINE el #-} + +text :: Text -> ClickM () +text content = ClickM \e -> do + e.hte_send $ execPut $ Binary.put $ PushStack $ CreateTextNode content + e.hte_send $ execPut $ Binary.put $ PopIns +{-# INLINE text #-} + +dynText :: DynVal Text -> ClickM () +dynText contentDyn = ClickM \e -> do + c <- readVal contentDyn + refId <- newRefId.unClickM e + e.hte_send $ execPut $ Binary.put $ PushStack $ CreateTextNode c + e.hte_send $ execPut $ Binary.put $ AssignRef refId (PeekStack 0) + e.hte_send $ execPut $ Binary.put $ PopIns + (subscribe contentDyn \nval -> ClickM \_ -> + e.hte_send $ execPut $ Binary.put $ UpdateTextNode (Ref refId) nval + ).unClickM e +{-# INLINEABLE dynText #-} + +prop :: Text -> Expr -> ClickM () +prop k v = ClickM \e -> + e.hte_send $ execPut $ Binary.put $ ElementProp (PeekStack 0) k v +{-# INLINE prop #-} + +addEventListener :: (Event ValueExpr -> Expr) -> (ValueExpr -> ClickM ()) -> ClickM () +addEventListener connectScript k = do + e <- reactive \scope s -> + let k' = local (\e -> e {hte_scope = scope}) . k + eventId = EventId s.next_id + (s', unSubRef) = newRefIdOp scope s {next_id = s.next_id + 1} + newSub = SubscriptionSimple scope (unsafeFromEventId eventId) (k' . unsafeCoerce) + newFin = CustomFinalizer scope $ enqueueExpr $ Apply (Ref unSubRef) Null + s'' = s' {subscriptions = newSub : s.subscriptions, finalizers = newFin : s.finalizers} + in (s'', AssignRef unSubRef (connectScript (Event eventId))) + enqueueExpr e + +class IsEventName eventName where + type EventListenerCb eventName :: Type + connectEventName :: EventListenerCb eventName -> ClickM () + +on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> ClickM () +on k = connectEventName @eventName k + +instance IsEventName "click" where + type EventListenerCb "click" = ClickM () + connectEventName k = addEventListener + (genericEvent defaultEventListenerOptions "click") (const k) + +data EventListenerOptions = EventListenerOptions + { prevent_default :: Bool + , stop_propagation :: Bool + } deriving stock (Generic, Show, Eq) + +defaultEventListenerOptions :: EventListenerOptions +defaultEventListenerOptions = EventListenerOptions + { prevent_default = False + , stop_propagation = False + } + +genericEvent :: EventListenerOptions -> Text -> Event ValueExpr -> Expr +genericEvent opt eventName (Event eventId) = + Eval + ("(function([target, trigger]){\n\ + \ function listener(event){\n\ + \ " <> preventDefaultStmt <> "\n\ + \ " <> stopPropagationStmt <> "\n\ + \ trigger();\n\ + \ }\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \})") `Apply` Arr [PeekStack 0, Lam (TriggerEvent eventId Null)] + where + preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" + stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs new file mode 100644 index 0000000..c369d7b --- /dev/null +++ b/Clickable/Internal.hs @@ -0,0 +1,346 @@ +{-# LANGUAGE StrictData #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# OPTIONS_GHC -Wno-name-shadowing #-} +module Clickable.Internal where + +import Clickable.Types +import Control.Monad +import Control.Monad.Reader +import Control.Monad.State.Strict +import Data.Binary qualified as Binary +import Data.Binary.Put (execPut) +import Data.ByteString.Builder ( Builder ) +import Data.ByteString.Builder.Extra (runBuilder, Next (..), BufferWriter) +import Data.ByteString.Unsafe +import Data.Functor.Const +import Data.IORef +import Data.List qualified as List +import Data.Map (Map) +import Data.Map qualified as Map +import Data.Text (Text) +import Data.Tuple (swap) +import Data.Word +import Foreign.C.String (CStringLen) +import Foreign.Marshal.Alloc (mallocBytes) +import Foreign.Ptr +import GHC.Exts +import Unsafe.Coerce + + +subscribe :: forall a. DynVal a -> (a -> ClickM ()) -> ClickM () +subscribe (ConstVal _) _ = return () +subscribe (FromVar (SourceVar srcid _)) k = reactive_ g where + newSub scope = SubscriptionSimple scope (coerce srcid) (k . unsafeCoerce) + g scope s = s {subscriptions = newSub scope : s.subscriptions} +subscribe (FromVar (OverrideVar _ var)) k = + subscribe (FromVar var) k +subscribe (FromVar (LensMap l var)) k = + subscribe (FromVar var) (k . getConst . l Const) +subscribe (MapVal v f) k = subscribe v (k . f) +subscribe (SplatVal fv av) k = do + src <- reactive h + subscribe fv $ f src + subscribe av $ g src + where + h scope s = (s', coerce event) where + s' = s + { subscriptions = newsub : s.subscriptions + , next_id = s.next_id + 1 + } + event = unsafeFromEventId $ EventId s.next_id + newsub = SubscriptionSimple scope event (k . unsafeCoerce) + f src fv' = do + av' <- readVal av + triggerEvent src $ fv' av' + g src av' = do + fv' <- readVal fv + triggerEvent src $ fv' av' +subscribe (OverrideSub f d) k = f subscribe' k' where + k' a _ = k a + subscribe' c = subscribe d \a -> c a () + +triggerEventOp :: Event a -> a -> InternalState -> InternalState +triggerEventOp event pload = + defer event $ gets (.subscriptions) >>= notify + where + eventEq :: forall a b. Event a -> Event b -> Bool + eventEq (Event a) (Event b) = a == b + + notify :: [Subscription Any] -> ClickM () + notify [] = return () + notify (SubscriptionSimple {ss_event_id, ss_callback} : xs) + | ss_event_id `eventEq` event = ss_callback (unsafeCoerce pload) >> notify xs + | otherwise = notify xs + notify (SubscriptionAccum {sa_event_id, sa_callback, sa_accum_ref} : xs) + | sa_event_id `eventEq` event = notifyAcc sa_callback sa_accum_ref >> notify xs + | otherwise = notify xs + notifyAcc :: forall b. (Any -> b -> ClickM b) -> IORef b -> ClickM () + notifyAcc k ref = do + acc <- liftIO $ readIORef ref + acc' <- k (unsafeCoerce pload) acc + liftIO $ writeIORef ref acc' + defer :: Event a -> ClickM () -> InternalState -> InternalState + defer k act s = s + {transaction_queue = Map.insert k.unEvent act s.transaction_queue} + +triggerEvent :: Event a -> a -> ClickM () +triggerEvent e a = modify $ triggerEventOp e a +{-# INLINE triggerEvent #-} + +reactive :: (ScopeId -> InternalState -> (InternalState, a)) -> ClickM a +reactive f = ClickM \e -> atomicModifyIORef' e.hte_state $ f e.hte_scope +{-# INLINE reactive #-} + +reactive_ :: (ScopeId -> InternalState -> InternalState) -> ClickM () +reactive_ f = reactive \scope s -> (f scope s, ()) +{-# INLINE reactive_ #-} + +-- | Loop until transaction_queue is empty. +-- +-- Makes possible to implement @Applicative DynVal@ without invoking +-- subscribers redundantly when multiple events are fired in the same +-- transition +trampoline :: ClickM a -> ClickM a +trampoline act = loop0 act where + loop0 :: ClickM a -> ClickM a + loop0 before = do + r <- before + mcont <- popQueue + forM_ mcont loop1 + return r + loop1 :: ClickM () -> ClickM () + loop1 before = do + before + mcont <- popQueue + forM_ mcont loop1 + popQueue :: ClickM (Maybe (ClickM ())) + popQueue = state \s -> + case Map.minViewWithKey s.transaction_queue of + Nothing -> (Nothing, s) + Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) + +runTransition :: InternalEnv -> ClickM () -> IO () +runTransition e c = + prompt e.hte_prompt_tag $ + ($ e) . unClickM . (<* syncPoint) . trampoline $ c + +syncPoint :: ClickM () +syncPoint = ClickM \e -> void $ e.hte_flush + +unsafeInsertHtml :: Text -> Expr +unsafeInsertHtml rawHtml = Eval + "(function(args){\ + \var parent = args[0];\ + \var rawHtml = args[1];\ + \var div = document.createElement('div');\ + \div.innerHTML = rawHtml;\ + \var iter = div.childNodes[0];\ + \for (; iter; iter = div.childNodes[0]) {\ + \ div.removeChild(iter);\ + \ if (parent instanceof Comment) {\ + \ parent.parentElement.insertBefore(iter, parent);\ + \ } else{\ + \ parent.appendChild(iter);\ + \ }\ + \}\ + \})" `Apply` (Arr [PeekStack 0, Str rawHtml]) + +newScope :: ClickM ScopeId +newScope = reactive newScopeOp +{-# INLINE newScope #-} + +newScopeOp :: ScopeId -> InternalState -> (InternalState, ScopeId) +newScopeOp p s = (s', scope) + where + s' = s {finalizers = fns, next_id = s.next_id + 1} + fns = ScopeFinalizer p scope : s.finalizers + scope = ScopeId s.next_id +{-# INLINE newScopeOp #-} + +newRefId :: ClickM RefId +newRefId = reactive newRefIdOp +{-# INLINE newRefId #-} + +newRefIdOp :: ScopeId -> InternalState -> (InternalState, RefId) +newRefIdOp e s = (s {next_id = s.next_id + 1}, RefId e s.next_id) +{-# INLINE newRefIdOp #-} + +freeScope :: Bool -> ScopeId -> ClickM () +freeScope unlink s = + reactive (const (freeScopeOp unlink s)) >>= applyFin + where + applyFin [] = enqueueExpr $ FreeScope s + applyFin (ScopeFinalizer{sf_linked_scope}:xs) = freeScope True sf_linked_scope >> applyFin xs + applyFin (CustomFinalizer{cf_callback}:xs) = cf_callback >> applyFin xs +{-# INLINE freeScope #-} + +freeScopeOp :: Bool -> ScopeId -> InternalState -> (InternalState, [Finalizer]) +freeScopeOp unlink scope s = + (s {subscriptions, finalizers}, scopeFns) + where + chkSub s' = subscriptionScope s' /= scope + chkFin True ScopeFinalizer{sf_resource_scope, sf_linked_scope} = + sf_resource_scope /= scope && sf_linked_scope /= scope + chkFin True CustomFinalizer{cf_resource_scope} = cf_resource_scope /= scope + chkFin False f = finalizerScope f /= scope + (finalizers, scopeFns) = List.partition (chkFin unlink) s.finalizers + subscriptions = List.filter chkSub s.subscriptions +{-# INLINE freeScopeOp #-} + +installFinalizer :: ClickM () -> ClickM () +installFinalizer = reactive_ . installFinalizerOp +{-# INLINE installFinalizer #-} + +installFinalizerOp :: ClickM () -> ScopeId -> InternalState -> InternalState +installFinalizerOp k scope s = + s {finalizers = CustomFinalizer scope k : s.finalizers} +{-# INLINE installFinalizerOp #-} + +emptyState :: InternalState +emptyState = InternalState [] [] Map.empty 0 + +--------------------------------------- +-- OPERATIONS OVER DYNAMIC VARIABLES -- +--------------------------------------- + +readVal :: MonadIO m => DynVal a -> m a +readVal (ConstVal a) = pure a +readVal (FromVar var) = readVar var +readVal (MapVal val f) = fmap f $ readVal val +readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) +readVal (OverrideSub _ a) = readVal a + +readVar :: MonadIO m => DynVar a -> m a +readVar (SourceVar _ ref) = liftIO $ readIORef ref +readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var +readVar (OverrideVar _ var) = readVar var + +newVar :: a -> ClickM (DynVar a) +newVar a = do + ref <- liftIO $ newIORef a + let mkEv s = unsafeFromEventId $ EventId s.next_id + state \s -> (SourceVar (mkEv s) ref, s {next_id = s.next_id + 1}) + +overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a +overrideVar = OverrideVar + +lensMap :: Lens' s a -> DynVar s -> DynVar a +lensMap = LensMap + +modifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a +modifyVar (SourceVar varId ref) f = do + (newVal, a) <- liftIO $ atomicModifyIORef' ref g + triggerEvent varId newVal + return a + where + g old = let (new, a) = f old in (new, (new, a)) +modifyVar (OverrideVar ufn var) f = + ufn (modifyVar var) f +modifyVar (LensMap l var) f = modifyVar var (swap . l (swap . f)) + +modifyVar_ :: DynVar s -> (s -> s) -> ClickM () +modifyVar_ var f = modifyVar var ((,()) . f) + +writeVar :: DynVar s -> s -> ClickM () +writeVar var s = modifyVar_ var $ const s + +forDyn :: DynVal a -> (a -> ClickM ()) -> ClickM () +forDyn dval action = readVal dval >>= action >> subscribe dval action + +forVar :: DynVar a -> (a -> ClickM ()) -> ClickM () +forVar = forDyn . fromVar + +-- | Update the value inside a DynVar without notifying +-- subscribers. Intended to be used as a workaround to synchronize the +-- state when the DOM was already updated locally. Consider "input" +-- event on elements: in some cases you can use +-- modifyVarQuiet for efficiency since you already know value +-- has already been updated. +-- +-- @ +-- counter <- newVar (0::Int) +-- input_ do +-- dynProp "value" counter +-- on @"input" \t -> +-- forM_ (readMaybe t) \v -> writeVarQuiet_ counter v +-- button_ do {text "-"; on @"click" $ modifyVar_ counter pred;} +-- button_ do {text "+"; on @"click" $ modifyVar_ counter succ;} +-- @ +modifyVarQuiet :: DynVar s -> (s -> (s, a)) -> ClickM a +modifyVarQuiet (SourceVar _varId ref) f = do + liftIO $ atomicModifyIORef' ref f +modifyVarQuiet (OverrideVar ufn var) f = + ufn (modifyVarQuiet var) f +modifyVarQuiet (LensMap l var) f = + modifyVarQuiet var (swap . l (swap . f)) +{-# INLINEABLE modifyVarQuiet #-} + +modifyVarQuiet_ :: DynVar s -> (s -> s) -> ClickM () +modifyVarQuiet_ var f = modifyVarQuiet var ((,()) . f) +{-# INLINE modifyVarQuiet_ #-} + +writeVarQuiet :: DynVar s -> s -> ClickM () +writeVarQuiet var = modifyVarQuiet_ var . const +{-# INLINE writeVarQuiet #-} + +enqueueExpr :: Expr -> ClickM () +enqueueExpr exp = ClickM \e -> + e.hte_send $ execPut $ Binary.put exp +{-# INLINE enqueueExpr #-} + +evalExpr :: Expr -> ClickM Expr +evalExpr exp = ClickM \e -> do + e.hte_send $ execPut $ Binary.put exp + return undefined +{-# INLINE evalExpr #-} + +withBuffer :: Ptr Word8 -> Int -> (CStringLen -> IO ()) -> IO (Builder -> IO (), IO ()) +withBuffer buf bufSize consume = do + -- buf <- mallocBytes bufSize + offset <- newIORef 0 + let write b = do + off <- readIORef offset + newOff <- writeLoop (runBuilder b) off + writeIORef offset newOff + writeLoop :: BufferWriter -> Int -> IO Int + writeLoop bufWrite off = do + (written, next) <- bufWrite (buf `plusPtr` off) (bufSize - off) + case next of + Done -> pure $ off + written + More _size moreWrite -> do + consume (castPtr buf, bufSize) + writeLoop moreWrite 0 + Chunk chunk moreWrite -> do + unsafeUseAsCStringLen chunk consume + writeLoop moreWrite off + flush = do + off <- atomicModifyIORef' offset (0,) + consume (castPtr buf, off) + return (write, flush) + +newInternalEnv :: Int -> (CStringLen -> IO ()) -> IO + ( InternalEnv + , IORef (Map Word32 (IO ValueExpr -> IO ())) + , CStringLen ) +newInternalEnv bufSize consume = do + buf <- mallocBytes bufSize + hte_state <- newIORef emptyState + (send', flush) <- withBuffer buf bufSize consume + hte_prompt_tag <- newPromptTag + continuations <- newIORef Map.empty + let env = InternalEnv + { hte_send = send' + , hte_flush = do + tid <- atomicModifyIORef' hte_state \s -> + (s {next_id = s.next_id + 1}, s.next_id) + send' $ execPut $ Binary.put $ YieldResult tid + flush + control hte_prompt_tag \c -> + modifyIORef' continuations $ Map.insert tid c + , hte_state + , hte_scope = ScopeId 0 + , hte_prompt_tag + } + pure (env, continuations, (castPtr buf, bufSize)) diff --git a/Clickable/Types.hs b/Clickable/Types.hs new file mode 100644 index 0000000..11ff471 --- /dev/null +++ b/Clickable/Types.hs @@ -0,0 +1,475 @@ +{-# LANGUAGE StrictData #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnboxedTuples #-} +module Clickable.Types where + +import Clickable.Float +import Control.Monad.Reader +import Control.Monad.State.Strict +import Data.Binary ( Binary ) +import Data.Bool (bool) +import Data.ByteString (ByteString) +import Data.ByteString.Builder ( Builder ) +import Data.IORef +import Data.Int +import Data.Map (Map) +import Data.Maybe (mapMaybe) +import Data.Text (Text) +import Data.Tuple +import Data.Word +import GHC.Exts +import GHC.Generics +import GHC.Types +import qualified Data.Text as Text +import qualified GHC.Generics as G +import qualified GHC.List as List + +newtype ClickM a = ClickM {unClickM :: InternalEnv -> IO a} + deriving (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) + via ReaderT InternalEnv IO + +instance MonadState InternalState ClickM where + state f = ClickM \e -> + atomicModifyIORef' e.hte_state (swap . f) + {-# INLINE state #-} + get = ClickM \e -> readIORef e.hte_state + {-# INLINE get #-} + put s = ClickM \e -> writeIORef e.hte_state s + {-# INLINE put #-} + +data InternalEnv = InternalEnv + { hte_send :: Builder -> IO () + , hte_flush :: IO ValueExpr + , hte_state :: IORef InternalState + , hte_scope :: ScopeId + , hte_prompt_tag :: PromptTag () + } + +data InternalState = InternalState + { subscriptions :: [Subscription Any] + , finalizers :: [Finalizer] + , transaction_queue :: Map EventId (ClickM ()) + , next_id :: Word32 + } + +data Expr where + Null :: Expr + Bool :: Word8 -> Expr + I8 :: Int8 -> Expr + I16 :: Int16 -> Expr + I32 :: Int32 -> Expr + I64 :: Int64 -> Expr + U8 :: Word8 -> Expr + U16 :: Word16 -> Expr + U32 :: Word32 -> Expr + U64 :: Word64 -> Expr + F32 :: Float32 -> Expr + F64 :: Float64 -> Expr + Str :: Text -> Expr + Arr :: [Expr] -> Expr + Obj :: [(Text, Expr)] -> Expr -- ^ JavaScript object + U8Arr :: ByteString -> Expr + + Dot :: Expr -> Text -> Expr + SetProp :: Expr -> Text -> Expr -> Expr + Ix :: Expr -> Word32 -> Expr + Id :: Text -> Expr + + Lam :: Expr -> Expr + Arg :: Word8 -> Expr + Apply :: Expr -> Expr -> Expr + Call :: Expr -> Text -> Expr -> Expr + + AssignRef :: RefId -> Expr -> Expr + FreeRef :: RefId -> Expr + Ref :: RefId -> Expr + FreeScope :: ScopeId -> Expr + + PeekStack :: Word8 -> Expr + PushStack :: Expr -> Expr + PopStack :: Expr + + PopIns :: Expr + ElementProp :: Expr -> Text -> Expr -> Expr + ElementAttr :: Expr -> Text -> Text -> Expr + ClassListAdd :: [Text] -> Expr + ClassListRemove :: [Text] -> Expr + InsertBrackets :: Expr + ClearBrackets :: Expr -> Expr + DropBrackets :: Expr -> Expr + + CreateElement :: Text -> Expr + CreateElementNS :: Text -> Text -> Expr + CreateTextNode :: Text -> Expr + UpdateTextNode :: Expr -> Text -> Expr + + Eval :: UnsafeJavaScript -> Expr + TriggerEvent :: EventId -> Expr -> Expr + YieldResult :: Word32 -> Expr + + deriving stock Generic + deriving anyclass Binary + +data ClientMsg where + StartMsg :: StartFlags -> ClientMsg + EventMsg :: EventId -> Expr -> ClientMsg + ResumeMsg :: Word32 -> Expr -> ClientMsg + deriving stock Generic + deriving anyclass Binary + +newtype StartFlags = StartFlags {unStartFlags :: Expr} + deriving newtype Binary + +newtype ScopeId = ScopeId {unScopeId :: Word32} + deriving newtype (Binary, Eq) + +data RefId = RefId ScopeId Word32 + deriving stock (Generic) + deriving anyclass (Binary) + +newtype EventId = EventId {unEventId :: Word32} + deriving newtype (Show, Ord, Eq) + deriving newtype (Binary) + +newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} + deriving newtype (IsString, Show, Semigroup, Monoid, Binary) + +newtype Event a = Event {unEvent :: EventId} + deriving newtype (Show, Ord, Eq, Binary) + +unsafeFromEventId :: EventId -> Event a +unsafeFromEventId = Event + +unsafeToEventId :: Event a -> EventId +unsafeToEventId = unEvent + +data DynVar a where + SourceVar :: Event a -> IORef a -> DynVar a + OverrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a + LensMap :: Lens' s a -> DynVar s -> DynVar a + +type UpdateFn s = forall a. (s -> (s, a)) -> ClickM a + +type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s + +data DynVal a where + ConstVal :: a -> DynVal a + FromVar :: DynVar a -> DynVal a + MapVal :: DynVal a -> (a -> b) -> DynVal b + SplatVal :: DynVal (a -> b) -> DynVal a -> DynVal b + OverrideSub :: (forall b. SubscribeFn a b -> SubscribeFn a b) -> DynVal a -> DynVal a + +type SubscribeFn a b = (a -> b -> ClickM b) -> ClickM () + +instance Functor DynVal where + fmap = flip MapVal + {-# INLINE fmap #-} +instance Applicative DynVal where + pure = ConstVal + {-# INLINE pure #-} + (<*>) = SplatVal + {-# INLINE (<*>) #-} + +fromVar :: DynVar a -> DynVal a +fromVar = FromVar +{-# INLINE fromVar #-} + +data Subscription a + = SubscriptionSimple + { ss_scope :: ScopeId + , ss_event_id :: Event a + , ss_callback :: a -> ClickM () + } + | forall b. SubscriptionAccum + { sa_resource_scope :: ScopeId + , sa_event_id :: Event a + , sa_callback :: a -> b -> ClickM b + , sa_accum_ref :: IORef b + } + +data Finalizer + = CustomFinalizer + { cf_resource_scope :: ScopeId + , cf_callback :: ClickM () + } + | ScopeFinalizer + { sf_resource_scope :: ScopeId + , sf_linked_scope :: ScopeId + } + +finalizerScope :: Finalizer -> ScopeId +finalizerScope CustomFinalizer{cf_resource_scope} = cf_resource_scope +finalizerScope ScopeFinalizer{sf_resource_scope} = sf_resource_scope + +subscriptionScope :: Subscription a -> ScopeId +subscriptionScope SubscriptionSimple{ss_scope} = ss_scope +subscriptionScope SubscriptionAccum{sa_resource_scope} = sa_resource_scope + +-- | JavaScript value, result of evaluating an 'Expr'. Should only +-- contain constructors up to and including 'U8Arr'. I chose to use +-- type alias rather than a new data type for easier conversion. +type ValueExpr = Expr + +class ToValue a where + toValue :: a -> ValueExpr + default toValue :: (Generic a, GToValue (Rep a)) => a -> ValueExpr + toValue = gToValue . G.from + +instance (Generic a, GToValue (Rep a)) => ToValue (Generically a) where + toValue = gToValue . G.from . (\(Generically x) -> x) + +instance ToValue ValueExpr where toValue = Prelude.id + +instance ToValue Bool where toValue = Bool . bool 0 1 + +instance ToValue Int8 where toValue = I8 +instance ToValue Int16 where toValue = I16 +instance ToValue Int32 where toValue = I32 +instance ToValue Int64 where toValue = I64 + +instance ToValue Word8 where toValue = U8 +instance ToValue Word16 where toValue = U16 +instance ToValue Word32 where toValue = U32 +instance ToValue Word64 where toValue = U64 + +instance ToValue Float where toValue = F32 . Float32 +instance ToValue Double where toValue = F64 . Float64 + +instance ToValue Int where toValue = I64 . fromIntegral +instance ToValue Word where toValue = U64 . fromIntegral + +instance ToValue Char where + toValue c = Str $ Text.cons c Text.empty + +instance ToValue Text where toValue = Str + +instance ToValue ByteString where toValue = U8Arr + +instance ToValue () where toValue _ = Null + +instance ToValue a => ToValue [a] where toValue = Arr . fmap toValue + +instance ToValue a => ToValue (Maybe a) where toValue = maybe Null toValue + +instance (ToValue a, ToValue b) => ToValue (a, b) where + toValue (a, b) = toValue [toValue a, toValue b] + +instance (ToValue a, ToValue b, ToValue c) => ToValue (a, b, c) where + toValue (a, b, c) = toValue [toValue a, toValue b, toValue c] +-------------------------------------------------------------------------------- + +class FromValue a where + fromValue :: ValueExpr -> Maybe a + default fromValue :: (Generic a, GFromValue (Rep a)) => ValueExpr -> Maybe a + fromValue = fmap G.to . gFromValue + +instance (Generic a, GFromValue (Rep a)) => FromValue (Generically a) where + fromValue = fmap (Generically . G.to) . gFromValue + +instance FromValue ValueExpr where fromValue = pure + +instance FromValue Bool where + fromValue (Bool 0) = Just False + fromValue (Bool _) = Just True + fromValue _ = Nothing + +instance FromValue Int8 where + fromValue (I8 j) = Just j + fromValue _ = Nothing + +instance FromValue Int16 where + fromValue (I16 j) = Just j + fromValue _ = Nothing + +instance FromValue Int32 where + fromValue = \case + I32 j -> Just j + F64 j -> Just $ floor j.unFloat64 + _ -> Nothing + +instance FromValue Int64 where + fromValue (I64 j) = Just j + fromValue _ = Nothing + +instance FromValue Word8 where + fromValue (U8 j) = Just j + fromValue _ = Nothing + +instance FromValue Word16 where + fromValue (U16 j) = Just j + fromValue _ = Nothing + +instance FromValue Word32 where + fromValue (U32 j) = Just j + fromValue _ = Nothing + +instance FromValue Word64 where + fromValue (U64 j) = Just j + fromValue _ = Nothing + +instance FromValue Float where + fromValue (F32 j) = Just j.unFloat32 + fromValue _ = Nothing + +instance FromValue Double where + fromValue = \case + I32 j -> Just $ fromIntegral j + F64 (Float64 j) -> Just j + _ -> Nothing + +instance FromValue Int where + fromValue (I8 j) = Just $ fromIntegral j + fromValue (I16 j) = Just $ fromIntegral j + fromValue (I32 j) = Just $ fromIntegral j + fromValue (I64 j) = Just $ fromIntegral j + fromValue (U8 j) = Just $ fromIntegral j + fromValue (U16 j) = Just $ fromIntegral j + fromValue (U32 j) = Just $ fromIntegral j + fromValue (U64 j) = Just $ fromIntegral j + fromValue _ = Nothing + +instance FromValue Word where + fromValue (I8 j) = Just $ fromIntegral j + fromValue (I16 j) = Just $ fromIntegral j + fromValue (I32 j) = Just $ fromIntegral j + fromValue (I64 j) = Just $ fromIntegral j + fromValue (U8 j) = Just $ fromIntegral j + fromValue (U16 j) = Just $ fromIntegral j + fromValue (U32 j) = Just $ fromIntegral j + fromValue (U64 j) = Just $ fromIntegral j + fromValue _ = Nothing + +instance FromValue Char where + fromValue = \case + Str a | Just (c, _) <- Text.uncons a -> Just c + | otherwise -> Nothing + _ -> Nothing + +instance FromValue Text where + fromValue = \case Str a -> Just a; _ -> Nothing + +instance FromValue ByteString where + fromValue = \case U8Arr a -> Just a; _ -> Nothing + +instance FromValue () where + fromValue = \case Null -> Just (); _ -> Nothing + +instance FromValue a => FromValue [a] where + fromValue = \case + Arr xs -> Just (mapMaybe fromValue xs) + _ -> Nothing + +instance FromValue a => FromValue (Maybe a) where + fromValue = fmap Just . fromValue @a + +instance (FromValue a, FromValue b) => FromValue (a, b) where + fromValue j = fromValue j >>= \case + Just (a:b:_) -> (,) <$> fromValue a <*> fromValue b + _ -> Nothing + +instance (FromValue a, FromValue b, FromValue c) => FromValue (a, b, c) where + fromValue j = fromValue j >>= \case + Just (a:b:c:_) -> (,,) <$> fromValue a <*> fromValue b <*> fromValue c + _ -> Nothing +-------------------------------------------------------------------------------- + +class GFromValue (f :: Type -> Type) where + gFromValue :: ValueExpr -> Maybe (f a) + +instance GFromValue f => GFromValue (M1 m c f) where + gFromValue = fmap M1 . gFromValue @f + +instance GFromValue U1 where + gFromValue _ = Just U1 + +instance GFromJSObject (x :*: y) => GFromValue (x :*: y) where + gFromValue (Obj kvs) = gFromJSObject kvs + gFromValue _ = Nothing + +instance {-# OVERLAPPING #-} FromValue a => GFromValue (S1 s (Rec0 a)) where + gFromValue = fmap (M1 . K1) . fromValue @a +-------------------------------------------------------------------------------- + +class GToValue (f :: Type -> Type) where + gToValue :: f x -> ValueExpr + +instance GToValue f => GToValue (M1 m c f) where + gToValue (M1 f) = gToValue f + +instance GToValue U1 where + gToValue _ = Null + +instance GToJSObject (x :*: y) => GToValue (x :*: y) where + gToValue (x :*: y) = Obj $ gToJSObject (x :*: y) + +instance {-# OVERLAPPING #-} (ToValue a) => GToValue (S1 s (Rec0 a)) where + gToValue (M1 (K1 a)) = toValue a +-------------------------------------------------------------------------------- + +class GToJSObject (f :: Type -> Type) where + gToJSObject :: f x -> [(Text, ValueExpr)] + +instance (GToJSObject x, GToJSObject y) => GToJSObject (x :*: y) where + gToJSObject (x :*: y) = gToJSObject x <> gToJSObject y + +instance (GToJSObject f) => GToJSObject (M1 m c f) where + gToJSObject (M1 a) = gToJSObject a + +instance {-# OVERLAPPING #-} (ToValue a, Selector s) => GToJSObject (S1 s (Rec0 a)) where + gToJSObject (M1 (K1 a)) = [(key, toValue a)] + where + key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) +-------------------------------------------------------------------------------- + +class GFromJSObject (f :: Type -> Type) where + gFromJSObject :: [(Text, ValueExpr)] -> Maybe (f x) + +instance (GFromJSObject x, GFromJSObject y) => GFromJSObject (x :*: y) where + gFromJSObject kvs = liftA2 (:*:) (gFromJSObject kvs) (gFromJSObject kvs) + +instance (GFromJSObject f) => GFromJSObject (M1 m c f) where + gFromJSObject = fmap M1 . gFromJSObject + +instance {-# OVERLAPPING #-} (FromValue a, Selector s) => GFromJSObject (S1 s (Rec0 a)) where + gFromJSObject kvs = List.lookup key kvs >>= fmap (M1 . K1) . fromValue + where + key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) +-------------------------------------------------------------------------------- + +{-| Boxed versions of [Delimited +Continuation](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0313-delimited-continuation-primops.rst) +primops. If you are not familiar with the concept, I highly recommend +watching [Delimited Continuations, Demystified by Alexis +King](https://www.youtube.com/watch?v=TE48LsgVlIU). + +TODO: Remove these once they are included in 'base' -} + +prompt :: PromptTag a -> IO a -> IO a +prompt (PromptTag t) (IO m) = IO (prompt# t m) + +control :: forall a b. PromptTag a -> ((IO b -> IO a) -> IO a) -> IO b +control (PromptTag t) f = IO (control0# t g) + where + g :: ((State# RealWorld -> (# State# RealWorld, b #)) + -> State# RealWorld -> (# State# RealWorld, a #)) + -> State# RealWorld -> (# State# RealWorld, a #) + g h = let IO m = f (k h) in m + k :: ((State# RealWorld -> (# State# RealWorld, b #)) + -> State# RealWorld -> (# State# RealWorld, a #)) + -> IO b -> IO a + k l (IO n) = IO (l n) + +data PromptTag a = PromptTag {unPromptTag :: PromptTag# a} + +data SomeTag = forall a. SomeTag (PromptTag a) + +newPromptTag :: forall a. IO (PromptTag a) +newPromptTag = IO \s -> + let !(# s', t #) = newPromptTag# @a s in (# s', PromptTag t #) diff --git a/Clickable/Wasm.hs b/Clickable/Wasm.hs new file mode 100644 index 0000000..6ba50d6 --- /dev/null +++ b/Clickable/Wasm.hs @@ -0,0 +1,71 @@ +{-# LANGUAGE StrictData #-} +{-# LANGUAGE CPP #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE RecursiveDo #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnboxedTuples #-} +{-# OPTIONS_GHC -Wno-unused-do-bind #-} +module Clickable.Wasm where + +import Clickable.Internal +import Clickable.Types +import Control.Monad +import Data.Binary (Binary) +import Data.ByteString (ByteString) +import Data.IORef +import Data.Word +import Foreign.Ptr +import System.IO.Unsafe (unsafePerformIO) +import qualified Data.Binary as Binary +import qualified Data.ByteString.Lazy as BSL +import qualified Data.ByteString.Unsafe as BSU +import qualified Data.Map as Map +import Data.Tuple (swap) +import Data.Map (Map) +import Foreign.C.String (CStringLen) + +foreign import ccall safe + "clickable_eval_buffer" clickable_eval_buffer :: Ptr Word8 -> Int -> IO () + +env :: InternalEnv +{-# NOINLINE env #-} + +continuations :: IORef (Map Word32 (IO Value -> IO ())) +{-# NOINLINE continuations #-} + +buf :: CStringLen +{-# NOINLINE buf #-} + +(env, continuations, buf) = unsafePerformIO $ + newInternalEnv (100 * 1024) \(ptr, len) -> + clickable_eval_buffer (castPtr ptr) len + +mkWasmApp :: ClickM () -> Ptr Word8 -> IO (Ptr Word8) +mkWasmApp app p | p == nullPtr = do + runTransition env app + return $ castPtr $ fst buf +mkWasmApp app inmsg = do + msg <- loadMessage inmsg $ snd buf + case msg of + Just (StartMsg _flags) -> + runTransition env app + Just (EventMsg eventId pload) -> + runTransition env $ + triggerEvent (unsafeFromEventId eventId) pload + Just (ResumeMsg contId pload) -> do + awatingThread <- atomicModifyIORef' continuations $ + swap . Map.alterF (,Nothing) contId + forM_ awatingThread \cont -> cont $ pure $ exprToValue pload + _ -> error "mkWasmApp: Failed to parse incomming command" + return $ castPtr $ fst buf + +loadMessage :: Binary msg => Ptr a -> Int -> IO (Maybe msg) +loadMessage p len + | nullPtr /= p = fmap (Just . Binary.decode . BSL.fromStrict) loadByteString + | otherwise = return Nothing + where + loadByteString :: IO ByteString + loadByteString = BSU.unsafePackCStringLen (castPtr p, len) diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs new file mode 100644 index 0000000..4795673 --- /dev/null +++ b/Clickable/WebSocket.hs @@ -0,0 +1,169 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE RecursiveDo #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DerivingStrategies #-} +module Clickable.WebSocket where + +import Clickable.Internal +import Clickable.Types +import Control.Concurrent +import Control.Concurrent.Async (race) +import Control.Exception (bracket, try) +import Control.Monad +import Control.Monad.State.Strict (modify) +import Data.Binary.Builder ( Builder ) +import Data.ByteString (ByteString) +import Data.ByteString.Base64.Lazy qualified as B64 +import Data.ByteString.Unsafe (unsafePackCStringLen) +import Data.Data +import Data.IORef +import Data.Map (Map) +import Data.Tuple +import Foreign.Ptr +import GHC.Generics +import Network.HTTP.Types +import Network.Wai +import Network.Wai.Handler.WebSockets +import Network.WebSockets +import qualified Data.Binary as Binary +import qualified Data.ByteString.Builder as Builder +import qualified Data.ByteString.Lazy as BSL +import qualified Data.Map as Map +import Data.Word + +index :: Builder -> Builder +index content = + "\n\ + \\n\ + \ \n\ + \ \n\ + \ \n\ + \ \n\ + \ \n\ + \" + where + b64 = B64.encode $ Builder.toLazyByteString content + +jsrts :: Builder +jsrts = + "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{AZ:()=>evalRange,JC:()=>ClientMsgTag,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalRange(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeValue(e,t),encodeValue(e,n)}))}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!0),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.InsPop=31]=\"InsPop\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DropBrackets=38]=\"DropBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateTextNode=41]=\"CreateTextNode\",e[e.UpdateTextNode=42]=\"UpdateTextNode\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.YieldResult=45]=\"YieldResult\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null){const n=new WebSocket(e),r={refs:new Map,stack:null};function s(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.EventMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))}function i(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.ResumeMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))}n.onopen=e=>{const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.StartMsg,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))},n.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.AZ({triggerEvent:s,resumeCont:i,persistent:r,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(3e4,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=Iovec.read_bytes_array(l,t,n);let o=0;for(const t of _){const{ret:n,data:_}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return l.setUint32(i,o,!0),n;if(a.set(_,t.buf),o+=_.length,r+=BigInt(_.length),_.length!=t.buf_len)break}return l.setUint32(i,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const l=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(l.slice(0,n),t),l.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=Ciovec.read_bytes_array(l,t,n);let o=0;for(const t of _){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:_,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(_!=ERRNO_SUCCESS)return l.setUint32(i,o,!0),_;if(o+=f,r+=BigInt(f),f!=n.byteLength)break}return l.setUint32(i,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const a=Iovec.read_bytes_array(i,t,n);let _=0;for(const t of a){const{ret:n,data:a}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,_,!0),n;if(l.set(a,t.buf),_+=a.length,a.length!=t.buf_len)break}return i.setUint32(r,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let _=0;for(;;){const{ret:o,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=o)return l.setUint32(i,_,!0),o;if(null==f)break;if(n-_null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const a=Ciovec.read_bytes_array(i,t,n);let _=0;for(const t of a){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:a,nwritten:o}=s.fds[e].fd_write(n);if(a!=ERRNO_SUCCESS)return i.setUint32(r,_,!0),a;if(_+=o,o!=n.byteLength)break}return i.setUint32(r,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(a.slice(n,n+r)),{ret:o,filestat:f}=s.fds[e].path_filestat_get(t,_);return null!=f&&f.write_bytes(l,i),o}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,l,a){const _=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(_.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,o,i,l,a)}return ERRNO_BADF},path_link(e,t,n,r,i,l,a){const _=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const o=new TextDecoder(\"utf-8\").decode(_.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(_.slice(l,l+a)),{ret:u,inode_obj:E}=s.fds[e].path_lookup(o,t);return null==E?u:s.fds[i].path_link(f,E,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,l,a,_,o){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const E=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(E);const{ret:c,fd_obj:R}=s.fds[e].path_open(t,E,i,l,a,_);if(0!=c)return c;s.fds.push(R);const d=s.fds.length-1;return f.setUint32(o,d,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,l){const a=new DataView(s.inst.exports.memory.buffer),_=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(_.slice(t,t+n));debug.log(o);const{ret:f,data:u}=s.fds[e].path_readlink(o);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return a.setUint32(l,0,!0),ERRNO_BADF;_.set(e,r),a.setUint32(l,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,l){const a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const _=new TextDecoder(\"utf-8\").decode(a.slice(t,t+n)),o=new TextDecoder(\"utf-8\").decode(a.slice(i,i+l));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(_);if(null==u)return f;if(f=s.fds[r].path_link(o,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(_,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const l=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(l.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(l.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:l,path:a}=Path.from(t);if(null==a)return{ret:l,fd_obj:null};let{ret:_,entry:o}=this.dir.get_entry_for_path(a);if(null==o){if(_!=ERRNO_NOENT)return{ret:_,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};o=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&o.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:o.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:l,filename:a,entry:_}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==l||null==a)return i;if(null!=_){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=_.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&_ instanceof Directory))return ERRNO_EXIST;if(0!=_.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||_.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(l.contents.set(a,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==l?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:l})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==l?r:l.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==l?r:l instanceof Directory&&l.stat().filetype===FILETYPE_DIRECTORY?0!==l.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:l,filename:a,entry:_}=this.get_parent_dir_and_entry_for_path(r,!0);return null==l||null==a?{ret:i,entry:null}:null!=_?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),l.contents.set(a,s),_=s,{ret:ERRNO_SUCCESS,entry:_})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null){const n=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]),r={refs:new Map,stack:null};function s(e,t){const n=new DataView(inst.exports.memory.buffer),s={triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)},resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},persistent:r,mem:n,isMutableMem:!0,begin:e,end:e+t};proto.AZ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:n.wasiImport,env:{clickable_eval_buffer:s}}))).then((e=>{inst=e,n.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}window.clickable={runWebsocket,runWasm}})();" + +runApp :: ClickM () -> Application +runApp app req respond = do + let path = pathInfo req + html200 = respond . responseBuilder status200 [("Content-Type", "text/html")] + text200 = respond . responseBuilder status200 [("Content-Type", "text/plain")] + wsi <- newWebSocketInstance () (const app) fallbackApp + case path of + [] -> + html200 $ index mempty + ["about"] -> text200 ("About Page") + ["dev.sock"] -> websocketsOr defaultConnectionOptions (websocketApp wsi) + fallbackApp req respond + _ -> text200 ("404 Not Found") + +fallbackApp :: Application +fallbackApp _ respond = respond $ responseLBS status404 + [(hContentType, "text/html; charset=utf-8")] + "

Not found

\n" + +data WebSocketInstance = forall a. Typeable a => WebSocketInstance + { conn_state_ref :: IORef (Map ConnectionId WebSocketConn) + , resource :: a + , client_app :: WebSocketConn -> StartFlags -> ClickM () + , server_app :: Application + , connection_lost :: WebSocketConn -> IO () + } + +newWebSocketInstance :: Typeable a => + a -> (StartFlags -> ClickM ()) -> Application -> IO WebSocketInstance +newWebSocketInstance resource clientApp serverApp = do + conn_state_ref <- newIORef Map.empty + return WebSocketInstance + { conn_state_ref + , resource + , client_app = const clientApp + , server_app = serverApp + , connection_lost = \_ -> pure () + } + +data WebSocketConn = WebSocketConn + { connection :: Connection + , continuations :: IORef (Map Word32 (IO ValueExpr -> IO ())) + , internal_env :: InternalEnv + , command_chan :: Chan (ClickM ()) + -- ^ Writing to the Chan sends a command to the browser to execute + , connection_id :: ConnectionId + } deriving Generic + +newtype ConnectionId = ConnectionId {unConnectionId :: Int} + deriving newtype (Ord, Show, Eq, Num, Enum) + +websocketApp :: WebSocketInstance -> ServerApp +websocketApp self p = + bracket acceptConn dropConn \connInfo -> + withPingThread connInfo.connection 30 (pure ()) $ loop connInfo + where + acceptConn = mdo + conn <- acceptRequest p + newConn conn + dropConn (conn::WebSocketConn) = do + modifyIORef' (conn_state_ref self) $ Map.delete conn.connection_id + self.connection_lost conn + loop (conn::WebSocketConn) = do + raceResult <- race + (try @ConnectionException (receiveData conn.connection)) + (readChan conn.command_chan) + case raceResult of + Left (Right (incomingBytes::ByteString)) -> do + let jsMessage = Binary.decode . BSL.fromStrict $ incomingBytes + reader conn $ Right jsMessage + loop conn + Left (Left (_::ConnectionException)) -> + return () + Right jsAction -> do + reader conn $ Left jsAction + loop conn + + reader :: WebSocketConn -> Either (ClickM ()) ClientMsg -> IO () + reader conn (Right (StartMsg flags)) = + void $ runTransition conn.internal_env + $ self.client_app conn flags + reader conn (Right (ResumeMsg contId pload)) = + prompt conn.internal_env.hte_prompt_tag do + awatingThread <- atomicModifyIORef' conn.continuations $ + swap . Map.alterF (,Nothing) contId + forM_ awatingThread \cont -> cont $ pure pload + reader conn (Right (EventMsg eid arg)) = + void $ runTransition conn.internal_env + $ modify (triggerEventOp (unsafeFromEventId eid) arg) + -- BrowserMessage BeforeUnload -> + -- return () + reader conn (Left a) = + void $ runTransition conn.internal_env a + + newConn connection = mdo + command_chan <- newChan + (internal_env, continuations, _) <- newInternalEnv (100 * 1024) \(ptr, len) -> do + bs <- unsafePackCStringLen (castPtr ptr, len) + sendDataMessage connection $ Network.WebSockets.Binary $ BSL.fromStrict bs + atomicModifyIORef' self.conn_state_ref \m -> + let conn = WebSocketConn + { internal_env + , connection + , command_chan + , connection_id = maybe 0 (succ . fst) $ Map.lookupMax m + , continuations + } + in (Map.insert conn.connection_id conn m, conn) diff --git a/LICENSE b/LICENSE index 3e80ac2..3abad44 100644 --- a/LICENSE +++ b/LICENSE @@ -1,28 +1,20 @@ -Copyright 2024 Vladislav Lagunov +Copyright (c) 2024 Vladislav Lagunov -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. -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. - -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. - -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. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index da6317a..0000000 --- a/README.md +++ /dev/null @@ -1,202 +0,0 @@ - -Lightweight frontend library for GHC with JavaScript backend with -focus on minimalism and simplicity - -## Getting started - -To follow the instructions, you would need to have [nix](https://nixos.org/download.html) -installed in your system. Alternatively, -you can choose to install manually [GHC with JavaScript -Backend](https://engineering.iog.io/2023-01-24-javascript-browser-tutorial/), -and `cabal` (comes with every [GHC](https://www.haskell.org/ghc/) installation) - -How to build library and the examples: -```sh -# Clone the repository -git clone https://github.com/lagunoff/htmlt.git -cd htmlt -# Enter the nix-shell -nix-shell -# Build examples with cabal -cabal --with-ghc=javascript-unknown-ghcjs-ghc --with-ghc-pkg=javascript-unknown-ghcjs-ghc-pkg build -f examples -``` -Once `cabal build` is successful, you can find js executables in -`./dist-newstyle/build/javascript-ghcjs/ghc-9.7.20230527/htmlt-0.1.0.0/x` and run them by opening `index.html` in browser - -### Minimal example - -```haskell --- Example featuring element and two buttons. The input value --- is synchronized with 'DynRef's state and can be modified by either entering a --- number into the input or by clicking one of the two buttons -app :: Html () -app = do - -- First create a 'DynRef - counterRef <- newRef @Int 0 - div_ do - input_ [type_ "number"] do - -- Show the value inside - dynProp "value" $ JSS.pack . show <$> fromRef counterRef - -- Parse and update the value on each InputEvent - on "input" $ decodeEvent intDecoder $ writeRef counterRef - br_ - -- Decrease the value on each click - button_ do - on_ "click" $ modifyRef counterRef pred - text "-" - -- Increase the value on each click - button_ do - on_ "click" $ modifyRef counterRef succ - text "+" - where - intDecoder = - valueDecoder >=> MaybeT . pure . readMaybe . JSS.unpack - -main :: IO () -main = - void $ attachToBody app - -``` -[Open the demo](https://lagunoff.github.io/htmlt/js-backend/htmlt-counter.jsexe/) - -## Quick API summary -
- Expand to see simplified definitions - -```hs --- Constructing DOM -el :: JSString -> Html a -> Html a -elns :: JSString -> JSString -> Html a -> Html a -text :: JSString -> Html () -dynText :: Dynamic JSString -> Html () - --- Applying attributes and properties -prop :: JSString -> v -> Html () -dynProp :: JSString -> Dynamic v -> Html () -attr :: JSString -> JSString -> Html () -dynAttr :: JSString -> JSString -> Html () -toggleClass :: JSString -> Dynamic Bool -> Html () -toggleAttr :: JSString -> Dynamic Bool -> Html () -dynStyle :: JSString -> Dynamic JSString -> Html () -dynStyles :: Dynamic JSString -> Html () -dynValue :: Dynamic JSString -> Html () -dynClass :: Dynamic JSString -> Html () -dynChecked :: Dynamic Bool -> Html () -dynDisabled :: Dynamic Bool -> Html () - --- Handling DOM events -on :: EventName -> (DOMEvent -> Step ()) -> Html () -on_ :: EventName -> Step () -> Html () -onOptions :: EventName -> ListenerOpts -> (DOMEvent -> Step ()) -> Html () -onGlobalEvent :: ListenerOpts -> DOMNode -> EventName -> (DOMEvent -> Step ()) -> Html () - --- Decoding data from DOM Events -mouseDeltaDecoder :: JSVal -> MaybeT m MouseDelta -clientXYDecoder :: JSVal -> MaybeT m (Point Int) -offsetXYDecoder :: JSVal -> MaybeT m (Point Int) -pageXYDecoder :: JSVal -> MaybeT m (Point Int) -keyModifiersDecoder :: JSVal -> MaybeT m KeyModifiers -keyCodeDecoder :: JSVal -> MaybeT m Int -keyboardEventDecoder :: JSVal -> MaybeT m KeyboardEvent -valueDecoder :: JSVal -> MaybeT m JSString -checkedDecoder :: JSVal -> MaybeT m Bool - --- DOM extras, useful helpers -unsafeHtml :: MonadIO m => JSString -> HtmlT m () -portal :: Monad m => DOMElement -> HtmlT m a -> HtmlT m a -installFinalizer :: MonadReactive m => IO () -> m () - --- Dynamic collections -simpleList :: Dynamic [a] -> (Int -> DynRef a -> Html ()) -> Html () - --- Arbitrary dynamic content -dyn :: Dynamic (Html ()) -> Html () - --- Contructing Events -newEvent :: MonadReactive m => m (Event a, Trigger a) -fmap :: (a -> b) -> Event a -> Event a -never :: Event a -updates :: Dynamic a -> Event a - --- Constructing Dynamics -constDyn :: a -> Dynamic a -fromRef :: DynRef a -> Dynamic a -fmap :: (a -> b) -> Dynamic a -> Dynamic b -(<*>) :: Dynamic (a -> b) -> Dynamic a -> Dynamic b -mapDyn :: MonadReactive m => Dynamic a -> (a -> b)-> m (Dynamic b) -mapDyn2 :: MonadReactive m => Dynamic a -> Dynamic b -> (a -> b -> c) -> m (Dynamic c) -mapDyn3 :: MonadReactive m => Dynamic a -> Dynamic b -> Dynamic c -> (a -> b -> c -> d) -> m (Dynamic d) -holdUniqDyn :: Eq a => Dynamic a -> Dynamic a -holdUniqDynBy :: (a -> a -> Bool) -> Dynamic a -> Dynamic a - --- Constructing DynRefs -newRef :: MonadReactive m => a -> m (DynRef a) -lensMap :: Lens' s a -> DynRef s -> DynRef a - --- Read and write DynRefs, Dynamics -readDyn :: MonadIO m => Dynamic a -> m a -readRef :: MonadIO m => DynRef a -> m a -writeRef :: DynRef a -> a -> Step () -modifyRef :: DynRef a -> (a -> a) -> Step () -atomicModifyRef :: DynRef a -> (a -> (a, r)) -> Step r - --- Starting and shutting down the application -atatchOptions :: StartOpts -> Html a -> IO (a, RunningApp) -attachTo :: DOMElement -> Html a -> IO (a, RunningApp) -attachToBody :: Html a -> IO (a, RunningApp) -detach :: RunningApp -> IO () -``` - -
- -## Other examples - - - - - - - - - - - - - - - - - - - - - - -
Counter5.6M all.js, 3.7M all.min.jssource - open | - open minified -
TodoMVC3.1M all.js, 773K all.min.jssource - open | - open minified -
Simple Routing11M all.js, 7.6M all.min.jssource - open | - open minified -
- - -For comparison, here are the sizes of all.js files build with GHCJS 8.6 -— 1.5M -[htmlt-counter](https://lagunoff.github.io/htmlt-counter/), -1.4M -[htmlt-todomvc](https://lagunoff.github.io/htmlt-todomvc/), -3.3M -[htmlt-simple-routing](https://lagunoff.github.io/htmlt-simple-routing/) - -## Todos - - [x] Migrate to GHC with JavaScript backend - - [ ] More examples and documentation - - [ ] Similar library for ReactNative - -## Legacy GHCJS version -The legacy version for GHCJS 8.6 and GHCJS 8.10 can still be found in -the [ghcjs](https://github.com/lagunoff/htmlt/tree/ghcjs) branch diff --git a/bin/README.md b/bin/README.md new file mode 100644 index 0000000..4271789 --- /dev/null +++ b/bin/README.md @@ -0,0 +1,57 @@ +# nix-bins: A Low-Effort, Portable Solution for Caching Nix-Shell Environments + +## Overview + +`nix-bins` is a lightweight, portable script designed to reduce the +startup delay of `nix-shell` by caching environment setups. It +generates command wrappers that allow for immediate execution, +bypassing the usual evaluation of the Nix expressions. + +## Purpose + +Nix provides reproducible environments with `nix-shell`, but entering +the development environment requires extra step, incures a painful +delay before running CLI tools and doesn't do well with other tools +like text editors or IDEs. `nix-bins` solves these issues by creating +executable wrappers for each command in the environment, enabling +near-instant access. + +## Setup and Usage + +1. **Copy the `nix-bins` Script**: Place `nix-bins` in your project's + `bin` directory. +2. **Generate Wrappers**: Execute: + +```bash +nix-shell --pure --run bin/nix-bins +``` +This command creates wrappers in ${project}/bin/${command}. +``` +tree bin +bin/ +├── nix-bins +├── ghci +├── ghc +├── ... +``` +3. **Update Wrappers**: Whenever you change your '*.nix' files repeat + the command from step 2 to keep the wrappers in sync. +4. **Update .gitignore**: Most likely you wouldn't want to see a bunch + of 'bin/${command}' wrappers in version control, exclude them from + git with following '.gitignore' config: +``` +bin/** +!bin/nix-bins +!bin/README.md +``` + +## Advantages + +- **Instant Command Execution**: Commands such as `bin/ghci` or + `bin/ghc` execute instantaneously +- **Smoother development experience**: Just use `bin/you_command` + without entering a new shell or relying on tools like `direnv` +- **Easier Integration**: Dev tools like Emacs require a command path, + but don't know how to enter 'nix-shell' +- **No Need to Escape Arguments**: For example, you can run +`bin/ghc -e "2 + 2"` instead of `nix-shell--run "ghc -e \"2 + 2\""` diff --git a/bin/nix-bins b/bin/nix-bins new file mode 100755 index 0000000..89e42f8 --- /dev/null +++ b/bin/nix-bins @@ -0,0 +1,55 @@ +#!/usr/bin/env sh + +usage() { + echo "Usage: nix-shell --pure --run 'bin/nix-bins'" +} + +# Check for command-line arguments +for arg in "$@"; do + case $arg in + --help) + usage + exit 0 + ;; + esac +done + +SCRIPT_DIR=$(dirname "$(realpath "$0")") + +# Step 1: Clear the ./bin/ directory except nix-shell-cache.sh and nix-bins +find "${SCRIPT_DIR}" -type f \ + ! -name 'nix-shell-cache.sh' \ + ! -name 'nix-bins' \ + ! -name 'README.md' -exec rm -f {} + + +# Step 2: Parse $PATH variable and acquire all executable commands +IFS=':' read -r -a path_array <<< "$PATH" +commands=() + +for dir in "${path_array[@]}"; do + if [ -d "$dir" ]; then + for cmd in "$dir"/*; do + if [ -x "$cmd" ] && [ ! -d "$cmd" ]; then + commands+=("$(basename "$cmd")") + fi + done + fi +done + +# Step 3: Create executable script for each command +for command in "${commands[@]}"; do + script_path="${SCRIPT_DIR}/${command}" + cat << EOF > "$script_path" +#!/usr/bin/env sh + +SCRIPT_DIR=\$(dirname "\$(realpath "\$0")") + +source "\${SCRIPT_DIR}/nix-shell-cache.sh" + +${command} "\$@" +EOF + chmod +x "$script_path" +done + +# Step 4: Save the enviroment into ./bin/nix-shell-cache.sh +export > "${SCRIPT_DIR}/nix-shell-cache.sh" diff --git a/cabal.project b/cabal.project index 4b3729b..8834d04 100644 --- a/cabal.project +++ b/cabal.project @@ -1,4 +1,2 @@ packages: - . - examples - benchmarks + ./ diff --git a/clickable.cabal b/clickable.cabal new file mode 100644 index 0000000..12cb04a --- /dev/null +++ b/clickable.cabal @@ -0,0 +1,42 @@ +cabal-version: 3.0 +name: clickable +version: 0.1.0.0 +-- synopsis: +-- description: +license: MIT +license-file: ./LICENSE +author: Vladislav Lagunov +maintainer: vlad.lagunoff@gmail.com +-- copyright: +build-type: Simple +extra-doc-files: CHANGELOG.md +-- extra-source-files: + +executable clickable + main-is: websocket.hs + hs-source-dirs: ./ + other-modules: + Clickable + Clickable.Html + Clickable.Types + Clickable.Internal + Clickable.WebSocket + Clickable.Float + -- other-extensions: + build-depends: + async, + base, + base64-bytestring, + binary, + bytestring, + containers, + ghc-prim, + http-types, + mtl, + text, + wai, + wai-websockets, + warp, + websockets, + default-language: GHC2021 + diff --git a/default.nix b/default.nix deleted file mode 100644 index c219a45..0000000 --- a/default.nix +++ /dev/null @@ -1,54 +0,0 @@ -{ pkgs ? import (builtins.fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/refs/tags/24.05.tar.gz"; -}) {} -}: - -let - inherit (pkgs.haskell.lib) doJailbreak; - - haskellPackages = pkgs.haskell.packages.ghcHEAD.override { - overrides = self: super: { - mkDerivation = args: super.mkDerivation ({ - doCheck = false; - doBenchmark = false; - doHoogle = false; - doHaddock = false; - jailbreak = true; - enableLibraryProfiling = false; - enableExecutableProfiling = false; - } // args); - - htmlt = self.callCabal2nix "htmlt" ./. {}; - - th-compat = self.callCabal2nix "th-compat" (builtins.fetchGit { - url = "https://github.com/haskell-compat/th-compat.git"; - rev = "eec1edb9e09eba14e7ba17be29a9674431c63c05"; - }) {}; - - th-abstraction = self.callCabal2nix "th-abstraction" (builtins.fetchGit { - url = "https://github.com/glguy/th-abstraction.git"; - rev = "1fb59d1651ac5462f44100c62e5806665d39b6c6"; - }) {}; - - aeson = doJailbreak (self.callCabal2nix "aeson" (builtins.fetchGit { - url = "https://github.com/haskell/aeson.git"; - rev = "0834ba7b081297d44c706914c92c31d264aef816"; - }) {}); - }; - }; - - result = { - pkgs = haskellPackages; - shell = pkgs.mkShell { - inputsFrom = [haskellPackages.htmlt.env]; - # fails to build, you have to have cabal installed on your system - # buildDepends = [haskellPackages.cabal-install]; - }; - javascript = pkgs.mkShell { - buildInputs = [ - pkgs.pkgsCross.ghcjs.buildPackages.haskell.compiler.ghcHEAD - ]; - }; - }; -in - result diff --git a/examples/examples.cabal b/examples/examples.cabal deleted file mode 100644 index 749e385..0000000 --- a/examples/examples.cabal +++ /dev/null @@ -1,44 +0,0 @@ -cabal-version: 3.4 - -name: examples -version: 0.1.0.0 -build-type: Simple - -executable todomvc - ghc-options: - -O3 -funbox-strict-fields -fstrictness -ddump-splices - -Wall -Wno-missing-signatures -Wno-name-shadowing -Wno-unused-matches - -Wno-unused-do-bind - hs-source-dirs: todomvc - if arch(wasm32) - ghc-options: - -no-hs-main -optl-mexec-model=reactor - -optl-Wl,--export=hs_init,--export=wasm_app,--export=malloc,--export=free - main-is: wasm.hs - else - main-is: dev.hs - build-depends: - base, - text, - transformers, - mtl, - htmlt, - other-modules: - App - TodoItem - TodoList - Utils - default-extensions: - GHC2024 - AllowAmbiguousTypes - BlockArguments - DefaultSignatures - DeriveAnyClass - FunctionalDependencies - OverloadedRecordDot - OverloadedStrings - PackageImports - RecordWildCards - RecursiveDo - TypeFamilies - UndecidableInstances diff --git a/examples/todomvc/App.hs b/examples/todomvc/App.hs deleted file mode 100644 index 98fac0c..0000000 --- a/examples/todomvc/App.hs +++ /dev/null @@ -1,24 +0,0 @@ -module App where - -import Control.Monad.Trans -import Data.Maybe -import Clickable - -import "this" TodoList qualified as TodoList -import "this" Utils - -app :: StartFlags -> ClickM () -app _ = do - items <- fromMaybe [] <$> readLocalStorage "todo-items" - stateVar <- TodoList.new items - installFinalizer do - s <- readVar stateVar - saveLocalStorage "todo-items" s.items - attachToBody do - el "style" $ text TodoList.styles - TodoList.html TodoList.TodoListConfig - { state_var = stateVar - } - lift $ addEventListener popstateEvent \loc -> do - let filter = fromMaybe TodoList.All $ TodoList.parseFilter loc.hash - modifyVar_ stateVar \s -> s {TodoList.filter} diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs deleted file mode 100644 index 3a1da61..0000000 --- a/examples/todomvc/TodoItem.hs +++ /dev/null @@ -1,84 +0,0 @@ -module TodoItem where - -import Clickable -import Data.List qualified as List -import Data.Maybe -import Data.Text (Text) -import GHC.Int -import GHC.Generics - -import "this" Utils - -data TodoItemConfig = TodoItemConfig - { state_var :: DynVar TodoItemState - , is_hidden_dyn :: DynVal Bool - , ask_delete_item :: ClickM () - } - -data TodoItemState = TodoItemState - { title :: Text - , completed :: Bool - , editing :: Maybe Text - } deriving stock (Show, Eq, Generic) - deriving anyclass (FromValue, ToValue) - -data TodoItemAction a where - CancelAction :: TodoItemAction () - CommitAction :: TodoItemAction () - InputAction :: Text -> TodoItemAction () - DoubleClickAction :: VarId -> TodoItemAction () - CheckedAction :: Bool -> TodoItemAction () - KeydownAction :: Int32 -> TodoItemAction () - -emptyState :: TodoItemState -emptyState = TodoItemState "" False Nothing - -eval :: TodoItemConfig -> TodoItemAction a -> ClickM a -eval cfg CancelAction = - modifyVar_ cfg.state_var \s -> s{editing=Nothing} -eval cfg CommitAction = do - state <- readVar cfg.state_var - case state.editing of - Just "" -> - cfg.ask_delete_item - Just t -> - modifyVar_ cfg.state_var \s -> s {editing=Nothing, title = t} - Nothing -> - pure () -eval cfg (InputAction newVal) = - modifyVar_ cfg.state_var \s -> s{editing = Just newVal} -eval cfg (DoubleClickAction inpElm) = do - trampoline do - modifyVar_ cfg.state_var \s -> s {editing = Just s.title} - syncPoint - assignFocus inpElm -eval cfg (CheckedAction isChecked) = - modifyVar_ cfg.state_var \s -> s{completed = isChecked} -eval cfg (KeydownAction key) = case key of - 13 {- Enter -} -> eval cfg CommitAction - 27 {- Escape -} -> eval cfg CancelAction - _ -> return () - -html :: TodoItemConfig -> HtmlM () -html cfg = li_ mdo - let completedDyn = (.completed) <$> fromVar cfg.state_var - editingDyn = isJust . (.editing) <$> fromVar cfg.state_var - valueDyn = fromMaybe "" . (.editing) <$> fromVar cfg.state_var - toggleClass "completed" completedDyn - toggleClass "editing" editingDyn - toggleClass "hidden" cfg.is_hidden_dyn - div_ [class_ "view"] do - on @"dblclick" $ eval cfg $ DoubleClickAction inp - input_ [class_ "toggle", type_ "checkbox"] do - dynChecked $ (.completed) <$> fromVar cfg.state_var - on @"checkbox/change" $ eval cfg . CheckedAction - label_ $ dynText $ (.title) <$> fromVar cfg.state_var - button_ [class_ "destroy"] do - on @"click" cfg.ask_delete_item - inp <- input_ [class_ "edit", type_ "text"] do - dynValue valueDyn - on @"input" $ eval cfg . InputAction - on @"keydown" $ eval cfg . KeydownAction - on @"blur" $ eval cfg CommitAction - saveDomBuilder - return () diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs deleted file mode 100644 index 3369a2b..0000000 --- a/examples/todomvc/TodoList.hs +++ /dev/null @@ -1,568 +0,0 @@ -module TodoList where - -import Clickable -import Control.Monad -import Data.List qualified as List -import Data.Text (Text) -import Data.Text qualified as Text -import GHC.Int - -import "this" TodoItem qualified as TodoItem - - -data TodoListConfig = TodoListConfig - { state_var :: DynVar TodoListState - } - -data TodoListState = TodoListState - { title :: Text - , items :: [TodoItem.TodoItemState] - , filter :: Filter - } deriving (Show, Eq) - -data Filter = All | Active | Completed - deriving (Show, Eq) - -data TodoListAction a where - ToggleAllAction :: Bool -> TodoListAction () - InputAction :: Text -> TodoListAction () - CommitAction :: TodoListAction () - KeydownAction :: Int32 -> TodoListAction () - DeleteItemAction :: Int -> TodoListAction () - ClearCompletedAction :: TodoListAction () - -new :: [TodoItem.TodoItemState] -> ClickM (DynVar TodoListState) -new items = - newVar TodoListState - { title = "" - , items = items - , filter = All - } - -eval :: TodoListConfig -> TodoListAction a -> ClickM a -eval cfg (ToggleAllAction isChecked) = - modifyVar_ cfg.state_var \s -> s - { items = - fmap (\i -> i {TodoItem.completed = isChecked}) s.items - } -eval cfg (InputAction newVal) = - modifyVar_ cfg.state_var \s -> s {title = newVal} -eval cfg CommitAction = do - title <- Text.strip . (.title) <$> readVar cfg.state_var - case title of - "" -> return () - t -> modifyVar_ cfg.state_var \s -> s - { items = s.items <> [newTodo t] - , title = "" - } - where - newTodo t = TodoItem.emptyState {TodoItem.title = t} -eval cfg (KeydownAction key) = case key of - 13 {- Enter -} -> eval cfg CommitAction - _ -> return () -eval cfg (DeleteItemAction itemIx) = - modifyVar_ cfg.state_var \s -> s {items = deleteIx itemIx s.items} - where - deleteIx :: Int -> [a] -> [a] - deleteIx _ [] = [] - deleteIx i (a:as) | i == 0 = as | otherwise = a : deleteIx (i-1) as -eval cfg ClearCompletedAction = - modifyVar_ cfg.state_var \s -> s - {items = (List.filter (not . TodoItem.completed)) s.items} - -html :: TodoListConfig -> HtmlM () -html cfg = do - div_ do - section_ [class_ "todoapp"] do - headerWidget - mainWidget - footerWidget - footerInfoWidget - where - headerWidget = header_ [class_ "header"] do - h1_ (text "todos") - input_ [class_ "new-todo", placeholder_ "What needs to be done?", autofocus_ True] do - dynValue $ (.title) <$> fromVar cfg.state_var - on @"input" $ eval cfg . InputAction - on @"keydown" $ eval cfg . KeydownAction - mainWidget = section_ [class_ "main"] do - toggleClass "hidden" hiddenDyn - input_ [id_ "toggle-all", class_ "toggle-all", type_ "checkbox"] do - on @"checkbox/change" $ eval cfg . ToggleAllAction - label_ do - attribute "for" "toggle-all" - text "Mark all as completed" - ul_ [class_ "todo-list"] do - simpleList itemsDyn \i todoRef -> - TodoItem.html $ TodoItem.TodoItemConfig - { TodoItem.state_var = overrideVar (todoItemUpdated cfg i) todoRef - , TodoItem.is_hidden_dyn = - isTodoItemHidden <$> fromVar cfg.state_var <*> fromVar todoRef - , TodoItem.ask_delete_item = eval cfg $ DeleteItemAction i - } - footerWidget = footer_ [class_ "footer"] do - toggleClass "hidden" hiddenDyn - span_ [class_ "todo-count"] do - strong_ $ dynText $ Text.pack . show <$> itemsLeftDyn - dynText $ pluralize " item left" " items left" <$> itemsLeftDyn - ul_ [class_ "filters"] do - forM_ [All, Active, Completed] filterWidget - button_ [class_ "clear-completed"] do - on @"click" $ eval cfg ClearCompletedAction - text "Clear completed" - footerInfoWidget = footer_ [class_ "info"] do - p_ "Double-click to edit a todo" - p_ do - text "Created by " - a_ [href_ "https://github.com/lagunoff"] "Vlad Lagunov" - p_ do - text "Part of " - a_ [href_ "http://todomvc.com"] "TodoMVC" - filterWidget :: Filter -> HtmlM () - filterWidget flt = li_ do - a_ [href_ (printFilter flt)] do - toggleClass "selected" $ filterSelectedDyn flt - text $ Text.pack $ show flt - hiddenDyn = - Prelude.null . (.items) <$> fromVar cfg.state_var - itemsLeftDyn = - countItemsLeft <$> fromVar cfg.state_var - filterSelectedDyn flt = - (==flt) . (.filter) <$> fromVar cfg.state_var - itemsDyn = - (.items) <$> fromVar cfg.state_var - countItemsLeft TodoListState{items} = - foldl (\acc TodoItem.TodoItemState{completed} -> - if not completed then acc + 1 else acc) 0 items - isTodoItemHidden :: TodoListState -> TodoItem.TodoItemState -> Bool - isTodoItemHidden listState itemState = - case (listState.filter, itemState.completed) of - (Active, True) -> True - (Completed, False) -> True - _ -> False - --- | Synchronize TodoItem state with the larger state of TodoList --- widget. -todoItemUpdated - :: TodoListConfig - -> Int - -> UpdateFn TodoItem.TodoItemState - -> UpdateFn TodoItem.TodoItemState -todoItemUpdated cfg i next f = do - -- Update the local TodoItemState - ((old, new), result) <- next g - let - -- When False, the update event won't be propagated into the outer - -- widget for the sake of optimization - needsUpdate = old.completed /= new.completed - -- Update TodoItemState inside the larger state - if needsUpdate - then modifyVar cfg.state_var $ h new - else modifyVarQuiet cfg.state_var $ h new - return result - where - g s = let (s', a) = f s in (s', ((s, s'), a)) - h e s = (s {items = updateIx i e s.items}, ()) - - updateIx :: Int -> a -> [a] -> [a] - updateIx 0 a (x:xs) = a : xs - updateIx n a (x:xs) = x : updateIx (pred n) a xs - updateIx _ _ [] = [] - -pluralize :: Text -> Text -> Int -> Text -pluralize singular _plural 0 = singular -pluralize _singular plural _ = plural - -parseFilter :: Text -> Maybe Filter -parseFilter = \case - "#/" -> Just All - "#/active" -> Just Active - "#/completed" -> Just Completed - _ -> Nothing - -printFilter :: Filter -> Text -printFilter = \case - All -> "#/" - Active -> "#/active" - Completed -> "#/completed" - -styles :: Text -styles = "\ - \body {\ - \ margin: 0;\ - \ padding: 0 ;\ - \}\ - \\ - \button {\ - \ margin: 0;\ - \ padding: 0;\ - \ border: 0;\ - \ background: none;\ - \ font-size: 100%;\ - \ vertical-align: baseline;\ - \ font-family: inherit;\ - \ font-weight: inherit;\ - \ color: inherit;\ - \ -webkit-appearance: none;\ - \ appearance: none;\ - \ -webkit-font-smoothing: antialiased;\ - \ -moz-osx-font-smoothing: grayscale;\ - \}\ - \\ - \body {\ - \ font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;\ - \ line-height: 1.4em;\ - \ background: #f5f5f5;\ - \ color: #4d4d4d;\ - \ min-width: 230px;\ - \ max-width: 550px;\ - \ margin: 0 auto;\ - \ -webkit-font-smoothing: antialiased;\ - \ -moz-osx-font-smoothing: grayscale;\ - \ font-weight: 300;\ - \}\ - \\ - \:focus {\ - \ outline: 0;\ - \}\ - \\ - \.hidden {\ - \ display: none;\ - \}\ - \\ - \.todoapp {\ - \ background: #fff;\ - \ margin: 130px 0 40px 0;\ - \ position: relative;\ - \ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),\ - \ 0 25px 50px 0 rgba(0, 0, 0, 0.1);\ - \}\ - \\ - \.todoapp input::-webkit-input-placeholder {\ - \ font-style: italic;\ - \ font-weight: 300;\ - \ color: #e6e6e6;\ - \}\ - \\ - \.todoapp input::-moz-placeholder {\ - \ font-style: italic;\ - \ font-weight: 300;\ - \ color: #e6e6e6;\ - \}\ - \\ - \.todoapp input::input-placeholder {\ - \ font-style: italic;\ - \ font-weight: 300;\ - \ color: #e6e6e6;\ - \}\ - \\ - \.todoapp h1 {\ - \ position: absolute;\ - \ top: -155px;\ - \ width: 100%;\ - \ font-size: 100px;\ - \ font-weight: 100;\ - \ text-align: center;\ - \ color: rgba(175, 47, 47, 0.15);\ - \ -webkit-text-rendering: optimizeLegibility;\ - \ -moz-text-rendering: optimizeLegibility;\ - \ text-rendering: optimizeLegibility;\ - \}\ - \\ - \.new-todo,\ - \.edit {\ - \ position: relative;\ - \ margin: 0;\ - \ width: 100%;\ - \ font-size: 24px;\ - \ font-family: inherit;\ - \ font-weight: inherit;\ - \ line-height: 1.4em;\ - \ border: 0;\ - \ color: inherit;\ - \ padding: 6px;\ - \ border: 1px solid #999;\ - \ box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);\ - \ box-sizing: border-box;\ - \ -webkit-font-smoothing: antialiased;\ - \ -moz-osx-font-smoothing: grayscale;\ - \}\ - \\ - \.new-todo {\ - \ padding: 16px 16px 16px 60px;\ - \ border: none;\ - \ background: rgba(0, 0, 0, 0.003);\ - \ box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);\ - \}\ - \\ - \.main {\ - \ position: relative;\ - \ z-index: 2;\ - \ border-top: 1px solid #e6e6e6;\ - \}\ - \\ - \.toggle-all {\ - \ width: 1px;\ - \ height: 1px;\ - \ border: none; /* Mobile Safari */\ - \ opacity: 0;\ - \ position: absolute;\ - \ right: 100%;\ - \ bottom: 100%;\ - \}\ - \\ - \.toggle-all + label {\ - \ width: 60px;\ - \ height: 34px;\ - \ font-size: 0;\ - \ position: absolute;\ - \ top: -52px;\ - \ left: -13px;\ - \ -webkit-transform: rotate(90deg);\ - \ transform: rotate(90deg);\ - \}\ - \\ - \.toggle-all + label:before {\ - \ content: '❯';\ - \ font-size: 22px;\ - \ color: #e6e6e6;\ - \ padding: 10px 27px 10px 27px;\ - \}\ - \\ - \.toggle-all:checked + label:before {\ - \ color: #737373;\ - \}\ - \\ - \.todo-list {\ - \ margin: 0;\ - \ padding: 0;\ - \ list-style: none;\ - \}\ - \\ - \.todo-list li {\ - \ position: relative;\ - \ font-size: 24px;\ - \ border-bottom: 1px solid #ededed;\ - \}\ - \\ - \.todo-list li:last-child {\ - \ border-bottom: none;\ - \}\ - \\ - \.todo-list li.editing {\ - \ border-bottom: none;\ - \ padding: 0;\ - \}\ - \\ - \.todo-list li.editing .edit {\ - \ display: block;\ - \ width: calc(100% - 43px);\ - \ padding: 12px 16px;\ - \ margin: 0 0 0 43px;\ - \}\ - \\ - \.todo-list li.editing .view {\ - \ display: none;\ - \}\ - \\ - \.todo-list li .toggle {\ - \ text-align: center;\ - \ width: 40px;\ - \ /* auto, since non-WebKit browsers doesn't support input styling */\ - \ height: auto;\ - \ position: absolute;\ - \ top: 0;\ - \ bottom: 0;\ - \ margin: auto 0;\ - \ border: none; /* Mobile Safari */\ - \ -webkit-appearance: none;\ - \ appearance: none;\ - \}\ - \\ - \.todo-list li .toggle {\ - \ opacity: 0;\ - \}\ - \\ - \.todo-list li .toggle + label {\ - \ /*\ - \ Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433\ - \ IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/\ - \ */\ - \ background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');\ - \ background-repeat: no-repeat;\ - \ background-position: center left;\ - \}\ - \\ - \.todo-list li .toggle:checked + label {\ - \ background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');\ - \}\ - \\ - \.todo-list li label {\ - \ word-break: break-all;\ - \ padding: 15px 15px 15px 60px;\ - \ display: block;\ - \ line-height: 1.2;\ - \ transition: color 0.4s;\ - \}\ - \\ - \.todo-list li.completed label {\ - \ color: #d9d9d9;\ - \ text-decoration: line-through;\ - \}\ - \\ - \.todo-list li .destroy {\ - \ display: none;\ - \ position: absolute;\ - \ top: 0;\ - \ right: 10px;\ - \ bottom: 0;\ - \ width: 40px;\ - \ height: 40px;\ - \ margin: auto 0;\ - \ font-size: 30px;\ - \ color: #cc9a9a;\ - \ margin-bottom: 11px;\ - \ transition: color 0.2s ease-out;\ - \}\ - \\ - \.todo-list li .destroy:hover {\ - \ color: #af5b5e;\ - \}\ - \\ - \.todo-list li .destroy:after {\ - \ content: '×';\ - \}\ - \\ - \.todo-list li:hover .destroy {\ - \ display: block;\ - \}\ - \\ - \.todo-list li .edit {\ - \ display: none;\ - \}\ - \\ - \.todo-list li.editing:last-child {\ - \ margin-bottom: -1px;\ - \}\ - \\ - \.footer {\ - \ color: #777;\ - \ padding: 10px 15px;\ - \ height: 20px;\ - \ text-align: center;\ - \ border-top: 1px solid #e6e6e6;\ - \}\ - \\ - \.footer:before {\ - \ content: '';\ - \ position: absolute;\ - \ right: 0;\ - \ bottom: 0;\ - \ left: 0;\ - \ height: 50px;\ - \ overflow: hidden;\ - \ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),\ - \ 0 8px 0 -3px #f6f6f6,\ - \ 0 9px 1px -3px rgba(0, 0, 0, 0.2),\ - \ 0 16px 0 -6px #f6f6f6,\ - \ 0 17px 2px -6px rgba(0, 0, 0, 0.2);\ - \}\ - \\ - \.todo-count {\ - \ float: left;\ - \ text-align: left;\ - \}\ - \\ - \.todo-count strong {\ - \ font-weight: 300;\ - \}\ - \\ - \.filters {\ - \ margin: 0;\ - \ padding: 0;\ - \ list-style: none;\ - \ position: absolute;\ - \ right: 0;\ - \ left: 0;\ - \}\ - \\ - \.filters li {\ - \ display: inline;\ - \}\ - \\ - \.filters li a {\ - \ color: inherit;\ - \ margin: 3px;\ - \ padding: 3px 7px;\ - \ text-decoration: none;\ - \ border: 1px solid transparent;\ - \ border-radius: 3px;\ - \}\ - \\ - \.filters li a:hover {\ - \ border-color: rgba(175, 47, 47, 0.1);\ - \}\ - \\ - \.filters li a.selected {\ - \ border-color: rgba(175, 47, 47, 0.2);\ - \}\ - \\ - \.clear-completed,\ - \html .clear-completed:active {\ - \ float: right;\ - \ position: relative;\ - \ line-height: 20px;\ - \ text-decoration: none;\ - \ cursor: pointer;\ - \}\ - \\ - \.clear-completed:hover {\ - \ text-decoration: underline;\ - \}\ - \\ - \.info {\ - \ margin: 65px auto 0;\ - \ color: #bfbfbf;\ - \ font-size: 10px;\ - \ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\ - \ text-align: center;\ - \}\ - \\ - \.info p {\ - \ line-height: 1;\ - \}\ - \\ - \.info a {\ - \ color: inherit;\ - \ text-decoration: none;\ - \ font-weight: 400;\ - \}\ - \\ - \.info a:hover {\ - \ text-decoration: underline;\ - \}\ - \\ - \/*\ - \ Hack to remove background from Mobile Safari.\ - \ Can't use it globally since it destroys checkboxes in Firefox\ - \*/\ - \@media screen and (-webkit-min-device-pixel-ratio:0) {\ - \ .toggle-all,\ - \ .todo-list li .toggle {\ - \ background: none;\ - \ }\ - \\ - \ .todo-list li .toggle {\ - \ height: 40px;\ - \ }\ - \}\ - \\ - \@media (max-width: 430px) {\ - \ .footer {\ - \ height: 50px;\ - \ }\ - \\ - \ .filters {\ - \ bottom: 10px;\ - \ }\ - \}" diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs deleted file mode 100644 index da360ed..0000000 --- a/examples/todomvc/Utils.hs +++ /dev/null @@ -1,18 +0,0 @@ -module Utils where - -import Data.Text (Text) -import Clickable - -readLocalStorage :: FromValue v => Text -> ClickM (Maybe v) -readLocalStorage key = do - let jsonParse = Call (Id "JSON") "parse" . (:[]) - jsval <- evalExpr $ jsonParse $ Call (Id "localStorage") "getItem" [Str key] - return $ fromValue jsval - -saveLocalStorage :: ToValue v => Text -> v -> ClickM () -saveLocalStorage key val = do - let stringify = Call (Id "JSON") "stringify" . (:[]) . valueToExpr . toValue - enqueueExpr $ Call (Id "localStorage") "setItem" [Str key, stringify val] - -assignFocus :: VarId -> ClickM () -assignFocus elem = enqueueExpr $ Call (Var elem) "focus" [] diff --git a/examples/todomvc/dev.hs b/examples/todomvc/dev.hs deleted file mode 100644 index 9dfe642..0000000 --- a/examples/todomvc/dev.hs +++ /dev/null @@ -1,5 +0,0 @@ -import Clickable.Main.Dev -import App (app) - -main :: IO () -main = runDev app diff --git a/examples/todomvc/wasm.hs b/examples/todomvc/wasm.hs deleted file mode 100644 index 60c19ad..0000000 --- a/examples/todomvc/wasm.hs +++ /dev/null @@ -1,10 +0,0 @@ -import Clickable.Main.Wasm -import GHC.Ptr -import GHC.Word -import App (app) - -main :: IO () -main = return () - -foreign export ccall wasm_app :: Ptr Word8 -> IO () -wasm_app = runWasm app diff --git a/ghc-wasm-meta b/ghc-wasm-meta deleted file mode 160000 index 7b3caea..0000000 --- a/ghc-wasm-meta +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7b3caea9828966b9f9b70b715f96768adb51c052 diff --git a/hie.yaml b/hie.yaml new file mode 100644 index 0000000..d15699f --- /dev/null +++ b/hie.yaml @@ -0,0 +1,4 @@ +cradle: + cabal: + - path: "./" + component: "exe:clickable" diff --git a/htmlt.cabal b/htmlt.cabal deleted file mode 100644 index 2e35985..0000000 --- a/htmlt.cabal +++ /dev/null @@ -1,73 +0,0 @@ -cabal-version: 3.4 - -name: htmlt -version: 0.1.0.0 -homepage: https://github.com/lagunoff/htmlt -license: BSD-3-Clause -license-file: LICENSE -author: Vladislav Lagunov -maintainer: vlad.lagunoff@gmail.com -copyright: 2019 Vladislav Lagunov -category: Web -build-type: Simple -extra-source-files: - README.md - -library - ghc-options: - -O3 -funbox-strict-fields -fstrictness - -Wall -Wno-missing-signatures -Wno-name-shadowing -Wno-unused-matches - -Wno-unused-do-bind - hs-source-dirs: src - exposed-modules: - Clickable - Clickable.Core - Clickable.DOM - Clickable.Element - Clickable.Property - Clickable.Main.Wasm - Clickable.Types - Clickable.Internal - Clickable.Protocol - Clickable.Protocol.Value - Clickable.FFI - Wasm.Compat.Prim - other-modules: Paths_htmlt - build-depends: - base, - binary, - bytestring, - containers, - exceptions, - mtl, - text, - transformers, - ghc-experimental, - ghc-prim, - if !arch(wasm32) - exposed-modules: - Clickable.Main.Dev - build-depends: - async, - foreign-store, - http-types, - wai, - wai-app-static, - wai-websockets, - warp, - websockets, - default-extensions: - AllowAmbiguousTypes - BlockArguments - DefaultSignatures - DeriveAnyClass - DuplicateRecordFields - FunctionalDependencies - GHC2024 - OverloadedRecordDot - OverloadedStrings - PackageImports - RecursiveDo - StrictData - TypeFamilies - UndecidableInstances diff --git a/jsbits/#wasm.ts# b/jsbits/#wasm.ts# new file mode 100644 index 0000000..b1bf8ab --- /dev/null +++ b/jsbits/#wasm.ts# @@ -0,0 +1,66 @@ +import { WASI, File, OpenFile } from '@bjorn3/browser_wasi_shim'; +import { ClientMsgTag, EventId, EvalState, PersistentState, Ptr } from "./proto"; +import * as proto from "./proto"; + +let inst: WebAssembly.Instance; + +export function runWasm(wasmUri: string, startFlags: unknown = null) { + const wasi = new WASI([], [], [ + new OpenFile(new File([])), // stdin + new OpenFile(new File([])), // stdout + new OpenFile(new File([])), // stderr + ]); + + const persistent: PersistentState = { + refs: new Map(), + stack: null, + }; + + function clickable_eval_buffer(ptr: Ptr, len: number): void { + // @ts-ignore + const mem = new DataView(inst.exports.memory.buffer); + + function triggerEvent(eventId: EventId, arg: unknown) { + const encoderState = {mem, begin: ptr, end: ptr + len}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.EventMsg, eventId, arg]); + // @ts-ignore + inst.exports.wasm_app(ptr); + }; + + function resumeCont(contId: number, res: unknown) { + const encoderState = {mem, begin: ptr, end: ptr + len}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.ResumeMsg, contId, res]); + // @ts-ignore + inst.exports.wasm_app(ptr); + }; + + const intp: EvalState = { + triggerEvent, + resumeCont, + persistent, + mem, + isMutableMem: true, + begin: ptr, + end: ptr + len, + }; + + proto.evalMem(intp); + } + + WebAssembly.compileStreaming(fetch(wasmUri)) + .then(wasm => WebAssembly.instantiate(wasm, { + wasi_snapshot_preview1: wasi.wasiImport, + env: { + clickable_eval_buffer, + }, + })) + .then(inst1 => { + inst = inst1; + // @ts-ignore + wasi.initialize(inst1); + // @ts-ignore + inst1.exports.hs_init(); + // @ts-ignore + inst1.exports.wasm_app(0); + }); +}; diff --git a/jsbits/#websocket.ts# b/jsbits/#websocket.ts# new file mode 100644 index 0000000..4197f05 --- /dev/null +++ b/jsbits/#websocket.ts# @@ -0,0 +1,82 @@ +import { ClientMsgTag, EventId, EvalState, PersistentState, Ptr } from "./proto"; +import * as proto from "./proto"; + +const outBuf = new ArrayBuffer(100 * 1024); +const mem = new DataView(outBuf); + +export function runWebsocket(devSocketUri: string, startFlags: unknown = null) { + const websocket = new WebSocket(devSocketUri); + const persistent: PersistentState = { + refs: new Map(), + stack: null, + }; + + function triggerEvent(eventId: EventId, arg: unknown) { + const encoderState = {mem, begin: 0, end: outBuf.byteLength}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.EventMsg, eventId, arg]); + websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); + }; + + function resumeCont(contId: number, res: unknown) { + const encoderState = {mem, begin: 0, end: outBuf.byteLength}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.ResumeMsg, contId, res]); + websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); + }; + + websocket.onopen = (_event) => { + const encoderState = {mem, begin: 0, end: outBuf.byteLength}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.StartMsg, startFlags]); + websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); + }; + + // Event handler for receiving messages from the server + websocket.onmessage = (event) => { + convertBlobToUint8Array(event.data).then(buf => { + proto.evalMem({ + triggerEvent, + resumeCont, + persistent, + mem: new DataView(buf), + isMutableMem: false, + begin: 0, + end: buf.byteLength, + }); + }); + }; + + // Event handler for errors + websocket.onerror = (event) => { + console.error("WebSocket error:", event); + }; + + // Event handler for when the connection is closed + websocket.onclose = (_event) => { + console.log("WebSocket connection closed, reloading the tab…"); + + function backoffLoop(timeout: number) { + // Assuming the server went down because it was re-compiled, wait + // until it comes back and reload the tab + const websocketTest = new WebSocket(devSocketUri); + const nextTimeout = Math.min(30_000, timeout * 2); + websocketTest.onopen = (_event) => window.location.reload(); + websocketTest.onclose = (_event) => { setTimeout(() => backoffLoop(nextTimeout), timeout); } + } + backoffLoop(100); + }; +} + +export function convertBlobToUint8Array(blob: Blob): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = () => { + resolve(reader.result as ArrayBuffer); + }; + + reader.onerror = (error) => { + reject(error); + }; + + reader.readAsArrayBuffer(blob); + }); +} diff --git a/jsbits/binary.ts b/jsbits/binary.ts deleted file mode 100644 index 69d0949..0000000 --- a/jsbits/binary.ts +++ /dev/null @@ -1,467 +0,0 @@ -/** - * Data.Binary serialization library implemented in typescript - */ -import { absurd } from './lib'; - -type HaskellPointer = number; - -export class DecoderBase
{ - // @ts-ignore - readonly _A: A; - - encode(value: A): Uint8Array { - const decoder = this as Decoder; - const size = computeSize(decoder, value); - const u8array = new Uint8Array(size); - runEncoder(decoder, u8array, 0, value); - return u8array; - } - - decode(mem: Uint8Array): A { - const decoder = this as Decoder; - const [resultVal, _ptr] = runDecoder(decoder, mem, 0); - return resultVal; - } -} - -export type Decoder = - | Int8Decoder - | Int16Decoder - | Int32Decoder - | Int64Decoder - | Word8Decoder - | Word16Decoder - | Word32Decoder - | Word64Decoder - | Float32Decoder - | Float64Decoder - | Uint8ArrayDecoder - | StringDecoder - | ArrayDecoder - | RecordDecoder - | OneOfDecoder - | RecursiveDecoder - | TupleDecoder -; - -export class Int8Decoder extends DecoderBase {} -export class Int16Decoder extends DecoderBase {} -export class Int32Decoder extends DecoderBase {} -export class Int64Decoder extends DecoderBase {} -export class Word8Decoder extends DecoderBase {} -export class Word16Decoder extends DecoderBase {} -export class Word32Decoder extends DecoderBase {} -export class Word64Decoder extends DecoderBase {} -export class Float32Decoder extends DecoderBase {} -export class Float64Decoder extends DecoderBase {} -export class Uint8ArrayDecoder extends DecoderBase {} -export class StringDecoder extends DecoderBase {} -export class ArrayDecoder extends DecoderBase { - constructor( - readonly _element: Decoder, - ) { super(); } -} -export class RecordDecoder extends DecoderBase { - constructor( - readonly _description: Record>, - ) { super(); } -} -export class OneOfDecoder extends DecoderBase { - constructor( - readonly _alternatives: Record>, - ) { super(); } -} -export class RecursiveDecoder extends DecoderBase { - constructor( - public _self: Decoder, - ) { super(); } -} -export class TupleDecoder extends DecoderBase { - constructor( - readonly _tuple: Decoder[], - ) { super(); } -} -export function computeSize( - decoder: Decoder, - value: A -): number { - if (decoder instanceof Int8Decoder) { - return 1; - } - if (decoder instanceof Int16Decoder) { - return 2; - } - if (decoder instanceof Int32Decoder) { - return 4; - } - if (decoder instanceof Int64Decoder) { - return 8; - } - if (decoder instanceof Word8Decoder) { - return 1; - } - if (decoder instanceof Word16Decoder) { - return 2; - } - if (decoder instanceof Word32Decoder) { - return 4; - } - if (decoder instanceof Word64Decoder) { - return 8; - } - if (decoder instanceof Float32Decoder) { - return 4; - } - if (decoder instanceof Float64Decoder) { - return 8; - } - if (decoder instanceof StringDecoder) { - const str = value as any as string; - const lengthSize = 8; // How many bytes to encode array length - const u8array = new TextEncoder().encode(str); - return lengthSize + u8array.length; - } - if (decoder instanceof Uint8ArrayDecoder) { - const u8array = value as any as Uint8Array; - const lengthSize = 8; // How many bytes to encode array length - return lengthSize + u8array.length; - } - if (decoder instanceof ArrayDecoder) { - const array = value as any as any[]; - const lengthSize = 8; // How many bytes to encode array length - return array.reduce((acc, v) => acc + computeSize(decoder._element, v), lengthSize); - } - if (decoder instanceof RecordDecoder) { - const obj = value as any as Record; - return Object.keys(decoder._description).reduce(((acc, k) => - acc + computeSize(decoder._description[k], obj[k]) - ), 0 - ); - } - if (decoder instanceof OneOfDecoder) { - const obj = value as any as { tag: number }; - const dscrSize = discriminatorSize(Object.keys(decoder._alternatives).length); - return dscrSize + computeSize(decoder._alternatives[obj.tag], obj); - } - if (decoder instanceof RecursiveDecoder) { - return computeSize(decoder._self, value); - } - if (decoder instanceof TupleDecoder) { - const tupleVal = value as any as any[]; - return decoder._tuple.reduce((acc, v, i) => acc + computeSize(v, tupleVal[i]), 0); - } - return absurd(decoder); -} - -export function runDecoder( - decoder: Decoder, - mem: Uint8Array, - ptr: HaskellPointer, -): [A, HaskellPointer] { - const view = new DataView(mem.buffer); - if (decoder instanceof Int8Decoder) { - const value = view.getInt8(ptr) as any; - return [value, ptr + 1]; - } - if (decoder instanceof Int16Decoder) { - const value = view.getInt16(ptr, true) as any; - return [value, ptr + 2]; - } - if (decoder instanceof Int32Decoder) { - const value = view.getInt32(ptr, true) as any; - return [value as any as A, ptr + 4]; - } - if (decoder instanceof Int64Decoder) { - const value = view.getBigInt64(ptr, true) as any; - return [value, ptr + 8]; - } - if (decoder instanceof Word8Decoder) { - const result = mem[ptr] as any as A; - return [result, ptr + 1]; - } - if (decoder instanceof Word16Decoder) { - const value = view.getUint8(ptr) as any; - return [value, ptr + 1]; - } - if (decoder instanceof Word32Decoder) { - const value = view.getUint32(ptr, true) as any; - return [value as any as A, ptr + 4]; - } - if (decoder instanceof Word64Decoder) { - const value = view.getBigUint64(ptr, true) as any; - return [value, ptr + 8]; - } - if (decoder instanceof Float32Decoder) { - const value = view.getFloat32(ptr, true) as any; - return [value, ptr + 4]; - } - if (decoder instanceof Float64Decoder) { - const value = view.getFloat64(ptr, true) as any; - return [value, ptr + 8]; - } - if (decoder instanceof StringDecoder) { - const len = mem[ptr + 7] + - (mem[ptr + 6] << 8) + - (mem[ptr + 5] << 16) + - (mem[ptr + 4] << 24) + - (mem[ptr + 3] << 32) + - (mem[ptr + 2] << 40) + - (mem[ptr + 1] << 48) + - (mem[ptr] << 56); - const strView = mem.subarray(ptr + 8, ptr + 8 + len); - const resultStr = new TextDecoder("utf8").decode(strView) as any as A; - return [resultStr, ptr + 8 + len]; - } - if (decoder instanceof Uint8ArrayDecoder) { - const len = mem[ptr + 7] + - (mem[ptr + 6] << 8) + - (mem[ptr + 5] << 16) + - (mem[ptr + 4] << 24) + - (mem[ptr + 3] << 32) + - (mem[ptr + 2] << 40) + - (mem[ptr + 1] << 48) + - (mem[ptr] << 56); - const resultU8Arr = mem.subarray(ptr + 8, ptr + 8 + len) as any as A; - return [resultU8Arr, ptr + 8 + len]; - } - if (decoder instanceof ArrayDecoder) { - const len = mem[ptr + 7] + - (mem[ptr + 6] << 8) + - (mem[ptr + 5] << 16) + - (mem[ptr + 4] << 24) + - (mem[ptr + 3] << 32) + - (mem[ptr + 2] << 40) + - (mem[ptr + 1] << 48) + - (mem[ptr] << 56); - const resultArr = []; - let jx = ptr + 8; - for (let i = 0; i < len; i++) { - const [val, newIx] = runDecoder(decoder._element, mem, jx); - resultArr.push(val); - jx = newIx; - } - return [resultArr as any as A, jx]; - } - if (decoder instanceof RecordDecoder) { - let jx = ptr; - const resultRec = Object.fromEntries( - Object.entries(decoder._description).map(([k, dec]) => { - const [val, newIx] = runDecoder(dec, mem, jx); - jx = newIx; - return [k, val]; - }) - ); - return [resultRec as any as A, jx]; - } - if (decoder instanceof OneOfDecoder) { - const dscrSize = discriminatorSize(Object.keys(decoder._alternatives).length); - const [tag, ix1] = readDiscriminator(dscrSize, mem, ptr); - const [oneValue, ix2] = runDecoder(decoder._alternatives[tag], mem, ix1); - oneValue['tag'] = tag; - return [oneValue, ix2]; - } - if (decoder instanceof RecursiveDecoder) { - return runDecoder(decoder._self, mem, ptr); - } - if (decoder instanceof TupleDecoder) { - let jx = ptr; - const resultTup = decoder._tuple.map(dec => { - const [val, newIx] = runDecoder(dec, mem, jx); - jx = newIx; - return val; - }); - return [resultTup as any as A, jx]; - } - return absurd(decoder); -} - -export function runEncoder( - decoder: Decoder, - mem: Uint8Array, - ptr: HaskellPointer, - value: A, -): HaskellPointer { - const view = new DataView(mem.buffer); - if (decoder instanceof Int8Decoder) { - view.setInt8(ptr, value as number); - return ptr + 1; - } - if (decoder instanceof Int16Decoder) { - view.setInt16(ptr, value as number, true); - return ptr + 2; - } - if (decoder instanceof Int32Decoder) { - view.setInt32(ptr, value as number, true); - return ptr + 4; - } - if (decoder instanceof Int64Decoder) { - view.setBigInt64(ptr, value as bigint, true); - return ptr + 8; - } - if (decoder instanceof Word8Decoder) { - view.setUint8(ptr, value as number); - return ptr + 1; - } - if (decoder instanceof Word16Decoder) { - view.setUint16(ptr, value as number, true); - return ptr + 2; - } - if (decoder instanceof Word32Decoder) { - view.setUint32(ptr, value as number, true); - return ptr + 4; - } - if (decoder instanceof Word64Decoder) { - view.setBigUint64(ptr, value as bigint, true); - return ptr + 8; - } - if (decoder instanceof Float32Decoder) { - view.setFloat32(ptr, value as number, true); - return ptr + 4; - } - if (decoder instanceof Float64Decoder) { - view.setFloat64(ptr, value as number, true); - return ptr + 8; - } - if (decoder instanceof StringDecoder) { - const str = value as any as string; - const encoder = new TextEncoder(); - const strView = encoder.encode(str); - const len = strView.length; - mem[ptr + 7] = len & 0xFF; - mem[ptr + 6] = (len >> 8) & 0xFF; - mem[ptr + 5] = (len >> 16) & 0xFF; - mem[ptr + 4] = (len >> 24) & 0xFF; - // mem[ptr + 3] = (len >> 32) & 0xFF; - // mem[ptr + 2] = (len >> 40) & 0xFF; - // mem[ptr + 1] = (len >> 48) & 0xFF; - // mem[ptr] = (len >> 56) & 0xFF; - mem.set(strView, ptr + 8); - return ptr + 8 + len; - } - if (decoder instanceof Uint8ArrayDecoder) { - const u8Array = value as any as Uint8Array; - const len = u8Array.length; - mem[ptr + 7] = len & 0xFF; - mem[ptr + 6] = (len >> 8) & 0xFF; - mem[ptr + 5] = (len >> 16) & 0xFF; - mem[ptr + 4] = (len >> 24) & 0xFF; - // mem[ptr + 3] = (len >> 32) & 0xFF; - // mem[ptr + 2] = (len >> 40) & 0xFF; - // mem[ptr + 1] = (len >> 48) & 0xFF; - // mem[ptr] = (len >> 56) & 0xFF; - mem.set(u8Array, ptr + 8); - return ptr + 8 + len; - } - if (decoder instanceof ArrayDecoder) { - const array = value as any as any[]; - const len = array.length; - mem[ptr + 7] = len & 0xFF; - mem[ptr + 6] = (len >> 8) & 0xFF; - mem[ptr + 5] = (len >> 16) & 0xFF; - mem[ptr + 4] = (len >> 24) & 0xFF; - // mem[ptr + 3] = (len >> 32) & 0xFF; - // mem[ptr + 2] = (len >> 40) & 0xFF; - // mem[ptr + 1] = (len >> 48) & 0xFF; - // mem[ptr] = (len >> 56) & 0xFF; - let jx = ptr + 8; - for (let i = 0; i < len; i++) { - jx = runEncoder(decoder._element, mem, jx, array[i]); - } - return jx; - } - if (decoder instanceof RecordDecoder) { - const obj = value as Record; - let jx = ptr; - for (const k in decoder._description) { - if (Object.prototype.hasOwnProperty.call(decoder._description, k)) { - jx = runEncoder(decoder._description[k], mem, jx, obj[k]); - } - } - return jx; - } - if (decoder instanceof OneOfDecoder) { - const tag = (value as any)['tag']; - const dscrSize = discriminatorSize(Object.keys(decoder._alternatives).length); - mem[ptr] = tag; - return runEncoder(decoder._alternatives[tag], mem, ptr + dscrSize, value); - } - if (decoder instanceof RecursiveDecoder) { - return runEncoder(decoder._self, mem, ptr, value); - } - if (decoder instanceof TupleDecoder) { - const tupleVal = value as any[]; - let jx = ptr; - decoder._tuple.forEach((dec, i) => { - jx = runEncoder(dec, mem, jx, tupleVal[i]); - }); - return jx; - } - return absurd(decoder); -} - -function discriminatorSize(numAlernatives: number): number { - return Math.ceil(Math.log2(numAlernatives) / 8); -} - -function readDiscriminator(dscrSize: number, mem: Uint8Array, ix: HaskellPointer): [number, HaskellPointer] { - // TODO: complete implementation for dscrSize > 1 - if (dscrSize != 1) throw new Error('Unimplemented'); - return [mem[ix], ix + 1]; -} - -export const int8 = new Int8Decoder(); -export const int16 = new Int16Decoder(); -export const int32 = new Int32Decoder(); -export const int64 = new Int64Decoder(); - -export const word8 = new Word8Decoder(); -export const word16 = new Word16Decoder(); -export const word32 = new Word32Decoder(); -export const word64 = new Word64Decoder(); - -export const float32 = new Float32Decoder(); -export const float64 = new Float64Decoder(); - -export const string = new StringDecoder(); - -export const u8array = new Uint8ArrayDecoder(); - -export function array(d: Decoder): ArrayDecoder { - return new ArrayDecoder(d); -} - -export function record }>(fields: fields): RecordDecoder<{[k in keyof fields]: fields[k]['_A'] }> { - return new RecordDecoder(fields); -} - -export type NarrowDownByTag< - Alternatives extends Record> - > = OneOfDecoder<{ [K in keyof Alternatives]: { tag: K } & Alternatives[K]['_A']}[keyof Alternatives]>; - -export function discriminate>>(alts: Alternatives): NarrowDownByTag { - return new OneOfDecoder(alts); -} - -export function tuple[]>(...args: Args): TupleDecoder<{[k in keyof Args]: Args[k]['_A'] }> { - return new TupleDecoder(args); -} - -export function recursive(f: (self: Decoder) => Decoder): Decoder { - const self = new RecursiveDecoder(undefined as any); - const result = f(self); - self._self = result; - return result; -} - -export type Maybe - = { tag: MaybeTag.Nothing } - | { tag: MaybeTag.Just, 0: A }; - -export enum MaybeTag { Nothing, Just }; - -export function maybe(decoder: Decoder): Decoder> { - return discriminate({ - [MaybeTag.Nothing]: record({}), - [MaybeTag.Just]: record({ 0: decoder }) - }); -} diff --git a/jsbits/dev.ts b/jsbits/dev.ts deleted file mode 100644 index 1c3b548..0000000 --- a/jsbits/dev.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { absurd } from './lib'; -import * as p from './protocol'; -import { HaskellMessage, JavaScriptMessage, JavaScriptMessageTag, HaskellMessageTag } from './protocol'; - -export function startDev(devSocketUri: string, startFlags: unknown = null) { - const websocket = new WebSocket(devSocketUri); - - const haskellCallback = async (jsMsg: JavaScriptMessage) => { - websocket.send(p.javascriptMessage.encode(jsMsg)); - // const haskMsg = await awaitWebsocketMessage(); - // await haskellApp(haskMsg, argScope, sendToHaskell); - }; - - websocket.onopen = (_event) => { - const startFlagsValue = p.unknownToValue(startFlags); - const binaryData = p.javascriptMessage.encode({ - tag: JavaScriptMessageTag.Start, - 0: startFlagsValue - }); - websocket.send(binaryData); - }; - - // Event handler for receiving messages from the server - websocket.onmessage = async (event) => { - const binaryDataReceived = await convertBlobToUint8Array(event.data); - const haskMsg = p.haskellMessage.decode(binaryDataReceived); - haskellApp(haskMsg, haskellCallback); - }; - - // Event handler for errors - websocket.onerror = (event) => { - console.error("WebSocket error:", event); - }; - - // Event handler for when the connection is closed - websocket.onclose = (_event) => { - console.log("WebSocket connection closed, reloading the tab…"); - - function backoffLoop(timeout: number) { - // Assuming the server went down because it was re-compiled, wait - // until it comes back and reload the tab - const websocketTest = new WebSocket(devSocketUri); - const nextTimeout = Math.min(30_000, timeout * 2); - websocketTest.onopen = (_event) => window.location.reload(); - websocketTest.onclose = (_event) => { setTimeout(() => backoffLoop(nextTimeout), timeout); } - } - backoffLoop(100); - }; -} - -export type HaskellAsyncCallback = (jsMsg: JavaScriptMessage) => Promise; - -export async function haskellApp ( - hmsg: HaskellMessage, - haskellCallback: HaskellAsyncCallback -): Promise { - switch (hmsg.tag) { - case HaskellMessageTag.EvalExpr: { - const result = p.evalExpr(hmsg.expr, { haskellCallback }); - const jvalue = p.unknownToValue(result); - const jmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, value: jvalue, threadId: hmsg.threadId }; - return haskellCallback(jmsg); - } - case HaskellMessageTag.HotReload: { - window.location.reload(); - return; - } - case HaskellMessageTag.Halt: { - return; - } - } - absurd(hmsg); -} - -export function convertBlobToUint8Array(blob: Blob): Promise { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - - reader.onload = () => { - const arrayBuffer = reader.result as ArrayBuffer; - const uint8Array = new Uint8Array(arrayBuffer); - resolve(uint8Array); - }; - - reader.onerror = (error) => { - reject(error); - }; - - reader.readAsArrayBuffer(blob); - }); -} diff --git a/jsbits/index.js b/jsbits/index.js index 2399096..53508ec 100644 --- a/jsbits/index.js +++ b/jsbits/index.js @@ -1,11 +1,7 @@ -import * as dev from './dev'; -import * as protocol from './protocol'; +import * as websocket from './websocket'; import * as wasm from './wasm'; -// Inject ClickablePublic object into the global scope window.clickable = { - startWasm: wasm.startWasm, - startDev: dev.startDev, - evalExpr: protocol.evalExpr, - evalUint8Array: protocol.evalUint8Array + runWebsocket: websocket.runWebsocket, + runWasm: wasm.runWasm, }; diff --git a/jsbits/jsffi.js b/jsbits/jsffi.js deleted file mode 100644 index 807eabc..0000000 --- a/jsbits/jsffi.js +++ /dev/null @@ -1,106 +0,0 @@ -import { evalMessage } from './wasm'; - -// This file implements the JavaScript runtime logic for Haskell -// modules that use JSFFI. It is not an ESM module, but the template -// of one; the post-linker script will copy all contents into a new -// ESM module. - -// Manage a mapping from unique 32-bit ids to actual JavaScript -// values. -class JSValManager { - #lastk = 0; - #kv = new Map(); - - constructor() {} - - // Maybe just bump this.#lastk? For 64-bit ids that's sufficient, - // but better safe than sorry in the 32-bit case. - #allocKey() { - let k = this.#lastk; - while (true) { - if (!this.#kv.has(k)) { - this.#lastk = k; - return k; - } - k = (k + 1) | 0; - } - } - - newJSVal(v) { - const k = this.#allocKey(); - this.#kv.set(k, v); - return k; - } - - // A separate has() call to ensure we can store undefined as a value - // too. Also, unconditionally check this since the check is cheap - // anyway, if the check fails then there's a use-after-free to be - // fixed. - getJSVal(k) { - if (!this.#kv.has(k)) { - throw new WebAssembly.RuntimeError(`getJSVal(${k})`); - } - return this.#kv.get(k); - } - - // Check for double free as well. - freeJSVal(k) { - if (!this.#kv.delete(k)) { - throw new WebAssembly.RuntimeError(`freeJSVal(${k})`); - } - } -} - -// A simple & fast setImmediate() implementation for browsers. It's -// not a drop-in replacement for node.js setImmediate() because: -// 1. There's no clearImmediate(), and setImmediate() doesn't return -// anything -// 2. There's no guarantee that callbacks scheduled by setImmediate() -// are executed in the same order (in fact it's the opposite lol), -// but you are never supposed to rely on this assumption anyway -class SetImmediate { - #fs = []; - #mc = new MessageChannel(); - - constructor() { - this.#mc.port1.addEventListener("message", () => { - this.#fs.pop()(); - }); - this.#mc.port1.start(); - } - - setImmediate(cb, ...args) { - this.#fs.push(() => cb(...args)); - this.#mc.port2.postMessage(undefined); - } -} - -// The actual setImmediate() to be used. This is a ESM module top -// level binding and doesn't pollute the globalThis namespace. -let setImmediate; -if (globalThis.setImmediate) { - // node.js, bun - setImmediate = globalThis.setImmediate; -} else { - /* try { - * // deno - * setImmediate = (await import("node:timers")).setImmediate; - * } catch { */ - // browsers - const sm = new SetImmediate(); - setImmediate = (cb, ...args) => sm.setImmediate(cb, ...args); - /* } */ -} - -export default (__exports) => { -const __ghc_wasm_jsffi_jsval_manager = new JSValManager(); -const __ghc_wasm_jsffi_finalization_registry = new FinalizationRegistry(sp => __exports.rts_freeStablePtr(sp)); -return { -newJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v), -getJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k), -freeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k), -scheduleWork: () => setImmediate(__exports.rts_schedulerLoop), -ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1,$2) => {console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));}, -ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC: ($1) => (evalMessage(__exports, $1)), -}; -}; diff --git a/jsbits/lib.ts b/jsbits/lib.ts deleted file mode 100644 index 710a5f1..0000000 --- a/jsbits/lib.ts +++ /dev/null @@ -1,100 +0,0 @@ - -/** Helper for totality checking */ -export function absurd(_x: never): any { - throw new Error('absurd: unreachable code'); -} - -export class IntMap { - public counter: number; - public map: Map; - - constructor() { - this.counter = 0; - this.map = new Map(); - } - - /** - * Generates a new key using the internal counter and maps it to the provided value. - * @param value The value to be mapped to the new key. - * @returns The generated key. - */ - push(value: T): number { - const key = this.counter++; - this.map.set(key, value); - return key; - } - - /** - * Sets the provided key to the specified value. - * @param key The key to set. - * @param value The value to be associated with the key. - */ - set(key: number, value: T): void { - this.map.set(key, value); - } - - /** - * Gets the value associated with the provided key. - * @param key The key to retrieve. - * @returns The value associated with the key, or undefined if the key is not found. - */ - get(key: number): T | undefined { - return this.map.get(key); - } - - /** - * Deletes the key and its associated value from the map. - * @param key The key to delete. - * @returns True if the key was found and deleted, false otherwise. - */ - delete(key: number): boolean { - return this.map.delete(key); - } - - /** - * Checks if the map contains the specified key. - * @param key The key to check. - * @returns True if the key is present in the map, false otherwise. - */ - has(key: number): boolean { - return this.map.has(key); - } - - /** - * Clears all keys and values from the map. - */ - clear(): void { - this.map.clear(); - } - - /** - * Returns an array of all keys in the map. - * @returns An array containing all keys in the map. - */ - keys(): IterableIterator { - return this.map.keys(); - } - - /** - * Returns an array of all values in the map. - * @returns An array containing all values in the map. - */ - values(): IterableIterator { - return this.map.values(); - } - - /** - * Returns an array of key-value pairs in the map. - * @returns An array containing key-value pairs in the map. - */ - entries(): IterableIterator<[number, T]> { - return this.map.entries(); - } - - /** - * Executes a provided function once per each key/value pair in the Map, in insertion order. - */ - forEach(callbackfn: (value: T, key: number, map: Map) => void, thisArg?: any): void { - this.map.forEach(callbackfn, thisArg); - } -} diff --git a/jsbits/post-link.mjs b/jsbits/post-link.mjs deleted file mode 100755 index 9981c7e..0000000 --- a/jsbits/post-link.mjs +++ /dev/null @@ -1,100 +0,0 @@ -#!/nix/store/x1xcjw5628crkk1pwr12y7nwbzkc3969-coreutils-9.4/bin/env -S node - -// This is the post-linker program that processes a wasm module with -// ghc_wasm_jsffi custom section and outputs an ESM module that -// exports a function to generate the ghc_wasm_jsffi wasm imports. It -// has a simple CLI interface: "./post-link.mjs -i foo.wasm -o -// foo.js", as well as an exported postLink function that takes a -// WebAssembly.Module object and returns the ESM module content. - -import fs from "node:fs/promises"; -import path from "node:path"; -import util from "node:util"; - -// Each record in the ghc_wasm_jsffi custom section are 3 -// NUL-terminated strings: name, binder, body. We try to parse the -// body as an expression and fallback to statements, and return the -// completely parsed arrow function source. -function parseRecord([name, binder, body]) { - for (const src of [`${binder} => (${body})`, `${binder} => {${body}}`]) { - try { - new Function(`return ${src};`); - return src; - } catch (_) {} - } - throw new Error(`parseRecord ${name} ${binder} ${body}`); -} - -// Parse ghc_wasm_jsffi custom sections in a WebAssembly.Module object -// and return an array of records. -function parseSections(mod) { - const recs = []; - const dec = new TextDecoder("utf-8", { fatal: true }); - const importNames = new Set( - WebAssembly.Module.imports(mod) - .filter((i) => i.module === "ghc_wasm_jsffi") - .map((i) => i.name), - ); - for (const buf of WebAssembly.Module.customSections(mod, "ghc_wasm_jsffi")) { - const ba = new Uint8Array(buf); - let strs = []; - for (let l = 0, r; l < ba.length; l = r + 1) { - r = ba.indexOf(0, l); - strs.push(dec.decode(ba.subarray(l, r))); - if (strs.length === 3) { - if (importNames.has(strs[0])) { - recs.push(strs); - } - strs = []; - } - } - } - return recs; -} - - -export async function postLink(mod) { - let src = await fs.readFile(path.join(import.meta.dirname, "prelude.js"), { - encoding: "utf-8", - }); - src = `${src}\nexport default (__exports) => {`; - src = `${src}\nconst __ghc_wasm_jsffi_jsval_manager = new JSValManager();`; - src = `${src}\nconst __ghc_wasm_jsffi_finalization_registry = new FinalizationRegistry(sp => __exports.rts_freeStablePtr(sp));`; - src = `${src}\nreturn {`; - src = `${src}\nnewJSVal: (v) => __ghc_wasm_jsffi_jsval_manager.newJSVal(v),`; - src = `${src}\ngetJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.getJSVal(k),`; - src = `${src}\nfreeJSVal: (k) => __ghc_wasm_jsffi_jsval_manager.freeJSVal(k),`; - src = `${src}\nscheduleWork: () => setImmediate(__exports.rts_schedulerLoop),`; - for (const rec of parseSections(mod)) { - src = `${src}\n${rec[0]}: ${parseRecord(rec)},`; - } - return `${src}\n};\n};\n`; -} - -function isMain() { - return import.meta.filename === process.argv[1]; -} - -async function main() { - const { input, output } = util.parseArgs({ - options: { - input: { - type: "string", - short: "i", - }, - output: { - type: "string", - short: "o", - }, - }, - }).values; - - await fs.writeFile( - output, - await postLink(await WebAssembly.compile(await fs.readFile(input))) - ); -} - -if (isMain()) { - await main(); -} diff --git a/jsbits/prelude.js b/jsbits/prelude.js deleted file mode 100644 index 9f99b83..0000000 --- a/jsbits/prelude.js +++ /dev/null @@ -1,93 +0,0 @@ -import { evalMessage } from './wasm'; - -// This file implements the JavaScript runtime logic for Haskell -// modules that use JSFFI. It is not an ESM module, but the template -// of one; the post-linker script will copy all contents into a new -// ESM module. - -// Manage a mapping from unique 32-bit ids to actual JavaScript -// values. -class JSValManager { - #lastk = 0; - #kv = new Map(); - - constructor() {} - - // Maybe just bump this.#lastk? For 64-bit ids that's sufficient, - // but better safe than sorry in the 32-bit case. - #allocKey() { - let k = this.#lastk; - while (true) { - if (!this.#kv.has(k)) { - this.#lastk = k; - return k; - } - k = (k + 1) | 0; - } - } - - newJSVal(v) { - const k = this.#allocKey(); - this.#kv.set(k, v); - return k; - } - - // A separate has() call to ensure we can store undefined as a value - // too. Also, unconditionally check this since the check is cheap - // anyway, if the check fails then there's a use-after-free to be - // fixed. - getJSVal(k) { - if (!this.#kv.has(k)) { - throw new WebAssembly.RuntimeError(`getJSVal(${k})`); - } - return this.#kv.get(k); - } - - // Check for double free as well. - freeJSVal(k) { - if (!this.#kv.delete(k)) { - throw new WebAssembly.RuntimeError(`freeJSVal(${k})`); - } - } -} - -// A simple & fast setImmediate() implementation for browsers. It's -// not a drop-in replacement for node.js setImmediate() because: -// 1. There's no clearImmediate(), and setImmediate() doesn't return -// anything -// 2. There's no guarantee that callbacks scheduled by setImmediate() -// are executed in the same order (in fact it's the opposite lol), -// but you are never supposed to rely on this assumption anyway -class SetImmediate { - #fs = []; - #mc = new MessageChannel(); - - constructor() { - this.#mc.port1.addEventListener("message", () => { - this.#fs.pop()(); - }); - this.#mc.port1.start(); - } - - setImmediate(cb, ...args) { - this.#fs.push(() => cb(...args)); - this.#mc.port2.postMessage(undefined); - } -} - -// The actual setImmediate() to be used. This is a ESM module top -// level binding and doesn't pollute the globalThis namespace. -let setImmediate; -if (globalThis.setImmediate) { - // node.js, bun - setImmediate = globalThis.setImmediate; -} else { - /* try { - * // deno - * setImmediate = (await import("node:timers")).setImmediate; - * } catch { */ - // browsers - const sm = new SetImmediate(); - setImmediate = (cb, ...args) => sm.setImmediate(cb, ...args); - /* } */ -} diff --git a/jsbits/proto.ts b/jsbits/proto.ts new file mode 100644 index 0000000..be3e6f7 --- /dev/null +++ b/jsbits/proto.ts @@ -0,0 +1,985 @@ +/** + * A recursive type representing a linked list, where `List` is + * either `null` (empty) or a `Cons` (non-empty list). + * + * @template T - The type of elements in the list. + */ +export type List = null | Cons; + +/** + * A tuple representing a non-empty list node, where the first element + * is the value (`T`), and the second is the rest of the list + * (`List`). + * + * @template T - The type of the element. + */ +export type Cons = [T, List]; + +export const VAL = 0; + +export const NEXT = 1; + +/** + * Creates a `Cons` (list node) with the given value and tail (rest of + * the list). + * + * @template T - The type of the element. + * @param {T} val - The value for the new node. + * @param {List} tail - The remaining list. + * @returns {Cons} - A new list node. + */ +export function Cons(val: T, tail: List): Cons { + return [val, tail]; +} + +/** Discriminator for `Expr` */ +export enum ExprTag { + Null, + Bool, + I8, + I16, + I32, + I64, + U8, + U16, + U32, + U64, + F32, + F64, + Str, + Arr, + Obj, + U8Arr, + + Dot, + SetProp, + Ix, + Id, + + Lam, + Arg, + Apply, + Call, + + AssignRef, + FreeRef, + Ref, + FreeScope, + + PeekStack, + PushStack, + PopStack, + + InsPop, + ElementProp, + ElementAttr, + ClassListAdd, + ClassListRemove, + InsertBrackets, + ClearBrackets, + DropBrackets, + + CreateElement, + CreateElementNS, + CreateTextNode, + UpdateTextNode, + + Eval, + TriggerEvent, + YieldResult, +} + +/** Encode `Expr` sum type as a union of disjoint n-tuples, keep in + * sync with `Expr` definition in + * https://github.com/lagunoff/clickable/blob/master/Clickable/Types.hs */ +export type Expr = + | [ExprTag.Null] + | [ExprTag.Bool, number] + | [ExprTag.I8, number] + | [ExprTag.I16, number] + | [ExprTag.I32, number] + | [ExprTag.I64, bigint] + | [ExprTag.U8, number] + | [ExprTag.U16, number] + | [ExprTag.U32, number] + | [ExprTag.U64, bigint] + | [ExprTag.F32, number] + | [ExprTag.F64, number] + | [ExprTag.Str, string] + | [ExprTag.Arr, Expr[]] + | [ExprTag.Obj, [string, Expr][]] + | [ExprTag.U8Arr, Uint8Array] + + | [ExprTag.Lam, Expr] + | [ExprTag.Arg, number] + | [ExprTag.Apply, Expr, Expr] + | [ExprTag.Call, Expr, string, Expr] + + | [ExprTag.AssignRef, number, number, Expr] + | [ExprTag.FreeRef, number, number] + | [ExprTag.Ref, number, number] + | [ExprTag.FreeScope, number] + + | [ExprTag.PeekStack, number] + | [ExprTag.PushStack, Expr] + | [ExprTag.PopStack] + + | [ExprTag.InsPop, Expr, Expr] + | [ExprTag.ElementProp, string, Expr] + | [ExprTag.ElementAttr, string, string] + | [ExprTag.ClassListAdd, string[]] + | [ExprTag.ClassListRemove, string[]] + | [ExprTag.InsertBrackets] + | [ExprTag.ClearBrackets, Expr] + | [ExprTag.DropBrackets, Expr] + + | [ExprTag.CreateElement, string] + | [ExprTag.CreateElementNS, string, string] + | [ExprTag.CreateTextNode, string] + | [ExprTag.UpdateTextNode, Expr, string] + + | [ExprTag.Eval, string] + | [ExprTag.TriggerEvent, number, Expr] + | [ExprTag.YieldResult, number] + ; + +export type Ptr = number; +export type ScopeId = number; +export type RefId = number; +export type EventId = number; + +export type EvalState = { + readonly triggerEvent: (eventId: EventId, arg: unknown) => void; + readonly resumeCont: (contId: number, res: unknown) => void; + readonly persistent: PersistentState; + readonly mem: DataView; + readonly isMutableMem: boolean; + begin: Ptr; + readonly end: Ptr; +}; + +export type PersistentState = { + readonly refs: Map>; + stack: List; +}; + +/** Evaluate sequence of `Expr` encoded as `Data.Binary.Binary` + * instance inside the memory given in `self.mem` */ +export function evalMem(self: EvalState): void { + let res = null; + for (; self.begin < self.end;) { + res = evalNext(self, null, res); + } +} + +/** Evaluate next single `Expr` relative to `self.begin` pointer */ +export function evalNext(self: EvalState, args: List = null, prevRes: unknown = null): unknown { + const tag: ExprTag = self.mem.getInt8(self.begin); + self.begin++; + + switch (tag) { + case ExprTag.Null: { + return null; + }; + case ExprTag.Bool: { + const res = self.mem.getInt8(self.begin) ? true : false; + self.begin++; + return res; + }; + + case ExprTag.I8: { + const res = self.mem.getInt8(self.begin); + self.begin++; + return res; + }; + case ExprTag.I16: { + const res = self.mem.getInt16(self.begin, false); + self.begin += 2; + return res; + }; + case ExprTag.I32: { + const res = self.mem.getInt32(self.begin, false); + self.begin += 4; + return res; + }; + case ExprTag.I64: { + const res = self.mem.getBigInt64(self.begin, false); + self.begin += 8; + return res; + }; + + case ExprTag.U8: { + const res = self.mem.getUint8(self.begin); + self.begin++; + return res; + }; + case ExprTag.U16: { + const res = self.mem.getUint16(self.begin, false); + self.begin += 2; + return res; + }; + case ExprTag.U32: { + const res = self.mem.getUint32(self.begin, false); + self.begin += 4; + return res; + }; + case ExprTag.U64: { + const res = self.mem.getBigUint64(self.begin, false); + self.begin += 8; + return res; + }; + + case ExprTag.F32: { + const res = self.mem.getFloat32(self.begin, true); + self.begin += 4; + return res; + }; + case ExprTag.F64: { + const res = self.mem.getFloat64(self.begin, true); + self.begin += 8; + return res; + }; + + case ExprTag.Str: { + return decodeString(self); + }; + case ExprTag.Arr: { + const len = Number(self.mem.getBigUint64(self.begin, false)); + const res = new Array(len).fill(undefined); + self.begin += 8; + for (let i = 0; i < len; i++) { + const val = evalNext(self, args, prevRes); + res[i] = val; + } + return res; + }; + case ExprTag.Obj: { + const len = Number(self.mem.getBigUint64(self.begin, false)); + const res: Record = {}; + self.begin += 8; + + for (let i = 0; i < len; i++) { + const key = decodeString(self); + const val = evalNext(self, args, prevRes); + + res[key] = val; + } + return res; + }; + case ExprTag.U8Arr: { + const len = Number(self.mem.getBigUint64(self.begin, false)); + self.begin += 8; + const res = new Uint8Array(self.mem.buffer).slice(self.begin, self.begin + len); + self.begin += len; + return res; + }; + + case ExprTag.Dot: { + const obj = evalNext(self, args, prevRes); + const key = decodeString(self); + return (obj as any)[key]; + }; + case ExprTag.SetProp: { + const obj = evalNext(self, args, prevRes); + const key = decodeString(self); + const val = evalNext(self, args, prevRes); + (obj as any)[key] = val; + return null; + }; + case ExprTag.Ix: { + const obj = evalNext(self, args, prevRes); + const key = self.mem.getUint32(self.begin); + self.begin += 4; + return (obj as any)[key]; + }; + case ExprTag.Id: { + const iden = decodeString(self); + return (global as any)[iden]; + }; + + case ExprTag.Lam: { + const ptrEnd = lookAheadExpr(self.mem, self.begin); + if (self.isMutableMem) { + const clonedBody = new Uint8Array(self.mem.buffer).slice(self.begin, ptrEnd); + const ctxNew: EvalState = { + ...self, + mem: new DataView(clonedBody.buffer), + isMutableMem: false, + begin: 0, + end: clonedBody.length, + }; + self.begin = ptrEnd; + return function (arg: unknown) { + ctxNew.begin = 0; + evalNext(ctxNew, Cons(arg, args)); + }; + } else { + const resetBegin = self.begin; + const ctxNew: EvalState = { + ...self, + end: ptrEnd, + }; + self.begin = ptrEnd; + return function (arg: unknown) { + ctxNew.begin = resetBegin; + evalNext(ctxNew, Cons(arg, args)); + }; + } + }; + case ExprTag.Arg: { + const argIx = self.mem.getInt8(self.begin); + self.begin += 1; + let iter = args; + let i = 0; + while (iter) { + if (i == argIx) { + return iter[VAL]; + } + iter = iter[NEXT]; + i++; + } + throw new Error("Arg: index out of argument stack"); + }; + case ExprTag.Apply: { + const fn = evalNext(self, args, prevRes); + const arg = evalNext(self, args, prevRes); + return (fn as any)(arg); + }; + case ExprTag.Call: { + const obj = evalNext(self, args, prevRes); + const key = decodeString(self); + const arg = evalNext(self, args, prevRes); + return (obj as any)[key].call(obj, arg); + }; + + case ExprTag.AssignRef: { + const scopeId = self.mem.getUint32(self.begin, false); + const refId = self.mem.getUint32(self.begin + 4, false); + self.begin += 8; + const val = evalNext(self, args, prevRes); + if (self.persistent.refs.has(scopeId)) { + const scopeMap = self.persistent.refs.get(scopeId)!; + scopeMap.set(refId, val); + } else { + const scopeMap = new Map(); + scopeMap.set(refId, val); + self.persistent.refs.set(scopeId, scopeMap); + } + return val; + }; + case ExprTag.FreeRef: { + const scopeId = self.mem.getUint32(self.begin, false); + const refId = self.mem.getUint32(self.begin + 4, false); + self.begin += 8; + const scopeMap = self.persistent.refs.get(scopeId); + if (!scopeMap) return null; + scopeMap.delete(refId); + if (scopeMap.size == 0) { + self.persistent.refs.delete(scopeId); + } + return null; + }; + case ExprTag.Ref: { + const scopeId = self.mem.getUint32(self.begin, false); + const refId = self.mem.getUint32(self.begin + 4, false); + self.begin += 8; + return self.persistent.refs.get(scopeId)?.get(refId); + }; + case ExprTag.FreeScope: { + const scopeId = self.mem.getUint32(self.begin, false); + self.begin += 4; + self.persistent.refs.delete(scopeId); + return null; + }; + + case ExprTag.PeekStack: { + const stackIx = self.mem.getInt8(self.begin); + self.begin += 1; + let iter = self.persistent.stack; + let i = 0; + while (iter) { + if (i == stackIx) { + return iter[VAL]; + } + iter = iter[NEXT]; + i++; + } + throw new Error("PeekStack: index out of stack size"); + }; + case ExprTag.PushStack: { + const val = evalNext(self, args, prevRes); + self.persistent.stack = Cons(val, self.persistent.stack); + return val; + }; + case ExprTag.PopStack: { + if (!self.persistent.stack) { + throw new Error("PopStack: empty stack"); + } + const res = self.persistent.stack[VAL]; + self.persistent.stack = self.persistent.stack[NEXT]; + return res; + }; + + case ExprTag.InsPop: { + if (!self.persistent.stack) { + throw new Error("InsPop: empty stack"); + } + const tip = self.persistent.stack[VAL] as Node; + self.persistent.stack = self.persistent.stack[NEXT]; + if (!self.persistent.stack) { + throw new Error("InsPop: empty stack"); + } + const parent = self.persistent.stack[VAL] as Element; + utils.insert(parent, tip); + return tip; + }; + case ExprTag.ElementProp: { + const el = evalNext(self, args, prevRes); + const key = decodeString(self); + const val = evalNext(self, args, prevRes); + utils.prop(el as any, key, val); + return null; + }; + case ExprTag.ElementAttr: { + const el = evalNext(self, args, prevRes); + const key = decodeString(self); + const val = decodeString(self); + utils.attr(el as any, key, val); + return null; + }; + case ExprTag.ClassListAdd: { + throw new Error("Unimplemented"); + }; + case ExprTag.ClassListRemove: { + throw new Error("Unimplemented"); + }; + case ExprTag.InsertBrackets: { + if (!self.persistent.stack) { + throw new Error("InsertBrackets: empty stack"); + } + const el = self.persistent.stack[VAL] as any; + return utils.insertBrackets(el); + }; + case ExprTag.ClearBrackets: { + const node = evalNext(self, args, prevRes); + utils.clearBrackets(node as any, false); + return null; + }; + case ExprTag.DropBrackets: { + const node = evalNext(self, args, prevRes); + utils.clearBrackets(node as any, true); + return null; + }; + case ExprTag.CreateElement: { + const tagName = decodeString(self); + return document.createElement(tagName); + }; + case ExprTag.CreateElementNS: { + const tagName = decodeString(self); + const ns = decodeString(self); + return document.createElementNS(tagName, ns); + }; + case ExprTag.CreateTextNode: { + const content = decodeString(self); + return document.createTextNode(content); + }; + case ExprTag.UpdateTextNode: { + const node = evalNext(self, args, prevRes); + const content = decodeString(self); + (node as Text).textContent = content; + return null; + }; + case ExprTag.Eval: { + const js = decodeString(self); + return eval(js); + }; + case ExprTag.TriggerEvent: { + const eventId = self.mem.getUint32(self.begin, false); + self.begin += 4; + const pload = evalNext(self, args, prevRes); + self.triggerEvent(eventId, pload); + return null; + }; + case ExprTag.YieldResult: { + const contId = self.mem.getUint32(self.begin, false); + self.begin += 4; + self.resumeCont(contId, prevRes); + return null; + }; + } +} + +/** Parse next Expr without evaluating it. This is needed to clone + * body expression of the Lam + */ +export function lookAheadExpr(mem: DataView, ptr: Ptr): Ptr { + const tag: ExprTag = mem.getInt8(ptr++); + + switch (tag) { + case ExprTag.Null: { + return ptr; + }; + case ExprTag.Bool: { + return ptr + 1; + }; + + case ExprTag.I8: { + return ptr + 1; + }; + case ExprTag.I16: { + return ptr + 2; + }; + case ExprTag.I32: { + return ptr + 4; + }; + case ExprTag.I64: { + return ptr + 8; + }; + + case ExprTag.U8: { + return ptr + 1; + }; + case ExprTag.U16: { + return ptr + 2; + }; + case ExprTag.U32: { + return ptr + 4; + }; + case ExprTag.U64: { + return ptr + 8; + }; + + case ExprTag.F32: { + return ptr + 4; + }; + case ExprTag.F64: { + return ptr + 8; + }; + + case ExprTag.Str: { + const len = Number(mem.getBigUint64(ptr, false)); + return ptr + 8 + len; + }; + // case ExprTag.Arr: { + // const len = Number(view.getBigUint64(ptr, false)); + // const result = new Array(len).fill(undefined); + // let iter = ptr + 8; + // for (let i = 0; i < len; i++) { + // const [newIter, val] = interpBytes(self, mem, iter); + // result[i] = val; + // iter = newIter; + // } + // return [iter, result]; + // }; + // case ExprTag.Obj: { + // const len = Number(view.getBigUint64(ptr, false)); + // const result: Record = {}; + // let iter = ptr + 8; + + // for (let i = 0; i < len; i++) { + // const [newIter1, key] = decodeString(self, mem, iter); + // const [newIter2, val] = interpBytes(self, mem, newIter1); + + // result[key] = val; + // iter = newIter2; + // } + // return [iter, result]; + // }; + // case ExprTag.U8Arr: { + // const len = Number(view.getBigUint64(ptr, false)); + // const res = mem.subarray(ptr + 8, ptr + 8 + len); + // return [ptr + 8 + len, res]; + // }; + + // case ExprTag.Dot: { + // const [newPtr1, obj] = interpBytes(self, mem, ptr); + // const [newPtr2, key] = decodeString(self, mem, newPtr1); + // return [newPtr2, (obj as any)[key]]; + // }; + // case ExprTag.SetProp: { + // const [newPtr1, obj] = interpBytes(self, mem, ptr); + // const [newPtr2, key] = decodeString(self, mem, newPtr1); + // const [newPtr3, val] = interpBytes(self, mem, newPtr2); + // (obj as any)[key] = val; + // return [newPtr3, null]; + // }; + // case ExprTag.Ix: { + // const [newPtr1, obj] = interpBytes(self, mem, ptr); + // const key = view.getUint32(newPtr1); + // return [newPtr1 + 4, (obj as any)[key]] + // }; + // case ExprTag.Id: { + // const [newPtr, iden] = decodeString(self, mem, ptr); + // return [newPtr, (global as any)[iden]]; + // }; + + // case ExprTag.Lam: { + // throw new Error("Unimplemented"); + // }; + // case ExprTag.Arg: { + // const _argIx = view.getUint8(ptr); + // throw new Error("Unimplemented"); + // }; + // case ExprTag.Apply: { + // const [newPtr1, fn] = interpBytes(self, mem, ptr); + // const [newPtr2, arg] = interpBytes(self, mem, newPtr1); + // return [newPtr2, (fn as any)(arg)]; + // }; + // case ExprTag.Call: { + // const [newPtr1, obj] = interpBytes(self, mem, ptr); + // const [newPtr2, key] = decodeString(self, mem, newPtr1); + // const [newPtr3, arg] = interpBytes(self, mem, newPtr2); + // return [newPtr3, (obj as any)[key].call(obj, arg)]; + // }; + + // case ExprTag.AssignRef: { + // const scopeId = view.getUint32(ptr, true); + // const refId = view.getUint32(ptr + 4, true); + // const [newPtr, val] = interpBytes(self, mem, ptr + 8); + // if (self.refs.has(scopeId)) { + // const scopeMap = self.refs.get(scopeId)!; + // scopeMap.set(refId, val); + // } else { + // const scopeMap = new Map(); + // scopeMap.set(refId, val); + // self.refs.set(scopeId, scopeMap); + // } + // return [newPtr, val]; + // }; + // case ExprTag.FreeRef: { + // const scopeId = view.getUint32(ptr, true); + // const refId = view.getUint32(ptr + 4, true); + // const scopeMap = self.refs.get(scopeId); + // if (!scopeMap) return [ptr + 8, null]; + // scopeMap.delete(refId); + // if (scopeMap.size == 0) { + // self.refs.delete(scopeId); + // } + // return [ptr + 8, null]; + // }; + // case ExprTag.Ref: { + // const scopeId = view.getUint32(ptr, true); + // const refId = view.getUint32(ptr + 4, true); + // const val = self.refs.get(scopeId)?.get(refId); + // return [ptr + 8, val]; + // }; + // case ExprTag.FreeScope: { + // const scopeId = view.getUint32(ptr, true); + // self.refs.delete(scopeId); + // return [ptr + 4, null]; + // }; + + // case ExprTag.PeekStack: { + // const stackIx = view.getInt8(ptr); + // let iter = self.stack; + // let i = 0; + // while (iter) { + // if (i == stackIx) { + // return [ptr + 1, iter[VAL]]; + // } + // iter = iter[NEXT]; + // i++; + // } + // throw new Error("PeekStack: index out of stack size"); + // }; + // case ExprTag.PushStack: { + // const [newPtr, val] = interpBytes(self, mem, ptr); + // self.stack = Cons(val, self.stack); + // return [newPtr, val]; + // }; + // case ExprTag.PopStack: { + // if (!self.stack) { + // throw new Error("PopStack: empty stack"); + // } + // const val = self.stack[VAL]; + // self.stack = self.stack[NEXT]; + // return [ptr, val]; + // }; + + // case ExprTag.InsPop: { + // if (!self.stack) { + // throw new Error("InsPop: empty stack"); + // } + // const tip = self.stack[VAL] as Node; + // self.stack = self.stack[NEXT]; + // if (!self.stack) { + // throw new Error("InsPop: empty stack"); + // } + // const parent = self.stack[VAL] as Element; + // utils.insert(parent, tip); + // return [ptr, tip]; + // }; + // case ExprTag.ElementProp: { + // const [newPtr1, el] = interpBytes(self, mem, ptr); + // const [newPtr2, key] = decodeString(self, mem, newPtr1); + // const [newPtr3, val] = interpBytes(self, mem, newPtr2); + // utils.prop(el as any, key, val); + // return [newPtr3, null]; + // }; + // case ExprTag.ElementAttr: { + // const [newPtr1, el] = interpBytes(self, mem, ptr); + // const [newPtr2, key] = decodeString(self, mem, newPtr1); + // const [newPtr3, val] = decodeString(self, mem, newPtr2); + // utils.attr(el as any, key, val); + // return [newPtr3, null]; + // }; + // case ExprTag.ClassListAdd: { + // throw new Error("Unimplemented"); + // }; + // case ExprTag.ClassListRemove: { + // throw new Error("Unimplemented"); + // }; + // case ExprTag.InsertBrackets: { + // if (!self.stack) { + // throw new Error("InsertBrackets: empty stack"); + // } + // const el = self.stack[VAL] as any; + // const node = utils.insertBrackets(el); + // return [ptr, node]; + // }; + // case ExprTag.ClearBrackets: { + // const [newPtr, node] = interpBytes(self, mem, ptr); + // utils.clearBrackets(node as any, false); + // return [newPtr, null]; + // }; + // case ExprTag.DropBrackets: { + // const [newPtr, node] = interpBytes(self, mem, ptr); + // utils.clearBrackets(node as any, true); + // return [newPtr, null]; + // }; + // case ExprTag.CreateElement: { + // const [newPtr, tagName] = decodeString(self, mem, ptr); + // const el = document.createElement(tagName); + // return [newPtr, el]; + // }; + // case ExprTag.CreateElementNS: { + // const [newPtr1, tagName] = decodeString(self, mem, ptr); + // const [newPtr2, ns] = decodeString(self, mem, newPtr1); + // const el = document.createElementNS(tagName, ns); + // return [newPtr2, el]; + // }; + // case ExprTag.CreateTextNode: { + // const [newPtr, content] = decodeString(self, mem, ptr); + // const node = document.createTextNode(content); + // return [newPtr, node]; + // }; + // case ExprTag.UpdateTextNode: { + // const [newPtr1, node] = interpBytes(self, mem, ptr); + // const [newPtr2, content] = decodeString(self, mem, newPtr1); + // (node as Text).textContent = content; + // return [newPtr2, null]; + // }; + case ExprTag.Eval: { + const len = Number(mem.getBigUint64(ptr, false)); + return ptr + 8 + len; + }; + case ExprTag.TriggerEvent: { + return lookAheadExpr(mem, ptr + 4); + }; + case ExprTag.YieldResult: { + return ptr + 4; + }; + } + throw new Error("lookAheadExpr: unimplemented"); +} + +export type EncoderState = { + readonly mem: DataView; + begin: Ptr; + readonly end: Ptr; +}; + +export function encodeValue(self: EncoderState, val: unknown): void { + if (typeof(val) === 'boolean') { + self.mem.setUint8(self.begin, ExprTag.Bool); + self.mem.setUint8(self.begin + 1, val ? 1 : 0); + self.begin += 2; + return; + } + if (typeof(val) === 'number') { + if (Number.isInteger(val)) { + self.mem.setUint8(self.begin, ExprTag.I32); + self.mem.setUint32(self.begin + 1, val, false); + self.begin += 5; + return; + } else { + self.mem.setUint8(self.begin, ExprTag.F64); + self.mem.setFloat64(self.begin + 1, val, true); + self.begin += 9; + return; + } + } + if (typeof(val) === 'string') { + self.mem.setUint8(self.begin, ExprTag.Str); + const destRange = new Uint8Array(self.mem.buffer).subarray(self.begin + 9); + const encResult = new TextEncoder().encodeInto(val, destRange) + self.mem.setBigUint64(self.begin + 1, BigInt(encResult.written), false); + self.begin += 9 + encResult.written; + return; + } + if (typeof(val) === 'bigint') { + self.mem.setUint8(self.begin, ExprTag.I64); + self.mem.setBigInt64(self.begin + 1, BigInt(val), false); + self.begin += 9; + return; + } + if (Array.isArray(val)) { + self.mem.setUint8(self.begin, ExprTag.Arr); + self.mem.setBigUint64(self.begin + 1, BigInt(val.length), false); + self.begin += 9; + val.forEach(v => encodeValue(self, v)); + return; + } + if (val instanceof Uint8Array) { + self.mem.setUint8(self.begin, ExprTag.U8Arr); + self.mem.setBigUint64(self.begin + 1, BigInt(val.byteLength), false); + new Uint8Array(self.mem.buffer).set(val, self.begin + 9); + self.begin += 9 + val.byteLength; + return; + } + if (val === null || val === undefined) { + self.mem.setUint8(self.begin, ExprTag.Null); + self.begin++; + return; + } + + const entries = Object.entries(val); + self.mem.setUint8(self.begin, ExprTag.Obj); + self.mem.setBigUint64(self.begin + 1, BigInt(entries.length), false); + self.begin += 9; + + entries.forEach(([k, v]) => { + encodeValue(self, k); + encodeValue(self, v); + }); + return; +} + +export enum ClientMsgTag { + StartMsg, + EventMsg, + ResumeMsg, +} + +export type ClientMsg = + | [ClientMsgTag.StartMsg, unknown] + | [ClientMsgTag.EventMsg, number, unknown] + | [ClientMsgTag.ResumeMsg, number, unknown] +; + +export function encodeClientMessage(self: EncoderState, val: ClientMsg) { + switch (val[0]) { + case ClientMsgTag.StartMsg: { + self.mem.setUint8(self.begin, ClientMsgTag.StartMsg); + self.begin++; + encodeValue(self, val[1]); + return; + } + case ClientMsgTag.EventMsg: { + self.mem.setUint8(self.begin, ClientMsgTag.EventMsg); + self.mem.setUint32(self.begin + 1, val[1], false); + self.begin += 5; + encodeValue(self, val[2]); + return; + } + case ClientMsgTag.ResumeMsg: { + self.mem.setUint8(self.begin, ClientMsgTag.ResumeMsg); + self.mem.setUint32(self.begin + 1, val[1], false); + self.begin += 5; + encodeValue(self, val[2]); + return; + } + } +} + +const decoder = new TextDecoder('utf8'); + +function decodeString(s: EvalState): string { + const len = Number(s.mem.getBigUint64(s.begin, false)); + s.begin += 8; + const strView = new Uint8Array(s.mem.buffer).subarray(s.begin, s.begin + len); + s.begin += len; + return decoder.decode(strView); +} + +namespace utils { + export function insert(builder: Element|Comment, child: Node): void { + if (builder instanceof Comment) { + builder.parentElement!.insertBefore(child, builder); + } else { + builder.appendChild(child); + } + } + + export function prop(parent: Element|Comment, propName: string, propValue: unknown): void { + if (parent instanceof Comment) { + (parent.parentElement as any)[propName] = propValue; + } else { + (parent as any)[propName] = propValue; + } + } + + export function attr(builder: Element|Comment, attrName: string, attrValue: string): void { + const element = getBuilderElement(builder); + element.setAttribute(attrName, attrValue); + } + + export function addEventListener(builder: Element|Comment, eventName: string, listener: EventListener): void { + const element = getBuilderElement(builder); + element.addEventListener(eventName, listener); + } + + export function removeEventListener(builder: Element|Comment, eventName: string, listener: EventListener): void { + const element = getBuilderElement(builder); + element.removeEventListener(eventName, listener); + } + + export function insertBrackets(builder: Element|Comment): Comment { + const begin = document.createComment('ContentBrackets {{'); + const end = document.createComment('}}'); + insert(builder, begin); + insert(builder, end); + return end; + } + + export function clearBrackets(bracket: Comment|Element, detach: boolean): void { + if (bracket instanceof Comment) { + let nestedCounter = 0; + for (;;){ + if (!bracket.previousSibling || + (nestedCounter == 0 && isOpenBracket(bracket.previousSibling)) + ) break; + if (isClosingBracket(bracket.previousSibling)) nestedCounter++; + else if (isOpenBracket(bracket.previousSibling)) nestedCounter--; + bracket.previousSibling!.parentNode!.removeChild(bracket.previousSibling!); + } + if (detach) { + bracket.previousSibling!.parentNode!.removeChild(bracket.previousSibling!); + bracket.parentNode!.removeChild(bracket); + } + } else { + bracket.innerHTML = ''; + } + } + + export function getBuilderElement(builder: Element|Comment): Element { + if (builder instanceof Comment) { + return builder.parentElement!; + } + return builder; + } + + function isOpenBracket(node: Node): boolean { + if (node instanceof Comment && node.textContent == 'ContentBrackets {{') { + return true; + } + return false; + } + + function isClosingBracket(node: Node): boolean { + if (node instanceof Comment && node.textContent == '}}') { + return true; + } + return false; + } +}; diff --git a/jsbits/protocol.ts b/jsbits/protocol.ts deleted file mode 100644 index 1e0c5d8..0000000 --- a/jsbits/protocol.ts +++ /dev/null @@ -1,774 +0,0 @@ -import * as b from './binary'; -import { absurd, IntMap } from './lib'; - -export type JSFunctionName = string; - -export type Ident = string; - -export type Bindings = Record; - -export type List = null | Cons; - -export type Cons = { 0: T, 1: List }; - -export function Cons(x: T, xs: List): List { - return [x, xs]; -} - -export function car(pair: Cons): T { - return pair[0]; -} - -export function cdr(pair: Cons): List { - return pair[1]; -} - -export type ClickablePublic = { - startWasm(wasmUri: string, startFlags?: unknown): void; - startDev(devSocketUri: string, startFlags?: unknown): void; - evalExpr(exp: Expr, options?: EvalOptions): unknown; - evalUint8Array(exp: Uint8Array, options?: EvalOptions): unknown; -}; - -export type HaskellCallback = (jsMsg: JavaScriptMessage, argScope: List) => void; - -export type EvalOptions = { - haskellCallback?: HaskellCallback; - idenScope?: List; - argScope?: List; - builderScope?: List; -}; - -export function evalExpr(exp: Expr, options: EvalOptions = {}): unknown { - const haskellCallback = options.haskellCallback || (() => {}); - const idenScope = options.idenScope || globalContext; - const argScope = options.argScope || null; - const builderScope = options.builderScope || null; - return evalLoop(haskellCallback, idenScope, argScope, builderScope, exp); -} - -export function evalUint8Array(exp: Uint8Array, options: EvalOptions = {}): unknown { - const decoded: Expr = expr.decode(exp); - return evalExpr(decoded, options); -} - -export function evalLoop ( - hscb: HaskellCallback, - idenScope: List, - argScope: List, - builderScope: List, - exp: Expr -): unknown { - switch(exp.tag) { - case ExprTag.Null: { - return null; - } - case ExprTag.Boolean: { - return exp[0] != 0; - } - case ExprTag.I8: { - return exp[0]; - } - case ExprTag.I16: { - return exp[0]; - } - case ExprTag.I32: { - return exp[0]; - } - case ExprTag.I64: { - return exp[0]; - } - case ExprTag.U8: { - return exp[0]; - } - case ExprTag.U16: { - return exp[0]; - } - case ExprTag.U32: { - return exp[0]; - } - case ExprTag.U64: { - return exp[0]; - } - case ExprTag.F32: { - return exp[0]; - } - case ExprTag.F64: { - return exp[0]; - } - case ExprTag.Str: { - return exp[0]; - } - case ExprTag.Arr: { - return exp[0].map(evalLoop.bind(undefined, hscb, idenScope, argScope, builderScope)); - } - case ExprTag.Obj: { - return Object.fromEntries(exp[0].map(([k, e]) => [k, evalLoop(hscb, idenScope, argScope, builderScope, e)])); - } - case ExprTag.U8Arr: { - return exp[0]; - } - case ExprTag.Dot: { - const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as any; - return lhs[exp[1]]; - } - case ExprTag.SetProp: { - const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[2]); - const obj = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as any; - obj[exp[1]] = rhs; - return rhs; - } - case ExprTag.Ix: { - const rhs: any = evalLoop(hscb, idenScope, argScope, builderScope, exp.exp); - return rhs[exp.ix]; - } - case ExprTag.Plus: { - const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as number; - const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[1]) as number; - return lhs + rhs; - } - case ExprTag.Subtract: { - const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as number; - const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[1]) as number; - return lhs - rhs; - } - case ExprTag.Multiply: { - const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as number; - const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[1]) as number; - return lhs * rhs; - } - case ExprTag.Divide: { - const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as number; - const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[1]) as number; - return lhs / rhs; - } - case ExprTag.Id: { - const ident = exp[0]; - for (let iter = idenScope; iter; iter = cdr(iter)) { - const bindings = car(iter); - if (ident in bindings) { - // Found bound value - return bindings[ident]; - } - } - throw new Error('Variable not in scope: ' + exp[0]); - } - case ExprTag.Lam: { - return function() { - return evalLoop(hscb, idenScope, Cons(arguments, argScope), builderScope, exp.body); - }; - } - case ExprTag.Arg: { - let iter = argScope; - let j = 0; - while (iter) { - if (j == exp.scopeIx) { - const iarguments = car(iter); - return iarguments[exp.argIx]; - } - iter = cdr(iter); - j++; - } - throw new Error('Argument scope out of a range: ' + exp.scopeIx); - } - case ExprTag.Apply: { - const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as Function; - return lhs.apply(undefined, exp[1].map(evalLoop.bind(undefined, hscb, idenScope, argScope, builderScope))); - } - case ExprTag.Call: { - const lhs = evalLoop(hscb, idenScope, argScope, builderScope, exp[0]) as any; - const fn = lhs[exp[1]]; - return fn.apply(lhs, exp[2].map(evalLoop.bind(undefined, hscb, idenScope, argScope, builderScope))); - } - case ExprTag.AssignVar: { - const rhs = evalLoop(hscb, idenScope, argScope, builderScope, exp.rhs); - if (varStorage.has(exp.scopeId)) { - const scopeMap = varStorage.get(exp.scopeId)!; - scopeMap.set(exp.varId, rhs); - } else { - const scopeMap = new Map(); - scopeMap.set(exp.varId, rhs); - varStorage.set(exp.scopeId, scopeMap); - } - return rhs; - } - case ExprTag.FreeVar: { - const scopeStorage = varStorage.get(exp.scopeId); - if (!scopeStorage) return null; - scopeStorage.delete(exp.varId); - if (scopeStorage.size == 0) { - varStorage.delete(exp.scopeId); - } - return null; - } - case ExprTag.Var: { - return varStorage.get(exp.scopeId)?.get(exp.varId); - } - case ExprTag.FreeScope: { - varStorage.delete(exp.scopeId); - const scopeFinalizers = finalizers.get(exp.scopeId); - finalizers.delete(exp.scopeId); - if (scopeFinalizers) scopeFinalizers.forEach(fn => fn ()); - return null; - } - case ExprTag.AskDomBuilder: { - if (builderScope == null) { - throw new Error('AskDomBuilder called without prior SupplyDomBuilder!'); - } - return builderScope[0]; - } - case ExprTag.SupplyDomBuilder: { - const builder = evalLoop(hscb, idenScope, argScope, builderScope, exp.builder) as Element|Comment; - const newBuilderScope = Cons(builder, builderScope); - return evalLoop(hscb, idenScope, argScope, newBuilderScope, exp.expr) - } - case ExprTag.InsertNode: { - if (builderScope == null) { - throw new Error('InsertNode called without prior SupplyDomBuilder!'); - } - const child = evalLoop(hscb, idenScope, argScope, builderScope, exp.child) as Node; - domHelpers.insertIntoBuilder(builderScope[0], child); - return null; - } - case ExprTag.ElementProp: { - if (builderScope == null) { - throw new Error('ElementProp called without prior SupplyDomBuilder!'); - } - const propValue = evalLoop(hscb, idenScope, argScope, builderScope, exp.propValue); - domHelpers.assignProperty(builderScope[0], exp.propName, propValue); - return null; - } - case ExprTag.ElementAttr: { - if (builderScope == null) { - throw new Error('ElementAttr called without prior SupplyDomBuilder!'); - } - domHelpers.assignAttribute(builderScope[0], exp.attrName, exp.attrValue); - return null; - } - case ExprTag.ClassListAdd: { - if (builderScope == null) { - throw new Error('InsertClassList called without prior SupplyDomBuilder!'); - } - const element = domHelpers.domBuilderElement(builderScope[0]); - exp.classList.forEach(className => element.classList.add(className)); - return null; - } - case ExprTag.ClassListRemove: { - if (builderScope == null) { - throw new Error('RemoveClassList called without prior SupplyDomBuilder!'); - } - const element = domHelpers.domBuilderElement(builderScope[0]); - exp.classList.forEach(className => element.classList.remove(className)); - return null; - } - case ExprTag.InsertBrackets: { - if (builderScope == null) { - throw new Error('InsertBoundary called without prior SupplyDomBuilder!'); - } - return domHelpers.insertBrackets(builderScope[0]); - } - case ExprTag.ClearBrackets: { - if (builderScope == null) { - throw new Error('InsertBoundary called without prior SupplyDomBuilder!'); - } - return domHelpers.clearBrackets(builderScope[0], Boolean(exp.detach)); - } - - case ExprTag.CreateElement: { - return document.createElement(exp.tagName); - } - case ExprTag.CreateElementNS: { - return document.createElementNS(exp.ns, exp.tagName); - } - case ExprTag.CreateTextNode: { - return document.createTextNode(exp.content); - } - case ExprTag.UpdateTextNode: { - const node = evalLoop(hscb, idenScope, argScope, builderScope, exp.node) as Text; - node.textContent = exp.content; - return null; - } - - case ExprTag.AddEventListener: { - const target = evalLoop(hscb, idenScope, argScope, builderScope, exp.target) as Element|Comment; - const eventName = evalLoop(hscb, idenScope, argScope, builderScope, exp.eventName) as string; - const listener = evalLoop(hscb, idenScope, argScope, builderScope, exp.listener) as EventListener; - domHelpers.addEventListener(target, eventName, listener); - const existingScope = finalizers.get(exp.reactiveScope); - const scopeFinalizers = existingScope ? existingScope : new IntMap(); - if (!existingScope) finalizers.set(exp.reactiveScope, scopeFinalizers); - return scopeFinalizers.push(() => domHelpers.removeEventListener(target, eventName, listener)); - } - case ExprTag.ConnectResource: { - const finalizer = evalLoop(hscb, idenScope, argScope, builderScope, exp.aquire) as Function; - const existingScope = finalizers.get(exp.reactiveScope); - const scopeFinalizers = existingScope ? existingScope : new IntMap(); - if (!existingScope) finalizers.set(exp.reactiveScope, scopeFinalizers); - return scopeFinalizers.push(finalizer); - } - case ExprTag.SetTimeout: { - const callback = evalLoop(hscb, idenScope, argScope, builderScope, exp.callback) as Function; - const existingScope = finalizers.get(exp.reactiveScope); - const scopeFinalizers = existingScope ? existingScope : new IntMap(); - if (!existingScope) finalizers.set(exp.reactiveScope, scopeFinalizers); - let timeoutId: NodeJS.Timeout|null = null; - const finalizerId = scopeFinalizers.push(() => timeoutId && clearTimeout(timeoutId)); - timeoutId = setTimeout(() => { - scopeFinalizers.delete(finalizerId); - timeoutId = null; - callback(); - }, exp.timeout); - return finalizerId; - } - case ExprTag.ApplyFinalizer: { - const existingScope = finalizers.get(exp.reactiveScope); - const finalizerId = evalLoop(hscb, idenScope, argScope, builderScope, exp.finalizerId) as number; - if (!existingScope) return false; - const cancellerFn = existingScope.get(finalizerId); - if (!cancellerFn) return false; - existingScope.delete(finalizerId); - cancellerFn(); - return true; - } - case ExprTag.RevSeq: { - return exp.exprs.reduceRight((_, e) => evalLoop(hscb, idenScope, argScope, builderScope, e), null); - } - case ExprTag.Eval: { - return eval(exp.rawJavaScript); - } - case ExprTag.TriggerEvent: { - const arg = evalLoop(hscb, idenScope, argScope, builderScope, exp.arg); - const jsMsg: JavaScriptMessage = { - tag: JavaScriptMessageTag.TriggerEventMsg, - arg: unknownToValue(arg), - callbackId: exp.callbackId, - } - return hscb(jsMsg, argScope); - } - case ExprTag.UncaughtException: { - throw new Error(exp.message); - } - } - absurd(exp); -} - -export function unknownToValue(inp: unknown): Value { - if (typeof(inp) === 'boolean') { - return { tag: ValueTag.Vbool, 0: inp ? 1 : 0 }; - } - if (typeof(inp) === 'number') { - if (Number.isInteger(inp)) { - return { tag: ValueTag.Vi32, 0: inp }; - } else { - return { tag: ValueTag.Vf64, 0: inp }; - } - } - if (typeof(inp) === 'string') { - return { tag: ValueTag.Vstr, 0: inp }; - } - if (typeof(inp) === 'bigint') { - return { tag: ValueTag.Vi64, 0: inp }; - } - if (Array.isArray(inp)) { - return { tag: ValueTag.Varr, 0: inp.map(unknownToValue) }; - } - if (inp instanceof Uint8Array) { - return { tag: ValueTag.Vu8arr, 0: inp }; - } - if (inp === null || inp === undefined) { - return { tag: ValueTag.Vnull }; - } - const entries = Object.entries(inp) - .map(([k, v]) => [k, unknownToValue(v)] as KV); - - return { tag: ValueTag.Vobj, 0: entries } - - type KV = [string, Value]; -} - -export enum ValueTag { - Vnull, - Vbool, - Vi8, - Vi16, - Vi32, - Vi64, - Vu8, - Vu16, - Vu32, - Vu64, - Vf32, - Vf64, - Vstr, - Varr, - Vobj, - Vu8arr, -} - -export type Value = - | { tag: ValueTag.Vnull } - | { tag: ValueTag.Vbool, 0: number } - | { tag: ValueTag.Vi8, 0: number } - | { tag: ValueTag.Vi16, 0: number } - | { tag: ValueTag.Vi32, 0: number } - | { tag: ValueTag.Vi64, 0: bigint } - | { tag: ValueTag.Vu8, 0: number } - | { tag: ValueTag.Vu16, 0: number } - | { tag: ValueTag.Vu32, 0: number } - | { tag: ValueTag.Vu64, 0: bigint } - | { tag: ValueTag.Vf32, 0: number } - | { tag: ValueTag.Vf64, 0: number } - | { tag: ValueTag.Vstr, 0: string } - | { tag: ValueTag.Varr, 0: Value[] } - | { tag: ValueTag.Vobj, 0: [string, Value][] } - | { tag: ValueTag.Vu8arr, 0: Uint8Array } -; - -export const jvalue = b.recursive(self => b.discriminate({ - [ValueTag.Vnull]: b.record({ }), - [ValueTag.Vbool]: b.record({ 0: b.int8 }), - - [ValueTag.Vi8]: b.record({ 0: b.int8 }), - [ValueTag.Vi16]: b.record({ 0: b.int16 }), - [ValueTag.Vi32]: b.record({ 0: b.int32 }), - [ValueTag.Vi64]: b.record({ 0: b.int64 }), - - [ValueTag.Vu8]: b.record({ 0: b.word8 }), - [ValueTag.Vu16]: b.record({ 0: b.word16 }), - [ValueTag.Vu32]: b.record({ 0: b.word32 }), - [ValueTag.Vu64]: b.record({ 0: b.word64 }), - - [ValueTag.Vf32]: b.record({ 0: b.float32 }), - [ValueTag.Vf64]: b.record({ 0: b.float64 }), - - [ValueTag.Vstr]: b.record({ 0: b.string }), - [ValueTag.Varr]: b.record({ 0: b.array(self) }), - [ValueTag.Vobj]: b.record({ 0: b.array(b.tuple(b.string, self)) }), - [ValueTag.Vu8arr]: b.record({ 0: b.u8array }), -})); - -export enum ExprTag { - Null, - Boolean, - - I8, - I16, - I32, - I64, - - U8, - U16, - U32, - U64, - - F32, - F64, - - Str, - Arr, - Obj, - U8Arr, - - Dot, - SetProp, - Ix, - - Plus, - Subtract, - Multiply, - Divide, - - Id, - Lam, - Arg, - Apply, - Call, - - AssignVar, - FreeVar, - Var, - FreeScope, - - AskDomBuilder, - SupplyDomBuilder, - - InsertNode, - ElementProp, - ElementAttr, - ClassListAdd, - ClassListRemove, - InsertBrackets, - ClearBrackets, - - CreateElement, - CreateElementNS, - CreateTextNode, - UpdateTextNode, - - AddEventListener, - ConnectResource, - SetTimeout, - ApplyFinalizer, - - RevSeq, - Eval, - TriggerEvent, - UncaughtException, -} - -export type Expr = - | { tag: ExprTag.Null } - | { tag: ExprTag.Boolean, 0: number } - - | { tag: ExprTag.I8, 0: number } - | { tag: ExprTag.I16, 0: number } - | { tag: ExprTag.I32, 0: number } - | { tag: ExprTag.I64, 0: bigint } - - | { tag: ExprTag.U8, 0: number } - | { tag: ExprTag.U16, 0: number } - | { tag: ExprTag.U32, 0: number } - | { tag: ExprTag.U64, 0: bigint } - - | { tag: ExprTag.F32, 0: number } - | { tag: ExprTag.F64, 0: number } - - | { tag: ExprTag.Str, 0: string } - | { tag: ExprTag.Arr, 0: Expr[] } - | { tag: ExprTag.Obj, 0: [string, Expr][] } - | { tag: ExprTag.U8Arr, 0: Uint8Array } - - | { tag: ExprTag.Dot, 0: Expr, 1: string } - | { tag: ExprTag.SetProp, 0: Expr, 1: string, 2: Expr } - | { tag: ExprTag.Ix, exp: Expr, ix: number } - - | { tag: ExprTag.Plus, 0: Expr, 1: Expr } - | { tag: ExprTag.Subtract, 0: Expr, 1: Expr } - | { tag: ExprTag.Multiply, 0: Expr, 1: Expr } - | { tag: ExprTag.Divide, 0: Expr, 1: Expr } - - | { tag: ExprTag.Id, 0: string } - | { tag: ExprTag.Lam, body: Expr } - | { tag: ExprTag.Arg, scopeIx: number, argIx: number } - | { tag: ExprTag.Apply, 0: Expr, 1: Expr[] } - | { tag: ExprTag.Call, 0: Expr, 1: JSFunctionName, 2: Expr[] } - - | { tag: ExprTag.AssignVar, scopeId: number, varId: number, rhs: Expr } - | { tag: ExprTag.FreeVar, scopeId: number, varId: number } - | { tag: ExprTag.Var, scopeId: number, varId: number } - | { tag: ExprTag.FreeScope, scopeId: number } - - | { tag: ExprTag.AskDomBuilder } - | { tag: ExprTag.SupplyDomBuilder, builder: Expr, expr: Expr } - - | { tag: ExprTag.InsertNode, child: Expr } - | { tag: ExprTag.ElementProp, propName: string, propValue: Expr } - | { tag: ExprTag.ElementAttr, attrName: string, attrValue: string } - | { tag: ExprTag.ClassListAdd, classList: string[] } - | { tag: ExprTag.ClassListRemove, classList: string[] } - | { tag: ExprTag.InsertBrackets } - | { tag: ExprTag.ClearBrackets, detach: number } - - | { tag: ExprTag.CreateElement, tagName: string } - | { tag: ExprTag.CreateElementNS, ns: string, tagName: string } - | { tag: ExprTag.CreateTextNode, content: string } - | { tag: ExprTag.UpdateTextNode, node: Expr, content: string } - - | { tag: ExprTag.AddEventListener, reactiveScope: number, target: Expr, eventName: Expr, listener: Expr } - | { tag: ExprTag.ConnectResource, reactiveScope: number, aquire: Expr } - | { tag: ExprTag.SetTimeout, reactiveScope: number, callback: Expr, timeout: number } - | { tag: ExprTag.ApplyFinalizer, reactiveScope: number, finalizerId: Expr } - - | { tag: ExprTag.RevSeq, exprs: Expr[] } - | { tag: ExprTag.Eval, rawJavaScript: string } - | { tag: ExprTag.TriggerEvent, callbackId: number, arg: Expr } - | { tag: ExprTag.UncaughtException, message: string } -; - -export const expr = b.recursive(self => b.discriminate({ - [ExprTag.Null]: b.record({}), - [ExprTag.Boolean]: b.record({ 0: b.int8 }), - - [ExprTag.I8]: b.record({ 0: b.int8 }), - [ExprTag.I16]: b.record({ 0: b.int16 }), - [ExprTag.I32]: b.record({ 0: b.int32 }), - [ExprTag.I64]: b.record({ 0: b.int64 }), - - [ExprTag.U8]: b.record({ 0: b.word8 }), - [ExprTag.U16]: b.record({ 0: b.word16 }), - [ExprTag.U32]: b.record({ 0: b.word32 }), - [ExprTag.U64]: b.record({ 0: b.word64 }), - - [ExprTag.F32]: b.record({ 0: b.float32 }), - [ExprTag.F64]: b.record({ 0: b.float64 }), - - [ExprTag.Str]: b.record({ 0: b.string }), - [ExprTag.Arr]: b.record({ 0: b.array(self) }), - [ExprTag.Obj]: b.record({ 0: b.array(b.tuple(b.string, self)) }), - [ExprTag.U8Arr]: b.record({ 0: b.u8array }), - - [ExprTag.Dot]: b.record({ 0: self, 1: b.string }), - [ExprTag.SetProp]: b.record({ 0: self, 1: b.string, 2: self }), - [ExprTag.Ix]: b.record({ exp: self, ix: b.int32 }), - - [ExprTag.Plus]: b.record({ 0: self, 1: self }), - [ExprTag.Subtract]: b.record({ 0: self, 1: self }), - [ExprTag.Multiply]: b.record({ 0: self, 1: self }), - [ExprTag.Divide]: b.record({ 0: self, 1: self }), - - [ExprTag.Id]: b.record({ 0: b.string }), - [ExprTag.Lam]: b.record({ body: self }), - [ExprTag.Arg]: b.record({ scopeIx: b.int8, argIx: b.int8 }), - [ExprTag.Apply]: b.record({ 0: self, 1: b.array(self) }), - [ExprTag.Call]: b.record({ 0: self, 1: b.string, 2: b.array(self) }), - - [ExprTag.AssignVar]: b.record({ scopeId: b.int32, varId: b.int32, rhs: self }), - [ExprTag.FreeVar]: b.record({ scopeId: b.int32, varId: b.int32 }), - [ExprTag.Var]: b.record({ scopeId: b.int32, varId: b.int32 }), - [ExprTag.FreeScope]: b.record({ scopeId: b.int32 }), - - [ExprTag.AskDomBuilder]: b.record({ }), - [ExprTag.SupplyDomBuilder]: b.record({ builder: self, expr: self }), - - [ExprTag.InsertNode]: b.record({ child: self }), - [ExprTag.ElementProp]: b.record({ propName: b.string, propValue: self }), - [ExprTag.ElementAttr]: b.record({ attrName: b.string, attrValue: b.string }), - [ExprTag.ClassListAdd]: b.record({ classList: b.array(b.string) }), - [ExprTag.ClassListRemove]: b.record({ classList: b.array(b.string) }), - [ExprTag.InsertBrackets]: b.record({ }), - [ExprTag.ClearBrackets]: b.record({ detach: b.int8 }), - - [ExprTag.CreateElement]: b.record({ tagName: b.string }), - [ExprTag.CreateElementNS]: b.record({ ns: b.string, tagName: b.string }), - [ExprTag.CreateTextNode]: b.record({ content: b.string }), - [ExprTag.UpdateTextNode]: b.record({ node: self, content: b.string }), - - [ExprTag.AddEventListener]: b.record({ reactiveScope: b.int32, target: self, eventName: self, listener: self }), - [ExprTag.ConnectResource]: b.record({ reactiveScope: b.int32, aquire: self }), - [ExprTag.SetTimeout]: b.record({ reactiveScope: b.int32, callback: self, timeout: b.int32 }), - [ExprTag.ApplyFinalizer]: b.record({ reactiveScope: b.int32, finalizerId: self }), - - [ExprTag.RevSeq]: b.record({ exprs: b.array(self) }), - [ExprTag.Eval]: b.record({ rawJavaScript: b.string }), - [ExprTag.TriggerEvent]: b.record({ callbackId: b.int32, arg: self }), - [ExprTag.UncaughtException]: b.record({ message: b.string }), -})); - -export enum HaskellMessageTag { - EvalExpr, - HotReload, - Halt, -} - -export const haskellMessage = b.discriminate({ - [HaskellMessageTag.EvalExpr]: b.record({ threadId: b.int32, expr: expr }), - [HaskellMessageTag.HotReload]: b.record({ }), - [HaskellMessageTag.Halt]: b.record({ }), -}); - -export enum JavaScriptMessageTag { - Start, - Return, - TriggerEventMsg, - BeforeUnload, -} - -export const javascriptMessage = b.discriminate({ - [JavaScriptMessageTag.Start]: b.record({ 0: jvalue }), - [JavaScriptMessageTag.Return]: b.record({ threadId: b.int32, value: jvalue }), - [JavaScriptMessageTag.TriggerEventMsg]: b.record({ arg: jvalue, callbackId: b.int32 }), - [JavaScriptMessageTag.BeforeUnload]: b.record({}), -}); - -export type HaskellMessage = typeof haskellMessage['_A']; -export type JavaScriptMessage = typeof javascriptMessage['_A']; - -export type ResourceScope = number; -export type VarId = number; - -export const varStorage = new Map>(); -export const finalizers = new Map>; - -export const globalContext: List = [window as any, null] - -namespace domHelpers { - export function insertIntoBuilder(builder: Element|Comment, child: Node): void { - if (builder instanceof Comment) { - builder.parentElement!.insertBefore(child, builder); - } else { - builder.appendChild(child); - } - } - - export function assignProperty(parent: Element|Comment, propName: string, propValue: unknown): void { - if (parent instanceof Comment) { - (parent.parentElement as any)[propName] = propValue; - } else { - (parent as any)[propName] = propValue; - } - } - - export function assignAttribute(builder: Element|Comment, attrName: string, attrValue: string): void { - const element = domBuilderElement(builder); - element.setAttribute(attrName, attrValue); - } - - export function addEventListener(builder: Element|Comment, eventName: string, listener: EventListener): void { - const element = domBuilderElement(builder); - element.addEventListener(eventName, listener); - } - - export function removeEventListener(builder: Element|Comment, eventName: string, listener: EventListener): void { - const element = domBuilderElement(builder); - element.removeEventListener(eventName, listener); - } - - export function insertBrackets(builder: Element|Comment): Comment { - const begin = document.createComment('ContentBrackets {{'); - const end = document.createComment('}}'); - insertIntoBuilder(builder, begin); - insertIntoBuilder(builder, end); - return end; - } - - export function clearBrackets(bracket: Comment|Element, detach: boolean): void { - if (bracket instanceof Comment) { - let nestedCounter = 0; - for (;;){ - if (!bracket.previousSibling || - (nestedCounter == 0 && isOpenBracket(bracket.previousSibling)) - ) break; - if (isClosingBracket(bracket.previousSibling)) nestedCounter++; - else if (isOpenBracket(bracket.previousSibling)) nestedCounter--; - bracket.previousSibling!.parentNode!.removeChild(bracket.previousSibling!); - } - if (detach) { - bracket.previousSibling!.parentNode!.removeChild(bracket.previousSibling!); - bracket.parentNode!.removeChild(bracket); - } - } else { - bracket.innerHTML = ''; - } - } - - export function domBuilderElement(builder: Element|Comment): Element { - if (builder instanceof Comment) { - return builder.parentElement!; - } - return builder; - } - - function isOpenBracket(node: Node): boolean { - if (node instanceof Comment && node.textContent == 'ContentBrackets {{') { - return true; - } - return false; - } - - function isClosingBracket(node: Node): boolean { - if (node instanceof Comment && node.textContent == '}}') { - return true; - } - return false; - } -}; diff --git a/jsbits/wasm.ts b/jsbits/wasm.ts index 07707a9..61b660f 100644 --- a/jsbits/wasm.ts +++ b/jsbits/wasm.ts @@ -1,103 +1,66 @@ import { WASI, File, OpenFile } from '@bjorn3/browser_wasi_shim'; -// @ts-ignore -import * as jsffi from './jsffi'; -import * as p from './protocol'; -import { JavaScriptMessage, HaskellMessageTag, JavaScriptMessageTag } from './protocol'; +import { ClientMsgTag, EventId, EvalState, PersistentState, Ptr } from "./proto"; +import * as proto from "./proto"; -export type HaskellPointer = number; +let inst: WebAssembly.Instance; -export type HaskellExports = { - hs_init: () => void; - wasm_app: (flags: HaskellPointer) => void; - malloc: (size: number) => HaskellPointer; - memory: WebAssembly.Memory; -}; - -export function loadBuffer(exports: HaskellExports, ptr: HaskellPointer): Uint8Array { - const b = new Uint8Array(exports.memory.buffer, ptr); - const len = b[0] + - (b[1] << 8) + - (b[2] << 16) + - (b[3] << 24) + - (b[4] << 32) + - (b[5] << 40) + - (b[6] << 48) + - (b[7] << 56); - const buf = (new Uint8Array(exports.memory.buffer, ptr + 8, len)).slice().buffer; - return new Uint8Array(buf); -} - -export function storeBuffer(exports: HaskellExports, u8array: Uint8Array): HaskellPointer { - const len = u8array.byteLength; - const ptr = exports.malloc(u8array.length + 8); - // Write the length of the buffer as 8 bytes before the buffer - const view = new DataView(exports.memory.buffer); - view.setUint32(ptr, len, true); - - // Copy the buffer into WebAssembly memory - const dest = new Uint8Array(exports.memory.buffer, ptr + 8, len); - dest.set(u8array); - return ptr; -} - -export function evalMessage(exports: HaskellExports, ptr: HaskellPointer): HaskellPointer { - const inbuf = loadBuffer(exports, ptr); - const hmsg = p.haskellMessage.decode(inbuf); - const haskellCallback = (jsmsg: JavaScriptMessage) => { - const outbuf = p.javascriptMessage.encode(jsmsg); - const ptr = storeBuffer(exports, outbuf); - exports.wasm_app(ptr); - }; - switch (hmsg.tag) { - case HaskellMessageTag.EvalExpr: { - const result = p.evalExpr(hmsg.expr, { haskellCallback }); - const jsmsg: JavaScriptMessage = { tag: JavaScriptMessageTag.Return, value: p.unknownToValue(result), threadId: hmsg.threadId }; - const outbuf = p.javascriptMessage.encode(jsmsg); - return storeBuffer(exports, outbuf); - } - case HaskellMessageTag.HotReload: { - window.location.reload(); - return 0; - } - case HaskellMessageTag.Halt: { - return 0; - } - } -} - -let __exports: HaskellExports = {} as any; - -export async function startWasm(wasmUri: string, startFlags: unknown = null) { +export function runWasm(wasmUri: string, startFlags: unknown = null) { const wasi = new WASI([], [], [ new OpenFile(new File([])), // stdin new OpenFile(new File([])), // stdout new OpenFile(new File([])), // stderr ]); - const wasm = await WebAssembly.compileStreaming(fetch(wasmUri)); - const inst = await WebAssembly.instantiate(wasm, { - wasi_snapshot_preview1: wasi.wasiImport, - ghc_wasm_jsffi: jsffi.default(__exports) - }); + const persistent: PersistentState = { + refs: new Map(), + stack: null, + }; + + function clickable_eval_buffer(ptr: Ptr, len: number): void { + // @ts-ignore + const mem = new DataView(inst.exports.memory.buffer); + + function triggerEvent(eventId: EventId, arg: unknown) { + const encoderState = {mem, begin: ptr, end: ptr + len}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.EventMsg, eventId, arg]); + // @ts-ignore + inst.exports.wasm_app(ptr); + }; - Object.assign(__exports, inst.exports); - // @ts-ignore - wasi.initialize(inst); - // @ts-ignore - await inst.exports.hs_init(); + function resumeCont(contId: number, res: unknown) { + const encoderState = {mem, begin: ptr, end: ptr + len}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.ResumeMsg, contId, res]); + // @ts-ignore + inst.exports.wasm_app(ptr); + }; - const startFlagsValue = p.unknownToValue(startFlags); - const startFlagsMessage: JavaScriptMessage = { tag: JavaScriptMessageTag.Start, 0: startFlagsValue }; - const startFlagsBuffer = p.javascriptMessage.encode(startFlagsMessage); - const startFlagsPtr = storeBuffer(__exports, startFlagsBuffer); + const intp: EvalState = { + triggerEvent, + resumeCont, + persistent, + mem, + isMutableMem: true, + begin: ptr, + end: ptr + len, + }; - // @ts-ignore - await inst.exports.wasm_app(startFlagsPtr); + proto.evalRange(intp); + } - window.addEventListener("beforeunload", () => { - const unloadMessage: JavaScriptMessage = { tag: JavaScriptMessageTag.BeforeUnload }; - const unloadBuffer = p.javascriptMessage.encode(unloadMessage); - const unloadPtr = storeBuffer(__exports, unloadBuffer); - __exports.wasm_app(unloadPtr); - }); + WebAssembly.compileStreaming(fetch(wasmUri)) + .then(wasm => WebAssembly.instantiate(wasm, { + wasi_snapshot_preview1: wasi.wasiImport, + env: { + clickable_eval_buffer, + }, + })) + .then(inst1 => { + inst = inst1; + // @ts-ignore + wasi.initialize(inst1); + // @ts-ignore + inst1.exports.hs_init(); + // @ts-ignore + inst1.exports.wasm_app(0); + }); }; diff --git a/jsbits/websocket.ts b/jsbits/websocket.ts new file mode 100644 index 0000000..47cdab1 --- /dev/null +++ b/jsbits/websocket.ts @@ -0,0 +1,82 @@ +import { ClientMsgTag, EventId, EvalState, PersistentState, Ptr } from "./proto"; +import * as proto from "./proto"; + +const outBuf = new ArrayBuffer(100 * 1024); +const mem = new DataView(outBuf); + +export function runWebsocket(devSocketUri: string, startFlags: unknown = null) { + const websocket = new WebSocket(devSocketUri); + const persistent: PersistentState = { + refs: new Map(), + stack: null, + }; + + function triggerEvent(eventId: EventId, arg: unknown) { + const encoderState = {mem, begin: 0, end: outBuf.byteLength}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.EventMsg, eventId, arg]); + websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); + }; + + function resumeCont(contId: number, res: unknown) { + const encoderState = {mem, begin: 0, end: outBuf.byteLength}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.ResumeMsg, contId, res]); + websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); + }; + + websocket.onopen = (_event) => { + const encoderState = {mem, begin: 0, end: outBuf.byteLength}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.StartMsg, startFlags]); + websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); + }; + + // Event handler for receiving messages from the server + websocket.onmessage = (event) => { + convertBlobToUint8Array(event.data).then(buf => { + proto.evalRange({ + triggerEvent, + resumeCont, + persistent, + mem: new DataView(buf), + isMutableMem: false, + begin: 0, + end: buf.byteLength, + }); + }); + }; + + // Event handler for errors + websocket.onerror = (event) => { + console.error("WebSocket error:", event); + }; + + // Event handler for when the connection is closed + websocket.onclose = (_event) => { + console.log("WebSocket connection closed, reloading the tab…"); + + function backoffLoop(timeout: number) { + // Assuming the server went down because it was re-compiled, wait + // until it comes back and reload the tab + const websocketTest = new WebSocket(devSocketUri); + const nextTimeout = Math.min(30_000, timeout * 2); + websocketTest.onopen = (_event) => window.location.reload(); + websocketTest.onclose = (_event) => { setTimeout(() => backoffLoop(nextTimeout), timeout); } + } + backoffLoop(100); + }; +} + +export function convertBlobToUint8Array(blob: Blob): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = () => { + resolve(reader.result as ArrayBuffer); + }; + + reader.onerror = (error) => { + reject(error); + }; + + reader.readAsArrayBuffer(blob); + }); +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..5a362d5 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "dependencies": { + "@bjorn3/browser_wasi_shim": "^0.3.0", + "ts-loader": "^9.5.1", + "tslib": "^2.7.0", + "typescript": "^5.6.2", + "webpack": "^5.95.0", + "webpack-cli": "^5.1.4" + } +} diff --git a/shell.nix b/shell.nix index 82fb296..bedcaa0 100644 --- a/shell.nix +++ b/shell.nix @@ -1 +1,97 @@ -(import ./default.nix {}).shell +let + sources = { + nixpkgs = builtins.fetchTarball { + url = "https://github.com/NixOS/nixpkgs/archive/refs/tags/24.05.tar.gz"; + }; + http-client = builtins.fetchGit { + url = "https://github.com/lagunoff/http-client.git"; + rev = "18388fb8f2a13290279a9e69a1ca2b4719e58cca"; + }; + ghc-wasm-meta = "gitlab:ghc/ghc-wasm-meta?host=gitlab.haskell.org&ref=108e4693cd147777e8d93683e58c8a5e1da74c96"; + }; + + pkgs = import sources.nixpkgs {}; + + overrides = final: prev: { + mkDerivation = args: prev.mkDerivation ({ + doCheck = false; + doBenchmark = false; + doHoogle = true; + doHaddock = true; + jailbreak = true; + enableLibraryProfiling = false; + enableExecutableProfiling = false; + } // args); + + clickable = final.callCabal2nix "clickable" ./ {}; + semirings = final.callCabal2nix "semirings" ../fullstack-hs/.overrides/semirings {}; + + th-compat = final.callCabal2nix "th-compat" (builtins.fetchGit { + url = "https://github.com/haskell-compat/th-compat.git"; + rev = "eec1edb9e09eba14e7ba17be29a9674431c63c05"; + }) {}; + + th-abstraction = final.callCabal2nix "th-abstraction" (builtins.fetchGit { + url = "https://github.com/glguy/th-abstraction.git"; + rev = "1fb59d1651ac5462f44100c62e5806665d39b6c6"; + }) {}; + + crypton-connection = final.callCabal2nix "crypton-connection" (builtins.fetchGit { + url = "https://github.com/kazu-yamamoto/crypton-connection.git"; + rev = "bab16ae4d0fa417ba315fb3d26f55418ce91fcb6"; + }) {}; + + lens = final.callCabal2nix "lens" (builtins.fetchGit { + url = "https://github.com/ekmett/lens.git"; + rev = "c1f47431d66f114262acb4023a0d79e979af5636"; + }) {}; + + ghc-exactprint = final.callCabal2nix "ghc-exactprint" (builtins.fetchGit { + url = "https://github.com/alanz/ghc-exactprint.git"; + rev = "630c4e8f36d0decb765644041a273f6ba8888d57"; + }) {}; + + hashable = final.callCabal2nix "hashable" ../fullstack-hs/.overrides/hashable {}; + + semigroupoids = final.callCabal2nix "semigroupoids" ../fullstack-hs/.overrides/semigroupoids {}; + extensions = final.callCabal2nix "extensions" ../fullstack-hs/.overrides/extensions {}; + stan = final.callCabal2nix "stan" ../fullstack-hs/.overrides/stan {}; + apply-refact = final.callCabal2nix "apply-refact" ../fullstack-hs/.overrides/apply-refact {}; + retrie = final.callCabal2nix "retrie" ../fullstack-hs/.overrides/retrie {}; + aeson-pretty = final.callCabal2nix "aeson-pretty" ../fullstack-hs/.overrides/aeson-pretty {}; + + ghcide = final.callCabal2nix "ghcide" ../fullstack-hs/.overrides/haskell-language-server/ghcide {}; + haskell-language-server = final.callCabal2nix "haskell-language-server" ../fullstack-hs/.overrides/haskell-language-server {}; + haskell-language-server-exe = final.callCabal2nix "haskell-language-server-exe" ../fullstack-hs/.overrides/haskell-language-server/exe {}; + hie-compat = final.callCabal2nix "hie-compat" ../fullstack-hs/.overrides/haskell-language-server/hie-compat {}; + hls-graph = final.callCabal2nix "hls-graph" ../fullstack-hs/.overrides/haskell-language-server/hls-graph {}; + hls-plugin-api = final.callCabal2nix "hls-plugin-api" ../fullstack-hs/.overrides/haskell-language-server/hls-plugin-api {}; + hls-test-utils = final.callCabal2nix "hls-test-utils" ../fullstack-hs/.overrides/haskell-language-server/hls-test-utils {}; + shake-bench = final.callCabal2nix "shake-bench" ../fullstack-hs/.overrides/haskell-language-server/shake-bench {}; + + cabal-add = final.callCabal2nix "cabal-add" ../fullstack-hs/.overrides/cabal-add {}; + ghc-lib-parser = final.callCabal2nix "ghc-lib-parser" ../fullstack-hs/.overrides/ghc-lib-parser-9.10.1.20240511 {}; + + aeson = final.callCabal2nix "aeson" ../fullstack-hs/.overrides/aeson {}; + attoparsec-aeson = final.callCabal2nix "attoparsec-aeson" ../fullstack-hs/.overrides/aeson/attoparsec-aeson {}; + lsp = final.callCabal2nix "lsp" ../fullstack-hs/.overrides/lsp/lsp {}; + lsp-types = final.callCabal2nix "lsp-types" ../fullstack-hs/.overrides/lsp/lsp-types {}; + lsp-test = final.callCabal2nix "lsp-test" ../fullstack-hs/.overrides/lsp/lsp-test {}; + }; + + haskellPackages = pkgs.haskell.packages.ghc9101.override { + inherit overrides; + }; + + ghc-wasm-meta = builtins.getFlake sources.ghc-wasm-meta; +in + (pkgs.mkShell { + inputsFrom = [haskellPackages.clickable.env]; + nativeBuildInputs = [ + ghc-wasm-meta.packages.x86_64-linux.default + haskellPackages.haskell-language-server-exe + (haskellPackages.hoogleWithPackages (p: p.clickable.buildInputs)) + ]; + }) // { + inherit haskellPackages; + } diff --git a/src/Clickable.hs b/src/Clickable.hs deleted file mode 100644 index 3fe4dc8..0000000 --- a/src/Clickable.hs +++ /dev/null @@ -1,10 +0,0 @@ -module Clickable (module Exports) where - -import Clickable.DOM as Exports -import Clickable.Core as Exports -import Clickable.Element as Exports -import Clickable.Property as Exports -import Clickable.Protocol as Exports -import Clickable.Protocol.Value as Exports -import Clickable.Types as Exports -import Wasm.Compat.Prim as Exports diff --git a/src/Clickable/#Protocol.hs# b/src/Clickable/#Protocol.hs# deleted file mode 100644 index 8878eb4..0000000 --- a/src/Clickable/#Protocol.hs# +++ /dev/null @@ -1,210 +0,0 @@ -{-# LANGUAGE DerivingVia #-} -module Clickable.Protocol where - -import Data.Binary (Binary) -import Data.ByteString (ByteString) -import Data.Int -import Data.Text (Text) -import Data.String -import Data.Word -import GHC.Generics - -import Clickable.Protocol.Value - -data HaskellMessage - = EvalExpr Int32Le Expr - -- ^ Evaluate expression, expect the result to be returned by - -- 'Return' message - | HotReload - -- ^ Used under dev server, won't return anything - | Halt - -- ^ Signal that current process completed, won't return anything - deriving stock (Generic, Show) - deriving anyclass (Binary) - -data JavaScriptMessage - = Start StartFlags - | Return Int32Le Value - | TriggerEventMsg Value EventId - | BeforeUnload - -- ^ Fired from addEventListener("beforeunload") listener. Won't - -- work under the DevServer! - deriving (Generic, Show) - deriving anyclass (Binary) - -newtype StartFlags = StartFlags {unStartFlags :: Value} - deriving newtype (Generic, Show, Binary) - --- | Strict Lambda calculus with arbitrary side-effects, meant to be --- used as commands executed in the JavaScript side, optimized for --- non-blocking execution and minimizing round-trips. -data Expr - = Null - -- ^ null or undefined values - | Bool Bool - -- ^ JavaScript boolean value - | I8 Int8 - | I16 Int16Le - | I32 Int32Le - | I64 Int64Le - - | U8 Word8 - | U16 Word16Le - | U32 Word32Le - | U64 Word64Le - - | F32 Float32Le - | F64 Float64Le - - | Str Text -- ^ JavaScript string - | Arr [Expr] -- ^ JavaScript array - | Obj [(Text, Expr)] -- ^ JavaScript object - | U8Arr ByteString -- ^ Raw byte array - - | Dot Expr Text - -- ^ Read string property of an object. @(Dot (Id "document") - -- "body")@ is equivalent to @document.body@ JavaScript expression - | SetProp Expr Text Expr - -- ^ Assign a value to a string property of an object @(AssignProp - -- (Id "foo") "bar" (Str "baz"))@ is equivalent to @foo['bar'] = - -- baz;@ JavaScript expression. Evaluates into its right-hand side - -- expression. - | Ix Expr Int64 - -- ^ Read value from an integer index of an object. @(Ix (Id - -- "foo") 0)@ is equivalent to @foo[0]@ JavaScript expression - - | Plus Expr Expr - -- ^ Binary addition @(Add 256 5647)@ is equivalent to @256 + 5647@ - | Subtract Expr Expr - -- ^ Binary substraction @(Subtract 256 5647)@ is equivalent to @256 - 5647@ - | Multiply Expr Expr - -- ^ Binary multiplication @(Multiply 256 5647)@ is equivalent to @256 * 5647@ - | Divide Expr Expr - -- ^ Binary division @(Divide 256 5647)@ is equivalent to @256 / 5647@ - - | Id Text -- ^ Lookup an identifier in current lexical scope - | Lam Expr - -- ^ Introduce a lambda function. Arguments can be accessed via 'Arg - -- 0 0' - | Arg Word8 Word8 - -- ^ Lookup an argument in the current argument scope. Separate - -- scope for argument from regular lexical scope required for - -- performance reasons. First field is "De Bruijn index" pointing to - -- nth-lambda counting outward from current expression. Second - -- number is positional argument for that lambda (each lambda - -- receives multiple arguments in a vector, see - -- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments) - -- De Bruijn indicies are notoriously hard to write manually, it's - -- one of the reasons this protocol is much less convenient than FFI - -- with JavaScript. One solution I found is that for complex code I - -- write regular JavaScript and run it with 'Eval'. - | Apply Expr [Expr] - -- ^ Apply a function to arbitrary length arguments. @Apply (Id - -- "encodeURIComponent") [Str "#"]@ going to evaluate to @String "%23"@ - | Call Expr Text [Expr] - -- ^ Call a method of an object @Call (Id "console") "log" [Str - -- "Hi!"]@ is equivalent to @console.log('Hi!')@ JavaScript code - - | AssignVar VarId Expr - -- ^ Assign a value to VarId allocated in haskell side. This way - -- haskell can save certain values between WASM reactor invocations - | FreeVar VarId - -- ^ Free variable allocated with @AssignVar@ - | Var VarId - -- ^ Retrieve the value of the variable - | FreeScope ResourceScope - -- ^ Free all the resources assosiated with the given ResourceScope - - | AskDomBuilder - | SupplyDomBuilder DomBuilder Expr - - | InsertNode Expr - | ElementProp Text Expr - | ElementAttr Text Text - | ClassListAdd [Text] - | ClassListRemove [Text] - | InsertBrackets - | ClearBrackets Bool - - | CreateElement Text - | CreateElementNS Text Text - | CreateTextNode Text - | UpdateTextNode Expr Text - - | AddEventListener ResourceScope Expr Expr Expr - -- ^ @AddEventListener rscope target eventName listener@ is - -- equivalent to @target.addEventListener(eventName, listener)@ it - -- returns @FinalizerId@ integer identifier that can be used in - -- 'RemoveEventListener', but calling 'RemoveEventListener' is not - -- required, it'll be called authomatically when given ResourceScope - -- will be freed with 'FreeScope' - | ConnectResource ResourceScope Expr - -- ^ Returns FinalizerId - | SetTimeout ResourceScope Expr Int32Le - -- ^ Returns FinalizerId - | ApplyFinalizer ResourceScope Expr - -- ^ Actuate given finalizer before the ResourceScope is freed - - | RevSeq [Expr] - -- ^ Sequence of the expressions in reverse order. It will be - -- evaluated from the end to the beggining of the list. Returns - -- whatever the last expression (from the head of the list) - -- evaluates into. Order is reversed to support fast insertion of - -- new instructions - | Eval UnsafeJavaScript - -- ^ Evaluate arbitrary JavaScript code @(Eval "setTimeout(() => - -- console.log('Hi!'), 1000)")@ will print a message with one second - -- delay - | TriggerEvent EventId Expr - -- ^ Emits `TriggerEventMsg` as a side-effect - | UncaughtException Text - deriving stock (Generic, Show) - deriving anyclass (Binary) - -valueToExpr :: Value -> Expr -valueToExpr = \case - Vnull -> Null - Vbool a -> Bool a - - Vi8 a -> I8 a - Vi16 a -> I16 a - Vi32 a -> I32 a - Vi64 a -> I64 a - - Vu8 a -> U8 a - Vu16 a -> U16 a - Vu32 a -> U32 a - Vu64 a -> U64 a - - Vf64 a -> F64 a - Vf32 a -> F32 a - - Vstr a -> Str a - Varr xs -> Arr $ fmap valueToExpr xs - Vobj kv -> Obj $ fmap (\(k, v) -> (k, valueToExpr v)) kv - Vu8arr a -> U8Arr a - -toExpr :: ToValue a => a -> Expr -toExpr = valueToExpr . toValue - -newtype DomBuilder = DomBuilder {unDomBuilder :: Expr} - deriving newtype (Show, Binary) - -data VarId = VarId ResourceScope Int32Le - deriving stock (Generic, Show, Ord, Eq) - deriving anyclass (Binary) - -newtype FinalizerId = FinalizerId {unFinalizerId :: Int32} - deriving newtype (Show, Ord, Eq) - deriving Binary via Int32Le - -newtype ResourceScope = ResourceScope {unResourceScope :: Int32} - deriving newtype (Show, Ord, Eq) - deriving Binary via Int32Le - -newtype EventId = EventId {unEventId :: Int32} - deriving newtype (Show, Ord, Eq) - deriving Binary via Int32Le - -newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} - deriving newtype (IsString, Show, Semigroup, Monoid, Binary) diff --git a/src/Clickable/Core.hs b/src/Clickable/Core.hs deleted file mode 100644 index c8ad8d7..0000000 --- a/src/Clickable/Core.hs +++ /dev/null @@ -1,399 +0,0 @@ -{-# OPTIONS_GHC -fno-warn-orphans #-} -module Clickable.Core - ( module Clickable.Core - , Internal.trampoline - , Internal.syncPoint - , Internal.launchClickM - ) where - -import Control.Monad -import Control.Monad.Reader -import Control.Monad.State -import Data.Function ((&)) -import Data.IORef -import Data.String -import Data.Text (Text) -import Data.Text qualified as Text -import Data.List qualified as List -import Data.Tuple - -import Clickable.Internal (reactive, reactive_) -import Clickable.Internal qualified as Internal -import Clickable.Types -import Clickable.Protocol -import Clickable.Protocol.Value - ---------------------------------------- --- OPERATIONS OVER DYNAMIC VARIABLES -- ---------------------------------------- - -newVar :: a -> ClickM (DynVar a) -newVar a = do - ref <- liftIO $ newIORef a - let mkEv s = unsafeFromEventId $ EventId s.next_id - state \s -> (SourceVar (mkEv s) ref, s {next_id = s.next_id + 1}) - -overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a -overrideVar = OverrideVar - -lensMap :: Lens' s a -> DynVar s -> DynVar a -lensMap = LensMap - -mapHoldVal :: (a -> b) -> DynVal a -> ClickM (DynVal b) -mapHoldVal = Internal.mapHoldVal - -readVal :: MonadIO m => DynVal a -> m a -readVal = Internal.readVal - -readVar :: MonadIO m => DynVar a -> m a -readVar = Internal.readVar - -modifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a -modifyVar var@(SourceVar varId ref) f = do - (newVal, a) <- liftIO $ atomicModifyIORef' ref g - modify $ Internal.triggerEvent varId newVal - return a - where - g old = let (new, a) = f old in (new, (new, a)) -modifyVar (OverrideVar ufn var) f = - ufn (modifyVar var) f -modifyVar (LensMap l var) f = modifyVar var (swap . l (swap . f)) - -modifyVar_ :: DynVar s -> (s -> s) -> ClickM () -modifyVar_ var f = modifyVar var ((,()) . f) - -writeVar :: DynVar s -> s -> ClickM () -writeVar var s = modifyVar_ var $ const s - -subscribe :: DynVal a -> (a -> ClickM ()) -> ClickM () -subscribe = Internal.subscribe - -forDyn :: DynVal a -> (a -> ClickM ()) -> ClickM () -forDyn dval action = readVal dval >>= action >> subscribe dval action - -forVar :: DynVar a -> (a -> ClickM ()) -> ClickM () -forVar = forDyn . fromVar - -modifyVarQuiet :: DynVar s -> (s -> (s, a)) -> ClickM a -modifyVarQuiet var@(SourceVar varId ref) f = do - (newVal, a) <- liftIO $ atomicModifyIORef' ref g - return a - where - g s = let (s', a) = f s in (s', (s', a)) -modifyVarQuiet (OverrideVar ufn var) f = - ufn (modifyVarQuiet var) f -modifyVarQuiet (LensMap l var) f = modifyVarQuiet var (swap . l (swap . f)) - -modifyVarQuiet_ :: DynVar s -> (s -> s) -> ClickM () -modifyVarQuiet_ var f = modifyVarQuiet var ((,()) . f) - --- todo: needs redesign -holdUniqDyn :: forall a. Eq a => DynVal a -> DynVal a -holdUniqDyn a = OverrideSub g a where - g :: forall b. SubscribeFn a b -> SubscribeFn a b - g next k = do - old <- readVal a - oldRef <- liftIO $ newIORef old - next \new acc -> do - old <- liftIO $ atomicModifyIORef' oldRef (new,) - if (old /= new) then k new acc else return acc - --------------------------------------- --- OPERATIONS OVER evaluation_queue -- --------------------------------------- - -enqueueExpr :: Expr -> ClickM () -enqueueExpr e = modify \s -> s {evaluation_queue = e : s.evaluation_queue} - -evalExpr :: Expr -> ClickM Value -evalExpr e = do - eval_expr <- asks (.eval_expr) - queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - liftIO $ eval_expr $ RevSeq $ e : queue - -------------------------- --- RESOURCE MANAGEMENT -- -------------------------- - -newScope :: ClickM ResourceScope -newScope = reactive Internal.newScope - -freeScope :: Bool -> ResourceScope -> ClickM () -freeScope unlink s = - reactive (const (Internal.freeScope unlink s)) >>= applyFin - where - applyFin [] = enqueueExpr $ FreeScope s - applyFin (ScopeFinalizer{sf_linked_scope}:xs) = freeScope True sf_linked_scope >> applyFin xs - applyFin (CustomFinalizer{cf_callback}:xs) = cf_callback >> applyFin xs - -installFinalizer :: ClickM () -> ClickM () -installFinalizer k = reactive_ $ Internal.installFinalizer k - -newVarId :: ClickM VarId -newVarId = reactive Internal.newVarId - -newCallback :: (a -> ClickM ()) -> ClickM (Event a) -newCallback k = reactive $ Internal.newCallback k - ------------------- --- BUILDING DOM -- ------------------- - -el :: Text -> HtmlM a -> HtmlM a -el t = lift . customizeHtml True (DomBuilder (CreateElement t)) - -elns :: Text -> Text -> HtmlM a -> HtmlM a -elns ns t = lift . customizeHtml True (DomBuilder (CreateElementNS ns t)) - -property :: ToValue a => Text -> a -> HtmlM () -property k v = lift $ modify f where - f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = ElementProp k (toExpr v) - -attribute :: Text -> Text -> HtmlM () -attribute k v = lift $ modify f where - f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = ElementAttr k v - -text :: Text -> HtmlM () -text t = lift $ modify f where - f s = s {evaluation_queue = expr : s.evaluation_queue } - expr = InsertNode $ CreateTextNode t - -dynText :: DynVal Text -> HtmlM () -dynText val = do - t <- lift $ readVal val - v <- lift $ newVarId - lift $ modify $ f v t - lift $ subscribe val $ enqueueExpr . UpdateTextNode (Var v) - where - f v t s = s {evaluation_queue = expr v t : s.evaluation_queue } - expr v t = InsertNode $ AssignVar v $ CreateTextNode t - -dynProp :: ToValue a => Text -> DynVal a -> HtmlM () -dynProp k val = do - t <- lift $ readVal val - v <- saveDomBuilder - lift $ modify $ f t - lift $ subscribe val $ enqueueExpr . SupplyDomBuilder (DomBuilder (Var v)) . ElementProp k . toExpr - where - f v s = s {evaluation_queue = expr v : s.evaluation_queue } - expr v = ElementProp k (toExpr v) - -dynAttr :: Text -> DynVal Text -> HtmlM () -dynAttr k val = do - t <- lift $ readVal val - v <- saveDomBuilder - lift $ modify $ f t - lift $ subscribe val $ enqueueExpr . SupplyDomBuilder (DomBuilder (Var v)) . ElementAttr k - where - f v s = s {evaluation_queue = expr v : s.evaluation_queue } - expr v = ElementAttr k v - -toggleClass :: Text -> DynVal Bool -> HtmlM () -toggleClass className val = do - scope <- lift $ asks (.scope) - v <- lift $ readVal val - n <- saveDomBuilder - let - initCmd False queue = queue - initCmd True queue = ClassListAdd [className] : queue - updateCmd False = SupplyDomBuilder (DomBuilder (Var n)) $ ClassListRemove [className] - updateCmd True = SupplyDomBuilder (DomBuilder (Var n)) $ ClassListAdd [className] - lift $ modify \s -> s {evaluation_queue = initCmd v s.evaluation_queue} - lift $ subscribe val $ enqueueExpr . updateCmd - -dynClassList :: DynVal [Text] -> HtmlM () -dynClassList dynList = do - n <- saveDomBuilder - scope <- lift $ asks (.scope) - initVal <- lift $ readVal dynList - let - compareList as bs = - (diffList as bs, diffList bs as) - diffList as bs = List.foldl' - (\xs k -> if List.elem k as then xs else k:xs) [] bs - k newList (_, _, oldList) = do - let (added, removed) = compareList oldList newList - modQueue $ updateCmd (added, removed, newList) - return (added, removed, newList) - updateCmd ([], [], _) queue = queue - updateCmd (added, [], _) queue = - SupplyDomBuilder (DomBuilder (Var n)) (ClassListAdd added) : queue - updateCmd ([], removed, _) queue = - SupplyDomBuilder (DomBuilder (Var n)) (ClassListRemove removed) : queue - updateCmd (added, removed, _) queue - = SupplyDomBuilder (DomBuilder (Var n)) (ClassListRemove removed) - : SupplyDomBuilder (DomBuilder (Var n)) (ClassListAdd added) - : queue - modQueue f = modify \s -> s {evaluation_queue = f s.evaluation_queue} - lift $ enqueueExpr $ ClassListAdd initVal - lift $ Internal.subscribeAccum dynList k ([], [], initVal) - ---------------------- --- DYNAMIC CONTENT -- ---------------------- - -dyn :: DynVal (HtmlM ()) -> HtmlM () -dyn val = do - brackets <- lift insertBrackets - scope <- lift newScope - initialVal <- lift $ readVal val - let - update html = do - lift $ clearBrackets brackets - html - exec h = - customizeHtml False (DomBuilder (Var brackets)) h - & local (\s -> s {scope}) - lift $ exec $ update initialVal - lift $ subscribe val $ \newVal -> do - freeScope False scope - exec $ update newVal - --- | Auxilliary datatype used in 'simpleList' implementation -data ElemEnv a = ElemEnv - { brackets :: VarId - , state_var :: DynVar a - , elem_scope :: ResourceScope - } - --- | Display dynamic collection of widgets. NOTE: changes in `DynVar --- a` do not automatically propagate into the larger state. See --- `OverrideVar` and todomvc example to see one way to upstream --- changes into the larger state. -simpleList - :: forall a. DynVal [a] - -- ^ Dynamic collection - -> (Int -> DynVar a -> HtmlM ()) - -- ^ Build HTML for each element in the list - -> HtmlM () -simpleList listDyn h = lift do - internalStateRef <- liftIO $ newIORef ([] :: [ElemEnv a]) - brackets <- insertBrackets - let - exec brackets scope h = - customizeHtml False (DomBuilder (Var brackets)) h - & local (\s -> s {scope}) - exec1 brackets = customizeHtml False (DomBuilder (Var brackets)) - - setup :: Int -> [a] -> [ElemEnv a] -> ClickM [ElemEnv a] - setup idx new existing = case (existing, new) of - ([], []) -> return [] - -- New list is longer, append new elements - ([], x:xs) -> do - e <- newElem idx x - exec e.brackets e.elem_scope $ h idx e.state_var - fmap (e:) $ setup (idx + 1) xs [] - -- New list is shorter, delete the elements that no longer - -- present in the new list - (r:rs, []) -> do - finalizeElems True (r:rs) - return [] - -- Update existing elements along the way - (r:rs, y:ys) -> do - writeVar r.state_var y - fmap (r:) $ setup (idx + 1) ys rs - newElem :: Int -> a -> ClickM (ElemEnv a) - newElem i a = do - elem_scope <- newScope - local (\s -> s {scope = elem_scope}) do - state_var <- newVar a - brackets <- insertBrackets - return ElemEnv {elem_scope, state_var, brackets} - finalizeElems :: Bool -> [ElemEnv a] -> ClickM () - finalizeElems remove = mapM_ \ee -> do - when remove $ detachBrackets ee.brackets - freeScope True ee.elem_scope - updateList new = do - eenvs <- liftIO $ readIORef internalStateRef - newEenvs <- setup 0 new eenvs - liftIO $ writeIORef internalStateRef newEenvs - initialVal <- readVal listDyn - exec1 brackets $ lift $ updateList initialVal - subscribe listDyn $ exec1 brackets . lift . updateList - --- | Parse given text as HTML and attach the resulting tree to --- 'html_current_element'. This way you can create not only HTML but --- anything that @innerHTML@ property can create (e.g. SVG) --- --- > -- Create a div with an SVG image inside that shows a black --- > -- circle --- > div_ [] do --- > unsafeHtml "\ --- > \\ --- > \" -unsafeHtml :: Text -> HtmlM () -unsafeHtml rawHtml = lift $ enqueueExpr (Internal.unsafeInsertHtml rawHtml) - --- | Attach resulting DOM to the given node instead of where it --- supposed to go given the cotext it used in. Might be useful for --- implementing modal dialogs, tooltips etc. Similar to what called --- portals in React ecosystem -portal :: DomBuilder -> HtmlM a -> HtmlM a -portal newRootEl html = - lift $ customizeHtml False newRootEl do - brackets <- lift insertBrackets - result <- lift $ customizeHtml False (DomBuilder (Var brackets)) html - lift $ installFinalizer $ detachBrackets brackets - return result - -blank :: Applicative m => m () -blank = pure () - ----------------------------- --- AUXILLIARY DEFINITIONS -- ----------------------------- - -customizeHtml :: Bool -> DomBuilder -> HtmlM a -> ClickM a -customizeHtml doInsert builder content = do - prevQueue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - result <- evalStateT content.unHtmlT Nothing - modify \s -> s {evaluation_queue = mkExpr s.evaluation_queue : prevQueue} - return result - where - mkExpr seq - | doInsert = InsertNode $ SupplyDomBuilder builder $ RevSeq (AskDomBuilder : seq) - | otherwise = SupplyDomBuilder builder $ RevSeq (AskDomBuilder : seq) - -attachHtml :: DomBuilder -> HtmlM a -> ClickM a -attachHtml rootEl contents = do - savedQueue <- state saveQueue - evalStateT contents.unHtmlT Nothing <* - modify (enqueueHtml savedQueue) - where - enqueueHtml saved s = s {evaluation_queue = e : saved} where - e = SupplyDomBuilder rootEl (RevSeq s.evaluation_queue) - saveQueue s = - (s.evaluation_queue, s {evaluation_queue = []}) - -attachToBody :: HtmlM a -> ClickM a -attachToBody = attachHtml $ DomBuilder $ Id "document" `Dot` "body" - -saveDomBuilder :: HtmlM VarId -saveDomBuilder = do - alreadySaved <- HtmlT get - case alreadySaved of - Nothing -> do - varId <- lift newVarId - HtmlT $ put $ Just varId - lift $ enqueueExpr $ AssignVar varId AskDomBuilder - return varId - Just saved -> return saved - -insertBrackets :: ClickM VarId -insertBrackets = do - brackets <- newVarId - enqueueExpr $ AssignVar brackets InsertBrackets - return brackets - -clearBrackets :: VarId -> ClickM () -clearBrackets n = - enqueueExpr $ SupplyDomBuilder (DomBuilder (Var n)) $ ClearBrackets False - -detachBrackets :: VarId -> ClickM () -detachBrackets n = - enqueueExpr $ SupplyDomBuilder (DomBuilder (Var n)) $ ClearBrackets True - -instance (a ~ ()) => IsString (HtmlM a) where - fromString = text . Text.pack diff --git a/src/Clickable/DOM.hs b/src/Clickable/DOM.hs deleted file mode 100644 index 2cf720f..0000000 --- a/src/Clickable/DOM.hs +++ /dev/null @@ -1,276 +0,0 @@ -module Clickable.DOM where - -import Control.Monad.Reader -import Data.Int -import Data.Kind -import Data.Text (Text) -import GHC.Generics -import Unsafe.Coerce - -import Clickable.Internal -import Clickable.Protocol -import Clickable.Protocol.Value -import Clickable.Types - - -data EventListenerOptions = EventListenerOptions - { prevent_default :: Bool - , stop_propagation :: Bool - } deriving stock (Generic, Show, Eq) - -defaultEventListenerOptions :: EventListenerOptions -defaultEventListenerOptions = EventListenerOptions - { prevent_default = False - , stop_propagation = False - } - --- | A snippet of JavaScript that subscribes to certain event. It --- should return a function that revokes the subscribtion. The typical --- usage will involve addEventListener/removeEventListener but it's --- not limited to this use case. Same method can be used to establish --- WebSocket connection or any other source of events in browser -newtype ConnectEventScript a = ConnectEventScript - { unConnectEventScript :: Event a -> Expr - } - -addEventListener :: FromValue a => ConnectEventScript a -> (a -> ClickM ()) -> ClickM () -addEventListener (ConnectEventScript ces) k = reactive_ \scope s -> - let k' :: Value -> ClickM () - k' = local (\e -> e {scope}) . mapM_ k . fromValue - eventId = EventId s.next_id - newSub = SubscriptionSimple scope (unsafeFromEventId eventId) (k' . unsafeCoerce) - connectExpr = ConnectResource scope $ ces $ unsafeFromEventId eventId - in s { evaluation_queue = connectExpr : s.evaluation_queue - , subscriptions = newSub : s.subscriptions - , next_id = s.next_id + 1 - } - -class IsEventName eventName where - type EventListenerCb eventName :: Type - connectEventName :: EventListenerCb eventName -> ClickM () - -on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HtmlM () -on k = lift $ connectEventName @eventName k - -instance IsEventName "click" where - type EventListenerCb "click" = ClickM () - connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "click") (const k) - -instance IsEventName "mousedown" where - type EventListenerCb "mousedown" = ClickM () - connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "mousedown") (const k) - -instance IsEventName "mouseup" where - type EventListenerCb "mouseup" = ClickM () - connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "mouseup") (const k) - -instance IsEventName "mouseenter" where - type EventListenerCb "mouseenter" = ClickM () - connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "mouseenter") (const k) - -instance IsEventName "mouseleave" where - type EventListenerCb "mouseleave" = ClickM () - connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "mouseleave") (const k) - -instance IsEventName "dblclick" where - type EventListenerCb "dblclick" = ClickM () - connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "dblclick") (const k) - -instance IsEventName "submit" where - type EventListenerCb "submit" = ClickM () - connectEventName k = addEventListener (genericEvent opt "submit") (const k) - where - opt = EventListenerOptions - { prevent_default = True - , stop_propagation = True - } - -instance IsEventName "input" where - type EventListenerCb "input" = Text -> ClickM () - connectEventName = addEventListener (inputEvent "input") - -instance IsEventName "keydown" where - type EventListenerCb "keydown" = Int32 -> ClickM () - connectEventName = addEventListener (keyboardEvent "keydown") - -instance IsEventName "keyup" where - type EventListenerCb "keyup" = Int32 -> ClickM () - connectEventName = addEventListener (keyboardEvent "keyup") - -instance IsEventName "focus" where - type EventListenerCb "focus" = ClickM () - connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "focus") (const k) - -instance IsEventName "blur" where - type EventListenerCb "blur" = ClickM () - connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "blur") (const k) - -instance IsEventName "input/blur" where - type EventListenerCb "input/blur" = Text -> ClickM () - connectEventName = addEventListener (inputEvent "blur") - -instance IsEventName "input/focus" where - type EventListenerCb "input/focus" = Text -> ClickM () - connectEventName = addEventListener (inputEvent "focus") - -instance IsEventName "checkbox/change" where - type EventListenerCb "checkbox/change" = Bool -> ClickM () - connectEventName = addEventListener checkboxChangeEvent - -instance IsEventName "select/change" where - type EventListenerCb "select/change" = Text -> ClickM () - connectEventName = addEventListener selectChangeEvent - -instance IsEventName "mousewheel" where - type EventListenerCb "mousewheel" = MouseWheel -> ClickM () - connectEventName = addEventListener mouseWheelEvent - --- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event -genericEvent :: EventListenerOptions -> Text -> ConnectEventScript () -genericEvent opt eventName = ConnectEventScript \(Event eventId) -> - Eval - ("(function(target, trigger){\n\ - \ function listener(event){\n\ - \ " <> preventDefaultStmt <> "\n\ - \ " <> stopPropagationStmt <> "\n\ - \ trigger();\n\ - \ }\n\ - \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` [AskDomBuilder, Lam (TriggerEvent eventId Null)] - where - preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" - stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" - --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event -inputEvent :: Text -> ConnectEventScript Text -inputEvent eventName = ConnectEventScript \(Event eventId) -> - Eval - ("(function(target, trigger){\n\ - \ function listener(event){\n\ - \ trigger(event.target.value);\n\ - \ }\n\ - \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] - --- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event --- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardEvent :: Text -> ConnectEventScript Int32 -keyboardEvent eventName = ConnectEventScript \(Event eventId) -> - Eval - ("(function(target, trigger){\n\ - \ function listener(event){\n\ - \ trigger(event.keyCode);\n\ - \ }\n\ - \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] - --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -checkboxChangeEvent :: ConnectEventScript Bool -checkboxChangeEvent = ConnectEventScript \(Event eventId) -> - Eval - "(function(target, trigger){\n\ - \ function listener(event){\n\ - \ trigger(event.target.checked);\n\ - \ }\n\ - \ target.addEventListener('change', listener);\n\ - \ return () => target.removeEventListener('change', listener);\n\ - \})" `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] - --- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -selectChangeEvent :: ConnectEventScript Text -selectChangeEvent = ConnectEventScript \(Event eventId) -> - Eval - "(function(target, trigger){\n\ - \ function listener(event){\n\ - \ trigger(event.target.value);\n\ - \ }\n\ - \ target.addEventListener('change', listener);\n\ - \ return () => target.removeEventListener('change', listener);\n\ - \})" `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] - -data Location = Location - { protocol :: Text - -- ^ A string containing the protocol scheme of the URL, including - -- the final ':' - , hostname :: Text - -- ^ A string containing the domain of the URL. - , port :: Text - -- ^ A string containing the port number of the URL. - , pathname :: Text - -- ^ A string containing an initial '/' followed by the path of the - -- URL, not including the query string or fragment. - , search :: Text - -- ^ A string containing a '?' followed by the parameters or - -- "querystring" of the URL - , hash :: Text - -- ^ A string containing a '#' followed by the fragment identifier - -- of the URL. - } deriving stock (Show, Eq, Generic) - deriving anyclass (FromValue, ToValue) - --- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event -popstateEvent :: ConnectEventScript Location -popstateEvent = ConnectEventScript \(Event eventId) -> - Eval - "(function(target, trigger){\n\ - \ function listener(){\n\ - \ trigger({\n\ - \ protocol: location.protocol,\n\ - \ hostname: location.hostname,\n\ - \ port: location.port,\n\ - \ pathname: location.pathname,\n\ - \ search: location.search,\n\ - \ hash: location.hash\n\ - \ });\n\ - \ }\n\ - \ target.addEventListener('popstate', listener);\n\ - \ return () => target.removeEventListener('popstate', listener);\n\ - \})" `Apply` [Id "window", Lam (TriggerEvent eventId (Arg 0 0))] - --- | Collection of deltaX, deltaY and deltaZ properties from WheelEvent --- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent -data MouseWheel = MouseWheel - { mw_delta_x :: Int32 - , mw_delta_y :: Int32 - , mw_delta_z :: Int32 - , mw_alt_key :: Bool - , mw_ctrl_key :: Bool - , mw_meta_key :: Bool - , mw_shift_key :: Bool - } deriving stock (Eq, Show, Generic) - deriving anyclass (FromValue, ToValue) - --- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent -mouseWheelEvent :: ConnectEventScript MouseWheel -mouseWheelEvent = ConnectEventScript \(Event eventId) -> - Eval - "(function(target, trigger){\n\ - \ function listener(event){\n\ - \ trigger({\n\ - \ mw_delta_x: event.deltaX,\n\ - \ mw_delta_y: event.deltaY,\n\ - \ mw_delta_z: event.deltaZ,\n\ - \ mw_alt_key: event.altKey,\n\ - \ mw_ctrl_key: event.ctrlKey,\n\ - \ mw_meta_key: event.metaKey,\n\ - \ mw_shift_key: event.shiftKey\n\ - \ });\n\ - \ }\n\ - \ target.addEventListener('mousewheel', listener);\n\ - \ return () => target.removeEventListener('mousewheel', listener);\n\ - \})" `Apply` [AskDomBuilder, Lam (TriggerEvent eventId (Arg 0 0))] diff --git a/src/Clickable/Element.hs b/src/Clickable/Element.hs deleted file mode 100644 index de84a7d..0000000 --- a/src/Clickable/Element.hs +++ /dev/null @@ -1,402 +0,0 @@ -{-| -Shortcuts for most common HTML5 elements --} -module Clickable.Element where - -import Clickable.Core -import Clickable.Types -import Data.Text - --- | This typeclass allows for tag constructors to have variable --- length arguments. Each tag constructor like 'div_' defined below --- can be called with one or two arguments --- --- > div_ $ text "A Div without attributes" --- > div_ [class_ "wrapper"] $ text "A Div with a class" --- --- Unceremoniously copied from the amazing @lucid@ library, see --- https://github.com/chrisdone/lucid/blob/fb3b0e7c189c2acd8d88838d4a13923f24542ee8/src/Lucid/Base.hs#L272 -class Term arg result | result -> arg where - term - :: Text -- ^ Name. - -> arg -- ^ Some argument. - -> result -- ^ Result: either an element or an attribute. - --- | Given attributes, expect more child input. -instance f ~ HtmlM a => Term [HtmlM ()] (f -> HtmlM a) where - term name attrs = el name . (sequence_ attrs *>) - {-# INLINE term #-} - --- | Given children immediately, just use that and expect no --- attributes. -instance Term (HtmlM a) (HtmlM a) where - term = el - {-# INLINE term #-} - -div_ :: Term arg result => arg -> result -div_ = term "div" -{-# INLINE div_ #-} - -table_ :: Term arg result => arg -> result -table_ = term "table" -{-# INLINE table_ #-} - -thead_ :: Term arg result => arg -> result -thead_ = term "thead" -{-# INLINE thead_ #-} - -tbody_ :: Term arg result => arg -> result -tbody_ = term "tbody" -{-# INLINE tbody_ #-} - -tr_ :: Term arg result => arg -> result -tr_ = term "tr" -{-# INLINE tr_ #-} - -th_ :: Term arg result => arg -> result -th_ = term "th" -{-# INLINE th_ #-} - -td_ :: Term arg result => arg -> result -td_ = term "td" -{-# INLINE td_ #-} - -tfoot_ :: Term arg result => arg -> result -tfoot_ = term "tfoot" -{-# INLINE tfoot_ #-} - -section_ :: Term arg result => arg -> result -section_ = term "section" -{-# INLINE section_ #-} - -header_ :: Term arg result => arg -> result -header_ = term "header" -{-# INLINE header_ #-} - -footer_ :: Term arg result => arg -> result -footer_ = term "footer" -{-# INLINE footer_ #-} - -button_ :: Term arg result => arg -> result -button_ = term "button" -{-# INLINE button_ #-} - -form_ :: Term arg result => arg -> result -form_ = term "form" -{-# INLINE form_ #-} - -p_ :: Term arg result => arg -> result -p_ = term "p" -{-# INLINE p_ #-} - -s_ :: Term arg result => arg -> result -s_ = term "s" -{-# INLINE s_ #-} - -ul_ :: Term arg result => arg -> result -ul_ = term "ul" -{-# INLINE ul_ #-} - -span_ :: Term arg result => arg -> result -span_ = term "span" -{-# INLINE span_ #-} - -strong_ :: Term arg result => arg -> result -strong_ = term "strong" -{-# INLINE strong_ #-} - -li_ :: Term arg result => arg -> result -li_ = term "li" -{-# INLINE li_ #-} - -h1_ :: Term arg result => arg -> result -h1_ = term "h1" -{-# INLINE h1_ #-} - -h2_ :: Term arg result => arg -> result -h2_ = term "h2" -{-# INLINE h2_ #-} - -h3_ :: Term arg result => arg -> result -h3_ = term "h3" -{-# INLINE h3_ #-} - -h4_ :: Term arg result => arg -> result -h4_ = term "h4" -{-# INLINE h4_ #-} - -h5_ :: Term arg result => arg -> result -h5_ = term "h5" -{-# INLINE h5_ #-} - -h6_ :: Term arg result => arg -> result -h6_ = term "h6" -{-# INLINE h6_ #-} - -hr_ :: Term arg result => arg -> result -hr_ = term "hr" -{-# INLINE hr_ #-} - -pre_ :: Term arg result => arg -> result -pre_ = term "pre" -{-# INLINE pre_ #-} - -input_ :: Term arg result => arg -> result -input_ = term "input" -{-# INLINE input_ #-} - -label_ :: Term arg result => arg -> result -label_ = term "label" -{-# INLINE label_ #-} - -a_ :: Term arg result => arg -> result -a_ = term "a" -{-# INLINE a_ #-} - -details_ :: Term arg result => arg -> result -details_ = term "details" -{-# INLINE details_ #-} - -summary_ :: Term arg result => arg -> result -summary_ = term "summary" -{-# INLINE summary_ #-} - -menuitem_ :: Term arg result => arg -> result -menuitem_ = term "menuitem" -{-# INLINE menuitem_ #-} - -menu_ :: Term arg result => arg -> result -menu_ = term "menu" -{-# INLINE menu_ #-} - -fieldset_ :: Term arg result => arg -> result -fieldset_ = term "fieldset" -{-# INLINE fieldset_ #-} - -legend_ :: Term arg result => arg -> result -legend_ = term "legend" -{-# INLINE legend_ #-} - -datalist_ :: Term arg result => arg -> result -datalist_ = term "datalist" -{-# INLINE datalist_ #-} - -optgroup_ :: Term arg result => arg -> result -optgroup_ = term "optgroup" -{-# INLINE optgroup_ #-} - -progress_ :: Term arg result => arg -> result -progress_ = term "progress" -{-# INLINE progress_ #-} - -meter_ :: Term arg result => arg -> result -meter_ = term "meter" -{-# INLINE meter_ #-} - -center_ :: Term arg result => arg -> result -center_ = term "center" -{-# INLINE center_ #-} - -audio_ :: Term arg result => arg -> result -audio_ = term "audio" -{-# INLINE audio_ #-} - -video_ :: Term arg result => arg -> result -video_ = term "video" -{-# INLINE video_ #-} - -source_ :: Term arg result => arg -> result -source_ = term "source" -{-# INLINE source_ #-} - -track_ :: Term arg result => arg -> result -track_ = term "track" -{-# INLINE track_ #-} - -embed_ :: Term arg result => arg -> result -embed_ = term "embed" -{-# INLINE embed_ #-} - -object_ :: Term arg result => arg -> result -object_ = term "object" -{-# INLINE object_ #-} - -param_ :: Term arg result => arg -> result -param_ = term "param" -{-# INLINE param_ #-} - -ins_ :: Term arg result => arg -> result -ins_ = term "ins" -{-# INLINE ins_ #-} - -del_ :: Term arg result => arg -> result -del_ = term "del" -{-# INLINE del_ #-} - -small_ :: Term arg result => arg -> result -small_ = term "small" -{-# INLINE small_ #-} - -cite_ :: Term arg result => arg -> result -cite_ = term "cite" -{-# INLINE cite_ #-} - -dfn_ :: Term arg result => arg -> result -dfn_ = term "dfn" -{-# INLINE dfn_ #-} - -abbr_ :: Term arg result => arg -> result -abbr_ = term "abbr" -{-# INLINE abbr_ #-} - -time_ :: Term arg result => arg -> result -time_ = term "time" -{-# INLINE time_ #-} - -var_ :: Term arg result => arg -> result -var_ = term "var" -{-# INLINE var_ #-} - -samp_ :: Term arg result => arg -> result -samp_ = term "samp" -{-# INLINE samp_ #-} - -kbd_ :: Term arg result => arg -> result -kbd_ = term "kbd" -{-# INLINE kbd_ #-} - -caption_ :: Term arg result => arg -> result -caption_ = term "caption" -{-# INLINE caption_ #-} - -colgroup_ :: Term arg result => arg -> result -colgroup_ = term "colgroup" -{-# INLINE colgroup_ #-} - -col_ :: Term arg result => arg -> result -col_ = term "col" -{-# INLINE col_ #-} - -nav_ :: Term arg result => arg -> result -nav_ = term "nav" -{-# INLINE nav_ #-} - -article_ :: Term arg result => arg -> result -article_ = term "article" -{-# INLINE article_ #-} - -aside_ :: Term arg result => arg -> result -aside_ = term "aside" -{-# INLINE aside_ #-} - -address_ :: Term arg result => arg -> result -address_ = term "address" -{-# INLINE address_ #-} - -main_ :: Term arg result => arg -> result -main_ = term "main" -{-# INLINE main_ #-} - -body_ :: Term arg result => arg -> result -body_ = term "body" -{-# INLINE body_ #-} - -figure_ :: Term arg result => arg -> result -figure_ = term "figure" -{-# INLINE figure_ #-} - -figcaption_ :: Term arg result => arg -> result -figcaption_ = term "figcaption" -{-# INLINE figcaption_ #-} - -dl_ :: Term arg result => arg -> result -dl_ = term "dl" -{-# INLINE dl_ #-} - -dt_ :: Term arg result => arg -> result -dt_ = term "dt" -{-# INLINE dt_ #-} - -dd_ :: Term arg result => arg -> result -dd_ = term "dd" -{-# INLINE dd_ #-} - -img_ :: Term arg result => arg -> result -img_ = term "img" -{-# INLINE img_ #-} - -iframe_ :: Term arg result => arg -> result -iframe_ = term "iframe" -{-# INLINE iframe_ #-} - -canvas_ :: Term arg result => arg -> result -canvas_ = term "canvas" -{-# INLINE canvas_ #-} - -math_ :: Term arg result => arg -> result -math_ = term "math" -{-# INLINE math_ #-} - -select_ :: Term arg result => arg -> result -select_ = term "select" -{-# INLINE select_ #-} - -option_ :: Term arg result => arg -> result -option_ = term "option" -{-# INLINE option_ #-} - -textarea_ :: Term arg result => arg -> result -textarea_ = term "textarea" -{-# INLINE textarea_ #-} - -sub_ :: Term arg result => arg -> result -sub_ = term "sub" -{-# INLINE sub_ #-} - -sup_ :: Term arg result => arg -> result -sup_ = term "sup" -{-# INLINE sup_ #-} - -br_ :: HtmlM () -br_ = el "br" blank -{-# INLINE br_ #-} - -ol_ :: Term arg result => arg -> result -ol_ = term "ol" -{-# INLINE ol_ #-} - -blockquote_ :: Term arg result => arg -> result -blockquote_ = term "blockquote" -{-# INLINE blockquote_ #-} - -code_ :: Term arg result => arg -> result -code_ = term "code" -{-# INLINE code_ #-} - -em_ :: Term arg result => arg -> result -em_ = term "em" -{-# INLINE em_ #-} - -i_ :: Term arg result => arg -> result -i_ = term "i" -{-# INLINE i_ #-} - -b_ :: Term arg result => arg -> result -b_ = term "b" -{-# INLINE b_ #-} - -u_ :: Term arg result => arg -> result -u_ = term "u" -{-# INLINE u_ #-} - -q_ :: Term arg result => arg -> result -q_ = term "q" -{-# INLINE q_ #-} - -script_ :: Term arg result => arg -> result -script_ = term "script" -{-# INLINE script_ #-} - -link_ :: Term arg result => arg -> result -link_ = term "link" -{-# INLINE link_ #-} diff --git a/src/Clickable/FFI.hs b/src/Clickable/FFI.hs deleted file mode 100644 index f4c6608..0000000 --- a/src/Clickable/FFI.hs +++ /dev/null @@ -1,37 +0,0 @@ -{-# OPTIONS_GHC -fno-warn-orphans #-} -{-# LANGUAGE CPP #-} -{-# LANGUAGE ForeignFunctionInterface #-} -{-# LANGUAGE MagicHash #-} - -#if defined(wasm32_HOST_ARCH) -{-# LANGUAGE JavaScriptFFI #-} -#endif -module Clickable.FFI where - -import Wasm.Compat.Prim -import Control.Monad.IO.Class -import GHC.Ptr -import Data.Word -import Data.Text.Internal -import Data.Array.Byte -import GHC.Prim - -consoleLog :: MonadIO m => Text -> m () -consoleLog (Text (ByteArray arr) off len) = liftIO do - let addr = byteArrayContents# arr - js_consoleLog (Ptr addr `plusPtr` off) len - -#if !defined(wasm32_HOST_ARCH) -js_evalMessage :: Ptr Word8 -> IO (Ptr Word8) -js_evalMessage = undefined - -js_consoleLog :: Ptr Word8 -> Int -> IO () -js_consoleLog = undefined -#else -foreign import javascript unsafe - "clickable.evalMessage(__exports, $1)" - js_evalMessage :: Ptr Word8 {- HaskellMessage -} -> IO (Ptr Word8 {- JavaScriptMessage -}) -foreign import javascript unsafe - "console.log(new TextDecoder('utf8').decode(new Uint8Array(__exports.memory.buffer, $1, $2)));" - js_consoleLog :: Ptr Word8 -> Int -> IO () -#endif diff --git a/src/Clickable/Internal.hs b/src/Clickable/Internal.hs deleted file mode 100644 index 686c430..0000000 --- a/src/Clickable/Internal.hs +++ /dev/null @@ -1,251 +0,0 @@ -module Clickable.Internal where - -import Control.Applicative -import Control.Monad -import Control.Monad.Reader -import Control.Monad.State -import Data.IORef -import Data.Text (Text) -import Data.List qualified as List -import Data.Map qualified as Map -import Unsafe.Coerce -import GHC.Exts - -import Clickable.Protocol -import Clickable.Protocol.Value -import Clickable.Types - -emptyState :: InternalState -emptyState = InternalState [] [] Map.empty [] 0 - -newInternalEnv :: (Expr -> IO Value) -> IO InternalEnv -newInternalEnv eval_expr = do - let scope = ResourceScope $ emptyState.next_id - internal_state_ref <- newIORef emptyState {next_id = emptyState.next_id + 1} - return InternalEnv {internal_state_ref, scope, eval_expr} - -triggerEvent :: Event a -> a -> InternalState -> InternalState -triggerEvent eventId a = - defer eventId $ gets (.subscriptions) >>= notify - where - anyEventId :: Event Any = coerce eventId - notify :: [Subscription Any] -> ClickM () - notify [] = return () - notify (SubscriptionSimple {ss_event_id, ss_callback} : xs) - | ss_event_id == anyEventId = ss_callback (unsafeCoerce a) >> notify xs - | otherwise = notify xs - notify (SubscriptionAccum {sa_event_id, sa_callback, sa_accum_ref} : xs) - | sa_event_id == anyEventId = notifyAcc sa_callback sa_accum_ref >> notify xs - | otherwise = notify xs - notifyAcc :: forall b. (Any -> b -> ClickM b) -> IORef b -> ClickM () - notifyAcc k ref = do - acc <- liftIO $ readIORef ref - acc' <- k (unsafeCoerce a) acc - liftIO $ writeIORef ref acc' - defer :: Event a -> ClickM () -> InternalState -> InternalState - defer k act s = s {transaction_queue = Map.insert (coerce k) act s.transaction_queue} - -newScope :: ResourceScope -> InternalState -> (InternalState, ResourceScope) -newScope p s = - let scopeId = ResourceScope $ s.next_id - finalizers = ScopeFinalizer p scopeId : s.finalizers - s' = s {finalizers, next_id = s.next_id + 1} - in (s', scopeId) - -newVarId :: ResourceScope -> InternalState -> (InternalState, VarId) -newVarId e s = (s {next_id = s.next_id + 1}, VarId e $ Int32Le s.next_id) - -freeScope :: - Bool -> - ResourceScope -> - InternalState -> (InternalState, [Finalizer]) -freeScope unlink rscope s = - let chkSub s = subscriptionScope s /= rscope - chkFin True ScopeFinalizer{sf_resource_scope, sf_linked_scope} = - sf_resource_scope /= rscope && sf_linked_scope /= rscope - chkFin True CustomFinalizer{cf_resource_scope} = cf_resource_scope /= rscope - chkFin False f = finalizerScope f /= rscope - (finalizers, scopeFns) = List.partition (chkFin unlink) s.finalizers - subscriptions = List.filter chkSub s.subscriptions - in (s {subscriptions, finalizers}, scopeFns) - -installFinalizer :: ClickM () -> ResourceScope -> InternalState -> InternalState -installFinalizer k scope s = s {finalizers = CustomFinalizer scope k : s.finalizers} - -subscribe :: forall a. DynVal a -> (a -> ClickM ()) -> ClickM () -subscribe (ConstVal _) _ = return () -subscribe (FromVar (SourceVar srcid _)) k = reactive_ g where - g scope s = s {subscriptions = SubscriptionSimple scope (coerce srcid) (k . unsafeCoerce) : s.subscriptions } -subscribe (FromVar (OverrideVar _ var)) k = - subscribe (FromVar var) k -subscribe (FromVar (LensMap l var)) k = - subscribe (FromVar var) (k . getConst . l Const) -subscribe (MapVal v f) k = subscribe v (k . f) -subscribe (MapHoldVal _ _ srcid ref) k = reactive_ g where - g scope s = s {subscriptions = SubscriptionSimple scope (coerce srcid) (k . unsafeCoerce) : s.subscriptions } -subscribe (SplatVal fv av) k = do - src <- reactive h - subscribe fv $ f src - subscribe av $ g src - where - h scope s = (s', coerce event) where - s' = s - { subscriptions = newsub : s.subscriptions - , next_id = s.next_id + 1 - } - event = unsafeFromEventId $ EventId s.next_id - newsub = SubscriptionSimple scope event (k . unsafeCoerce) - f src fv' = do - av' <- readVal av - modify $ triggerEvent src $ fv' av' - g src av' = do - fv' <- readVal fv - modify $ triggerEvent src $ fv' av' -subscribe (OverrideSub f d) k = f subscribe' k' where - k' a _ = k a - subscribe' k = subscribe d \a -> k a () - -subscribeAccum :: DynVal a -> (a -> b -> ClickM b) -> b -> ClickM () -subscribeAccum (ConstVal _) _ _ = return () -subscribeAccum (FromVar (SourceVar srcid _)) k b = do - ref <- liftIO $ newIORef b - let newSub scope = SubscriptionAccum scope (coerce srcid) (k . unsafeCoerce) ref - let g scope s = s {subscriptions = newSub scope : s.subscriptions} - reactive_ g -subscribeAccum (FromVar (OverrideVar _ var)) k b = - subscribeAccum (FromVar var) k b -subscribeAccum (FromVar (LensMap l var)) k b = - subscribeAccum (FromVar var) (k . getConst . l Const) b -subscribeAccum (MapVal v f) k b = subscribeAccum v (k . f) b -subscribeAccum (MapHoldVal _ _ srcid ref) k b = do - ref <- liftIO $ newIORef b - let newSub scope = SubscriptionAccum scope (coerce srcid) (k . unsafeCoerce) ref - let g scope s = s {subscriptions = newSub scope : s.subscriptions} - reactive_ g -subscribeAccum (SplatVal fv av) k b = do - ref <- liftIO $ newIORef b - let - h scope s = (s', coerce event) where - s' = s - { subscriptions = newsub : s.subscriptions - , next_id = s.next_id + 1 - } - event = unsafeFromEventId $ EventId s.next_id - newsub = SubscriptionAccum scope event (k . unsafeCoerce) ref - f src fv' = do - av' <- readVal av - modify $ triggerEvent src $ fv' av' - g src av' = do - fv' <- readVal fv - modify $ triggerEvent src $ fv' av' - src <- reactive h - subscribe fv $ f src - subscribe av $ g src -subscribeAccum (OverrideSub f a) k b = f (flip (subscribeAccum a) b) k - -readVal :: MonadIO m => DynVal a -> m a -readVal (ConstVal a) = pure a -readVal (FromVar var) = readVar var -readVal (MapVal val f) = fmap f $ readVal val -readVal (MapHoldVal _ _ _ ref) = liftIO $ readIORef ref -readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) -readVal (OverrideSub _ a) = readVal a - -readVar :: MonadIO m => DynVar a -> m a -readVar (SourceVar _ ref) = liftIO $ readIORef ref -readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var -readVar (OverrideVar _ var) = readVar var - -newCallback :: - (a -> ClickM ()) -> - ResourceScope -> - InternalState -> (InternalState, Event a) -newCallback k rscope s = - let - event = unsafeFromEventId $ EventId s.next_id - new = SubscriptionSimple rscope (coerce event) (k . unsafeCoerce) - subscriptions = new : s.subscriptions - in - (s { next_id = s.next_id + 1, subscriptions}, event) - -launchClickM :: InternalEnv -> ClickM a -> IO a -launchClickM env = flip runReaderT env . unClickT . (<* syncPoint) . trampoline - --- | Loop until transaction_queue is empty. --- --- This makes possible to implement @Applicative DynVal@ without --- redundantly firing callback for the final result. TODO: Is this --- even worth-while to have? What if just let multiple DOM changes --- when it depends on multiple sources? -trampoline :: ClickM a -> ClickM a -trampoline act = loop0 act where - loop0 :: ClickM a -> ClickM a - loop0 before = do - r <- before - mcont <- popQueue - forM_ mcont loop1 - return r - loop1 :: ClickM () -> ClickM () - loop1 before = do - before - mcont <- popQueue - forM_ mcont loop1 - popQueue :: ClickM (Maybe (ClickM ())) - popQueue = state \s -> - case Map.minViewWithKey s.transaction_queue of - Nothing -> (Nothing, s) - Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) - -syncPoint :: ClickM () -syncPoint = do - eval_expr <- asks (.eval_expr) - queue <- state \s -> (s.evaluation_queue, s {evaluation_queue = []}) - unless (List.null queue) do - liftIO $ eval_expr $ RevSeq queue - return () - -reactive :: (ResourceScope -> InternalState -> (InternalState, a)) -> ClickM a -reactive f = ClickT $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ f e.scope - -reactive_ :: (ResourceScope -> InternalState -> InternalState) -> ClickM () -reactive_ f = reactive \scope s -> (f scope s, ()) - -data ClientMessage - = BrowserMessage JavaScriptMessage - -- ^ Regular command received from JavaScript environment - | DevServerMessage (ClickM ()) - -- ^ Bypass protocol and inject a command directly into the - -- DevServer instance (useful for delivering notifications under - -- devserver) - -mapHoldVal :: (a -> b) -> DynVal a -> ClickM (DynVal b) -mapHoldVal f da = do - a <- readVal da - ref <- liftIO $ newIORef $ f a - reactive $ g ref - where - g ref scope s = (s', val) where - event = unsafeFromEventId $ EventId s.next_id - newSub = SubscriptionSimple scope (coerce event) (k . unsafeCoerce) - k a = do - let b = f a - liftIO $ writeIORef ref b - modify $ triggerEvent event b - s' = s {subscriptions = newSub : s.subscriptions, next_id = succ s.next_id} - val = MapHoldVal da f event ref - -unsafeInsertHtml :: Text -> Expr -unsafeInsertHtml rawHtml = Eval - "(function(builder, rawHtml){\ - \var div = document.createElement('div');\ - \div.innerHTML = rawHtml;\ - \var iter = div.childNodes[0];\ - \for (; iter; iter = div.childNodes[0]) {\ - \ div.removeChild(iter);\ - \ if (builder instanceof Comment) {\ - \ builder.parentElement.insertBefore(iter, builder);\ - \ } else{\ - \ builder.appendChild(iter);\ - \ }\ - \}\ - \})" `Apply` [AskDomBuilder, Str rawHtml] diff --git a/src/Clickable/Main/Dev.hs b/src/Clickable/Main/Dev.hs deleted file mode 100644 index 72e7f81..0000000 --- a/src/Clickable/Main/Dev.hs +++ /dev/null @@ -1,328 +0,0 @@ -module Clickable.Main.Dev where - -import Control.Concurrent -import Control.Concurrent.Async -import Control.Exception -import Control.Monad -import Control.Monad.State -import Data.Binary qualified as Binary -import Data.ByteString as BS -import Data.ByteString.Builder (Builder) -import Data.ByteString.Builder qualified as Builder -import Data.ByteString.Lazy qualified as BSL -import Data.Function -import Data.IORef -import Data.List qualified as List -import Data.Map (Map) -import Data.Map qualified as Map -import Data.Maybe -import Data.Tuple -import Data.Typeable -import Data.Word -import Foreign.Store -import GHC.Conc.Sync -import GHC.Generics -import GHC.IO.Exception -import Network.HTTP.Types as H -import Network.Wai as WAI -import Network.Wai.Application.Static -import Network.Wai.Handler.Warp qualified as Warp -import Network.Wai.Handler.WebSockets -import Network.WebSockets -import System.Environment -import System.IO - -import "this" Clickable.Internal (ClientMessage(..)) -import "this" Clickable.Internal qualified as Internal -import "this" Clickable.Protocol -import "this" Clickable.Protocol.Value -import "this" Clickable.Types - - -data DevConfig a = DevConfig - { aquire_resource :: IO a - -- ^ Called once the GHCi session is loaded. Returns a polymorphic - -- resource that typically contains a database connection and other - -- long-lived entities that persist across versions when the - -- application is reloaded. - , release_resource :: a -> IO () - -- ^ Runs before the ghci session is unloaded - , reload_app :: a -> IO ApplicationSpec - -- ^ Given resource of type 'a', initialize instances of client and - -- server applications. Runs each time ghci session reloads - , html_template :: HtmlTemplateArgs -> Builder - -- ^ Template for index.html, receives the current URL origin - -- (protocol + host) - , docroots :: [FilePath] - -- ^ List of directories to use with wai-static middleware, could be - -- empty, usually be used like docroots = ["./public"] - , warp_settings :: Warp.Settings - } deriving Generic - -data ApplicationSpec = ApplicationSpec - { client_app :: ConnectionInfo -> StartFlags -> ClickM () - , server_app :: Application - , connection_lost :: ConnectionInfo -> IO () - -- ^ Will be executed after a connection closes - } deriving Generic - -defaultConfig :: (ConnectionInfo -> StartFlags -> ClickM ()) -> DevConfig () -defaultConfig clientApp = DevConfig - { aquire_resource = pure () - , release_resource = const (pure ()) - , reload_app = \_ -> pure $ ApplicationSpec clientApp fallbackApp (const (pure ())) - , html_template = htmlTemplate - , docroots = [] - , warp_settings = Warp.defaultSettings - } - -runSettings :: Typeable resource => DevConfig resource -> IO () -runSettings cfg = do - -- Using a random constant as the key for Foreign.Store - let storeId = 183 - hSetBuffering stderr LineBuffering - lookupStore storeId >>= \case - Nothing -> do - inst <- newInstance cfg - writeStore (Store storeId) inst - let - useCurrentApp req resp = do - RunningApp{devserver_config, server_app} <- readIORef inst.app_state_ref - withStaticApp devserver_config.docroots server_app req resp - forkIfRepl $ tryPort cfg.warp_settings $ - middleware inst useCurrentApp - Just store -> do - oldInst <- readStore store - updateInstance cfg oldInst - conns <- readIORef oldInst.conn_state_ref - forM_ conns \conn -> - sendDataMessage conn.connection . Binary $ Binary.encode HotReload - where - tryPort :: Warp.Settings -> Application -> IO () - tryPort settings application = do - hPutStrLn stderr $ "Running a Dev Server at http://localhost:" <> - show (Warp.getPort settings) <> "/" - result <- try $ Warp.runSettings settings application - case result of - Right () -> return () - Left (e::IOException) - | ioe_type e == ResourceBusy -> do - hPutStrLn stderr $ "Already in use, trying next port…" - tryPort (Warp.setPort (Warp.getPort settings + 1) settings) application - | otherwise -> throwIO e - withStaticApp :: [FilePath] -> Middleware - withStaticApp [] next = next - withStaticApp (docroot:docroots) next = - staticApp (defaultFileServerSettings docroot) - {ss404Handler = Just (withStaticApp docroots next)} - forkIfRepl action = do - isRepl <- (== "") <$> getProgName - if isRepl then void (forkIO action) else action - -runDev :: (ConnectionInfo -> StartFlags -> ClickM ()) -> IO () -runDev clientApp = runSettings $ defaultConfig clientApp - -middleware :: DevInstance -> Middleware -middleware opts next req resp = - case pathInfo req of - [] -> indexHtml req resp - ["index.html"] -> indexHtml req resp - ["dev.sock"] -> devserverApp req resp - _ -> next req resp - where - devserverApp = - websocketsOr defaultConnectionOptions (websocketApp opts) - fallbackApp - indexHtml req resp = do - let devSocket = mkWebsocketUrl req - RunningApp{devserver_config} <- readIORef opts.app_state_ref - resp $ responseBuilder status200 - [(hContentType, "text/html; charset=utf-8")] $ - devserver_config.html_template $ HtmlTemplateArgs indexBundleJs devSocket - -mkWebsocketUrl :: WAI.Request -> ByteString -mkWebsocketUrl req = - WAI.requestHeaders req - & List.lookup "Host" - & fromMaybe "localhost" - & ((if WAI.isSecure req then "wss://" else "ws://") <>) - & (<> "/dev.sock") - -data HtmlTemplateArgs = HtmlTemplateArgs - { js_runtime :: ByteString - , ws_url :: ByteString - } - -htmlTemplate :: HtmlTemplateArgs -> Builder -htmlTemplate hta = - "\n\ - \ \n\ - \ \n\ - \ \n\ - \\n" - -fallbackApp :: Application -fallbackApp _ resp = - resp $ responseLBS status404 - [(hContentType, "text/html; charset=utf-8")] - "\n\ - \ \n\ - \

Not Found

\n\ - \ \n\ - \\n" - -websocketApp :: DevInstance -> ServerApp -websocketApp opt p = - let - acceptConn = mdo - conn <- acceptRequest p - newConn conn - dropConn connInfo = do - modifyIORef' opt.conn_state_ref $ Map.delete connInfo.connection_id - runningApp <- readIORef opt.app_state_ref - runningApp.connection_lost connInfo - receive c = - try @ConnectionException (receiveData c) - loop connInfo = do - runningApp <- readIORef opt.app_state_ref - raceResult <- race (receive connInfo.connection) (readChan connInfo.command_chan) - case raceResult of - Left (Right (incomingBytes::ByteString)) -> do - let jsMessage = Binary.decode . BSL.fromStrict $ incomingBytes - reader connInfo runningApp $ BrowserMessage jsMessage - loop connInfo - Left (Left (_::ConnectionException)) -> - return () - Right jsAction -> do - reader connInfo runningApp $ DevServerMessage jsAction - loop connInfo - - reader :: ConnectionInfo -> RunningApp -> ClientMessage -> IO () - reader conn app = \case - BrowserMessage (Start flags) -> void $ forkIO - $ Internal.launchClickM conn.internal_env - $ app.client_app conn flags - BrowserMessage (Return tid val) -> do - mmvar <- atomicModifyIORef' conn.threads_ref $ - swap . Map.alterF (,Nothing) (fromIntegral tid.unInt32Le) - forM_ mmvar \mvar -> - void $ tryPutMVar mvar val - BrowserMessage (TriggerEventMsg arg eid) -> void $ forkIO - $ Internal.launchClickM conn.internal_env - $ modify (Internal.triggerEvent (unsafeFromEventId eid) arg) - BrowserMessage BeforeUnload -> - return () - DevServerMessage a -> void $ forkIO - $ Internal.launchClickM conn.internal_env a - - newConn connection = mdo - command_chan <- newChan - threads_ref <- newIORef Map.empty - internal_env <- newInternalEnv connection threads_ref - connInfo <- atomicModifyIORef' opt.conn_state_ref \m -> - let - connection_id = Map.lookupMax m & maybe 0 (succ . fst) - connInfo = ConnectionInfo - { internal_env - , connection - , command_chan - , connection_id - , threads_ref } - in - (Map.insert connection_id connInfo m, connInfo) - return connInfo - newInternalEnv :: Connection -> IORef (Map Word64 (MVar Value)) -> IO InternalEnv - newInternalEnv conn awaiting = - Internal.newInternalEnv \expr -> do - tid <- fmap fromThreadId myThreadId - sendDataMessage conn . Binary . Binary.encode $ EvalExpr (Int32Le (fromIntegral tid)) expr - mvar <- newEmptyMVar - modifyIORef' awaiting $ Map.insert tid mvar - takeMVar mvar - in - bracket acceptConn dropConn \connInfo -> - withPingThread connInfo.connection 30 (pure ()) $ loop connInfo - -newInstance :: Typeable resource => DevConfig resource -> IO DevInstance -newInstance cfg = do - resource <- cfg.aquire_resource - appSpec <- cfg.reload_app resource - app_state_ref <- newIORef RunningApp - { resource - , devserver_config = cfg - , client_app = appSpec.client_app - , server_app = appSpec.server_app - , connection_lost = appSpec.connection_lost - } - conn_state_ref <- newIORef Map.empty - return DevInstance {conn_state_ref, app_state_ref} - -updateInstance - :: Typeable resource - => DevConfig resource - -> DevInstance - -> IO () -updateInstance cfg devInst = do - let - tryOldResource :: forall a. Typeable a => DevConfig a -> - RunningApp -> Either (IO ()) a - tryOldResource _ RunningApp {resource, devserver_config} - | Just Refl <- eqResource @a resource = Right resource - | otherwise = Left (devserver_config.release_resource resource) - eqResource :: forall a b. (Typeable a, Typeable b) => b -> Maybe (a :~: b) - eqResource _ = eqT @a @b - oldApp <- readIORef devInst.app_state_ref - case tryOldResource cfg oldApp of - Right oldResource -> do - appSpec <- cfg.reload_app oldResource - writeIORef devInst.app_state_ref RunningApp - { resource = oldResource - , devserver_config = cfg - , client_app = appSpec.client_app - , server_app = appSpec.server_app - , connection_lost = appSpec.connection_lost - } - Left releaseOld -> do - releaseOld - newResource <- cfg.aquire_resource - appSpec <- cfg.reload_app newResource - writeIORef devInst.app_state_ref RunningApp - { resource = newResource - , devserver_config = cfg - , client_app = appSpec.client_app - , server_app = appSpec.server_app - , connection_lost = appSpec.connection_lost - } - -data DevInstance = DevInstance - { conn_state_ref :: IORef (Map ConnectionId ConnectionInfo) - , app_state_ref :: IORef RunningApp - } deriving Generic - -data ConnectionInfo = ConnectionInfo - { connection :: Connection - , threads_ref :: IORef (Map Word64 (MVar Value)) - , internal_env :: InternalEnv - , command_chan :: Chan (ClickM ()) - -- ^ Writing to the Chan sends a command to the browser to execute - , connection_id :: ConnectionId - } deriving Generic - -data RunningApp = forall a. Typeable a => RunningApp - { resource :: a - , devserver_config :: DevConfig a - , client_app :: ConnectionInfo -> StartFlags -> ClickM () - , server_app :: Application - , connection_lost :: ConnectionInfo -> IO () - } - -newtype ConnectionId = ConnectionId {unConnectionId :: Int} - deriving newtype (Ord, Show, Eq, Num, Enum) - --- | Run @yarn run webpack --mode production@ and copy contents here --- from @./dist-newstyle/index.bundle.js@ -indexBundleJs :: ByteString -indexBundleJs = "(()=>{\"use strict\";var __webpack_modules__={924:(e,t,r)=>{r.d(t,{BN:()=>v,D:()=>C,Gk:()=>U,HA:()=>I,HQ:()=>A,In:()=>S,K2:()=>L,PV:()=>j,Sj:()=>B,Tf:()=>k,YE:()=>m,YO:()=>K,Yj:()=>R,b9:()=>W,g1:()=>V,l8:()=>w,tB:()=>H});var n=r(366);class _{encode(e){const t=h(this,e),r=new Uint8Array(t);return P(this,r,0,e),r}decode(e){const[t,r]=O(this,e,0);return t}}class a extends _{}class s extends _{}class i extends _{}class o extends _{}class l extends _{}class c extends _{}class u extends _{}class p extends _{}class d extends _{}class E extends _{}class f extends _{}class g extends _{}class b extends _{constructor(e){super(),this._element=e}}class D extends _{constructor(e){super(),this._description=e}}class T extends _{constructor(e){super(),this._alternatives=e}}class y extends _{constructor(e){super(),this._self=e}}class M extends _{constructor(e){super(),this._tuple=e}}function h(e,t){if(e instanceof a)return 1;if(e instanceof s)return 2;if(e instanceof i)return 4;if(e instanceof o)return 8;if(e instanceof l)return 1;if(e instanceof c)return 2;if(e instanceof u)return 4;if(e instanceof p)return 8;if(e instanceof d)return 4;if(e instanceof E)return 8;if(e instanceof g){const e=t;return 8+(new TextEncoder).encode(e).length}if(e instanceof f)return 8+t.length;if(e instanceof b){const r=8;return t.reduce(((t,r)=>t+h(e._element,r)),r)}if(e instanceof D){const r=t;return Object.keys(e._description).reduce(((t,n)=>t+h(e._description[n],r[n])),0)}if(e instanceof T){const r=t;return x(Object.keys(e._alternatives).length)+h(e._alternatives[r.tag],r)}if(e instanceof y)return h(e._self,t);if(e instanceof M){const r=t;return e._tuple.reduce(((e,t,n)=>e+h(t,r[n])),0)}return(0,n.G)(e)}function O(e,t,r){const _=new DataView(t.buffer);if(e instanceof a)return[_.getInt8(r),r+1];if(e instanceof s)return[_.getInt16(r,!0),r+2];if(e instanceof i)return[_.getInt32(r,!0),r+4];if(e instanceof o)return[_.getBigInt64(r,!0),r+8];if(e instanceof l)return[t[r],r+1];if(e instanceof c)return[_.getUint8(r),r+1];if(e instanceof u)return[_.getUint32(r,!0),r+4];if(e instanceof p)return[_.getBigUint64(r,!0),r+8];if(e instanceof d)return[_.getFloat32(r,!0),r+4];if(e instanceof E)return[_.getFloat64(r,!0),r+8];if(e instanceof g){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),n=t.subarray(r+8,r+8+e);return[new TextDecoder(\"utf8\").decode(n),r+8+e]}if(e instanceof f){const e=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56);return[t.subarray(r+8,r+8+e),r+8+e]}if(e instanceof b){const n=t[r+7]+(t[r+6]<<8)+(t[r+5]<<16)+(t[r+4]<<24)+(t[r+3]<<32)+(t[r+2]<<40)+(t[r+1]<<48)+(t[r]<<56),_=[];let a=r+8;for(let r=0;r{const[_,a]=O(r,t,n);return n=a,[e,_]}))),n]}if(e instanceof T){const n=x(Object.keys(e._alternatives).length),[_,a]=function(e,t,r){if(1!=e)throw new Error(\"Unimplemented\");return[t[r],r+1]}(n,t,r),[s,i]=O(e._alternatives[_],t,a);return s.tag=_,[s,i]}if(e instanceof y)return O(e._self,t,r);if(e instanceof M){let n=r;return[e._tuple.map((e=>{const[r,_]=O(e,t,n);return n=_,r})),n]}return(0,n.G)(e)}function P(e,t,r,_){const h=new DataView(t.buffer);if(e instanceof a)return h.setInt8(r,_),r+1;if(e instanceof s)return h.setInt16(r,_,!0),r+2;if(e instanceof i)return h.setInt32(r,_,!0),r+4;if(e instanceof o)return h.setBigInt64(r,_,!0),r+8;if(e instanceof l)return h.setUint8(r,_),r+1;if(e instanceof c)return h.setUint16(r,_,!0),r+2;if(e instanceof u)return h.setUint32(r,_,!0),r+4;if(e instanceof p)return h.setBigUint64(r,_,!0),r+8;if(e instanceof d)return h.setFloat32(r,_,!0),r+4;if(e instanceof E)return h.setFloat64(r,_,!0),r+8;if(e instanceof g){const e=_,n=(new TextEncoder).encode(e),a=n.length;return t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255,t.set(n,r+8),r+8+a}if(e instanceof f){const e=_,n=e.length;return t[r+7]=255&n,t[r+6]=n>>8&255,t[r+5]=n>>16&255,t[r+4]=n>>24&255,t.set(e,r+8),r+8+n}if(e instanceof b){const n=_,a=n.length;t[r+7]=255&a,t[r+6]=a>>8&255,t[r+5]=a>>16&255,t[r+4]=a>>24&255;let s=r+8;for(let r=0;r{a=P(e,t,a,n[r])})),a}return(0,n.G)(e)}function x(e){return Math.ceil(Math.log2(e)/8)}const m=new a,w=new s,I=new i,U=new o,A=new l,B=new c,L=new u,C=new p,S=new d,v=new E,R=new g,W=new f;function K(e){return new b(e)}function V(e){return new D(e)}function k(e){return new T(e)}function j(...e){return new M(e)}function H(e){const t=new y(void 0),r=e(t);return t._self=r,r}var N;!function(e){e[e.Nothing=0]=\"Nothing\",e[e.Just=1]=\"Just\"}(N||(N={}))},366:(e,t,r)=>{function n(e){throw new Error(\"absurd: unreachable code\")}r.d(t,{G:()=>n,Y:()=>_});class _{constructor(){this.counter=0,this.map=new Map}push(e){const t=this.counter++;return this.map.set(t,e),t}set(e,t){this.map.set(e,t)}get(e){return this.map.get(e)}delete(e){return this.map.delete(e)}has(e){return this.map.has(e)}clear(){this.map.clear()}keys(){return this.map.keys()}values(){return this.map.values()}entries(){return this.map.entries()}forEach(e,t){this.map.forEach(e,t)}}},933:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Am:()=>evalUint8Array,I4:()=>HaskellMessageTag,bR:()=>javascriptMessage,bp:()=>unknownToValue,dB:()=>JavaScriptMessageTag,sy:()=>haskellMessage,wL:()=>evalExpr});var _binary__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(924),_lib__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(366),ValueTag;function Cons(e,t){return[e,t]}function car(e){return e[0]}function cdr(e){return e[1]}function evalExpr(e,t={}){return evalLoop(t.haskellCallback||(()=>{}),t.idenScope||globalContext,t.argScope||null,t.builderScope||null,e)}function evalUint8Array(e,t={}){return evalExpr(expr.decode(e),t)}function evalLoop(hscb,idenScope,argScope,builderScope,exp){var _a;switch(exp.tag){case ExprTag.Null:return null;case ExprTag.Boolean:return 0!=exp[0];case ExprTag.I8:case ExprTag.I16:case ExprTag.I32:case ExprTag.I64:case ExprTag.U8:case ExprTag.U16:case ExprTag.U32:case ExprTag.U64:case ExprTag.F32:case ExprTag.F64:case ExprTag.Str:return exp[0];case ExprTag.Arr:return exp[0].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope));case ExprTag.Obj:return Object.fromEntries(exp[0].map((([e,t])=>[e,evalLoop(hscb,idenScope,argScope,builderScope,t)])));case ExprTag.U8Arr:return exp[0];case ExprTag.Dot:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return e[exp[1]]}case ExprTag.SetProp:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[2]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return t[exp[1]]=e,e}case ExprTag.Ix:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.exp);return e[exp.ix]}case ExprTag.Plus:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e+t}case ExprTag.Subtract:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e-t}case ExprTag.Multiply:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e*t}case ExprTag.Divide:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=evalLoop(hscb,idenScope,argScope,builderScope,exp[1]);return e/t}case ExprTag.Id:{const e=exp[0];for(let t=idenScope;t;t=cdr(t)){const r=car(t);if(e in r)return r[e]}throw new Error(\"Variable not in scope: \"+exp[0])}case ExprTag.Lam:return function(){return evalLoop(hscb,idenScope,Cons(arguments,argScope),builderScope,exp.body)};case ExprTag.Arg:{let e=argScope,t=0;for(;e;){if(t==exp.scopeIx){const t=car(e);return t[exp.argIx]}e=cdr(e),t++}throw new Error(\"Argument scope out of a range: \"+exp.scopeIx)}case ExprTag.Apply:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]);return e.apply(void 0,exp[1].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope)))}case ExprTag.Call:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp[0]),t=e[exp[1]];return t.apply(e,exp[2].map(evalLoop.bind(void 0,hscb,idenScope,argScope,builderScope)))}case ExprTag.AssignVar:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.rhs);if(varStorage.has(exp.scopeId)){const t=varStorage.get(exp.scopeId);t.set(exp.varId,e)}else{const t=new Map;t.set(exp.varId,e),varStorage.set(exp.scopeId,t)}return e}case ExprTag.FreeVar:{const e=varStorage.get(exp.scopeId);return e?(e.delete(exp.varId),0==e.size&&varStorage.delete(exp.scopeId),null):null}case ExprTag.Var:return null===(_a=varStorage.get(exp.scopeId))||void 0===_a?void 0:_a.get(exp.varId);case ExprTag.FreeScope:{varStorage.delete(exp.scopeId);const e=finalizers.get(exp.scopeId);return finalizers.delete(exp.scopeId),e&&e.forEach((e=>e())),null}case ExprTag.AskDomBuilder:if(null==builderScope)throw new Error(\"AskDomBuilder called without prior SupplyDomBuilder!\");return builderScope[0];case ExprTag.SupplyDomBuilder:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.builder),t=Cons(e,builderScope);return evalLoop(hscb,idenScope,argScope,t,exp.expr)}case ExprTag.InsertNode:{if(null==builderScope)throw new Error(\"InsertNode called without prior SupplyDomBuilder!\");const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.child);return domHelpers.insertIntoBuilder(builderScope[0],e),null}case ExprTag.ElementProp:{if(null==builderScope)throw new Error(\"ElementProp called without prior SupplyDomBuilder!\");const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.propValue);return domHelpers.assignProperty(builderScope[0],exp.propName,e),null}case ExprTag.ElementAttr:if(null==builderScope)throw new Error(\"ElementAttr called without prior SupplyDomBuilder!\");return domHelpers.assignAttribute(builderScope[0],exp.attrName,exp.attrValue),null;case ExprTag.ClassListAdd:{if(null==builderScope)throw new Error(\"InsertClassList called without prior SupplyDomBuilder!\");const e=domHelpers.domBuilderElement(builderScope[0]);return exp.classList.forEach((t=>e.classList.add(t))),null}case ExprTag.ClassListRemove:{if(null==builderScope)throw new Error(\"RemoveClassList called without prior SupplyDomBuilder!\");const e=domHelpers.domBuilderElement(builderScope[0]);return exp.classList.forEach((t=>e.classList.remove(t))),null}case ExprTag.InsertBrackets:if(null==builderScope)throw new Error(\"InsertBoundary called without prior SupplyDomBuilder!\");return domHelpers.insertBrackets(builderScope[0]);case ExprTag.ClearBrackets:if(null==builderScope)throw new Error(\"InsertBoundary called without prior SupplyDomBuilder!\");return domHelpers.clearBrackets(builderScope[0],Boolean(exp.detach));case ExprTag.CreateElement:return document.createElement(exp.tagName);case ExprTag.CreateElementNS:return document.createElementNS(exp.ns,exp.tagName);case ExprTag.CreateTextNode:return document.createTextNode(exp.content);case ExprTag.UpdateTextNode:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.node);return e.textContent=exp.content,null}case ExprTag.AddEventListener:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.target),t=evalLoop(hscb,idenScope,argScope,builderScope,exp.eventName),r=evalLoop(hscb,idenScope,argScope,builderScope,exp.listener);domHelpers.addEventListener(e,t,r);const n=finalizers.get(exp.reactiveScope),_=n||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return n||finalizers.set(exp.reactiveScope,_),_.push((()=>domHelpers.removeEventListener(e,t,r)))}case ExprTag.ConnectResource:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.aquire),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;return t||finalizers.set(exp.reactiveScope,r),r.push(e)}case ExprTag.SetTimeout:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.callback),t=finalizers.get(exp.reactiveScope),r=t||new _lib__WEBPACK_IMPORTED_MODULE_1__.Y;t||finalizers.set(exp.reactiveScope,r);let n=null;const _=r.push((()=>n&&clearTimeout(n)));return n=setTimeout((()=>{r.delete(_),n=null,e()}),exp.timeout),_}case ExprTag.ApplyFinalizer:{const e=finalizers.get(exp.reactiveScope),t=evalLoop(hscb,idenScope,argScope,builderScope,exp.finalizerId);if(!e)return!1;const r=e.get(t);return!!r&&(e.delete(t),r(),!0)}case ExprTag.RevSeq:return exp.exprs.reduceRight(((e,t)=>evalLoop(hscb,idenScope,argScope,builderScope,t)),null);case ExprTag.Eval:return eval(exp.rawJavaScript);case ExprTag.TriggerEvent:{const e=evalLoop(hscb,idenScope,argScope,builderScope,exp.arg),t={tag:JavaScriptMessageTag.TriggerEventMsg,arg:unknownToValue(e),callbackId:exp.callbackId};return hscb(t,argScope)}case ExprTag.UncaughtException:throw new Error(exp.message)}(0,_lib__WEBPACK_IMPORTED_MODULE_1__.G)(exp)}function unknownToValue(e){if(\"boolean\"==typeof e)return{tag:ValueTag.Vbool,0:e?1:0};if(\"number\"==typeof e)return Number.isInteger(e)?{tag:ValueTag.Vi32,0:e}:{tag:ValueTag.Vf64,0:e};if(\"string\"==typeof e)return{tag:ValueTag.Vstr,0:e};if(\"bigint\"==typeof e)return{tag:ValueTag.Vi64,0:e};if(Array.isArray(e))return{tag:ValueTag.Varr,0:e.map(unknownToValue)};if(e instanceof Uint8Array)return{tag:ValueTag.Vu8arr,0:e};if(null==e)return{tag:ValueTag.Vnull};const t=Object.entries(e).map((([e,t])=>[e,unknownToValue(t)]));return{tag:ValueTag.Vobj,0:t}}!function(e){e[e.Vnull=0]=\"Vnull\",e[e.Vbool=1]=\"Vbool\",e[e.Vi8=2]=\"Vi8\",e[e.Vi16=3]=\"Vi16\",e[e.Vi32=4]=\"Vi32\",e[e.Vi64=5]=\"Vi64\",e[e.Vu8=6]=\"Vu8\",e[e.Vu16=7]=\"Vu16\",e[e.Vu32=8]=\"Vu32\",e[e.Vu64=9]=\"Vu64\",e[e.Vf32=10]=\"Vf32\",e[e.Vf64=11]=\"Vf64\",e[e.Vstr=12]=\"Vstr\",e[e.Varr=13]=\"Varr\",e[e.Vobj=14]=\"Vobj\",e[e.Vu8arr=15]=\"Vu8arr\"}(ValueTag||(ValueTag={}));const jvalue=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ValueTag.Vnull]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ValueTag.Vbool]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ValueTag.Vi16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ValueTag.Vi32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ValueTag.Vi64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ValueTag.Vu8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ValueTag.Vu16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ValueTag.Vu32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ValueTag.Vu64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ValueTag.Vf32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ValueTag.Vf64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ValueTag.Vstr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ValueTag.Varr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ValueTag.Vobj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ValueTag.Vu8arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9})})));var ExprTag;!function(e){e[e.Null=0]=\"Null\",e[e.Boolean=1]=\"Boolean\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Plus=19]=\"Plus\",e[e.Subtract=20]=\"Subtract\",e[e.Multiply=21]=\"Multiply\",e[e.Divide=22]=\"Divide\",e[e.Id=23]=\"Id\",e[e.Lam=24]=\"Lam\",e[e.Arg=25]=\"Arg\",e[e.Apply=26]=\"Apply\",e[e.Call=27]=\"Call\",e[e.AssignVar=28]=\"AssignVar\",e[e.FreeVar=29]=\"FreeVar\",e[e.Var=30]=\"Var\",e[e.FreeScope=31]=\"FreeScope\",e[e.AskDomBuilder=32]=\"AskDomBuilder\",e[e.SupplyDomBuilder=33]=\"SupplyDomBuilder\",e[e.InsertNode=34]=\"InsertNode\",e[e.ElementProp=35]=\"ElementProp\",e[e.ElementAttr=36]=\"ElementAttr\",e[e.ClassListAdd=37]=\"ClassListAdd\",e[e.ClassListRemove=38]=\"ClassListRemove\",e[e.InsertBrackets=39]=\"InsertBrackets\",e[e.ClearBrackets=40]=\"ClearBrackets\",e[e.CreateElement=41]=\"CreateElement\",e[e.CreateElementNS=42]=\"CreateElementNS\",e[e.CreateTextNode=43]=\"CreateTextNode\",e[e.UpdateTextNode=44]=\"UpdateTextNode\",e[e.AddEventListener=45]=\"AddEventListener\",e[e.ConnectResource=46]=\"ConnectResource\",e[e.SetTimeout=47]=\"SetTimeout\",e[e.ApplyFinalizer=48]=\"ApplyFinalizer\",e[e.RevSeq=49]=\"RevSeq\",e[e.Eval=50]=\"Eval\",e[e.TriggerEvent=51]=\"TriggerEvent\",e[e.UncaughtException=52]=\"UncaughtException\"}(ExprTag||(ExprTag={}));const expr=_binary__WEBPACK_IMPORTED_MODULE_0__.tB((e=>_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[ExprTag.Null]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.Boolean]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.I16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.l8}),[ExprTag.I32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.I64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Gk}),[ExprTag.U8]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.HQ}),[ExprTag.U16]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Sj}),[ExprTag.U32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.K2}),[ExprTag.U64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.D}),[ExprTag.F32]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.In}),[ExprTag.F64]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.BN}),[ExprTag.Str]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Obj]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.PV(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,e))}),[ExprTag.U8Arr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.b9}),[ExprTag.Dot]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.SetProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:e}),[ExprTag.Ix]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exp:e,ix:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Plus]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Subtract]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Multiply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Divide]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:e}),[ExprTag.Id]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.Lam]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({body:e}),[ExprTag.Arg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE,argIx:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.Apply]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Call]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:e,1:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,2:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.AssignVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,rhs:e}),[ExprTag.FreeVar]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.Var]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,varId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.FreeScope]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({scopeId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.AskDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.SupplyDomBuilder]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({builder:e,expr:e}),[ExprTag.InsertNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({child:e}),[ExprTag.ElementProp]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({propName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,propValue:e}),[ExprTag.ElementAttr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({attrName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,attrValue:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.ClassListAdd]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.ClassListRemove]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({classList:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(_binary__WEBPACK_IMPORTED_MODULE_0__.Yj)}),[ExprTag.InsertBrackets]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[ExprTag.ClearBrackets]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({detach:_binary__WEBPACK_IMPORTED_MODULE_0__.YE}),[ExprTag.CreateElement]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateElementNS]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({ns:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj,tagName:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.CreateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.UpdateTextNode]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({node:e,content:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.AddEventListener]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,target:e,eventName:e,listener:e}),[ExprTag.ConnectResource]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,aquire:e}),[ExprTag.SetTimeout]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,callback:e,timeout:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[ExprTag.ApplyFinalizer]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({reactiveScope:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,finalizerId:e}),[ExprTag.RevSeq]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({exprs:_binary__WEBPACK_IMPORTED_MODULE_0__.YO(e)}),[ExprTag.Eval]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({rawJavaScript:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj}),[ExprTag.TriggerEvent]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,arg:e}),[ExprTag.UncaughtException]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({message:_binary__WEBPACK_IMPORTED_MODULE_0__.Yj})})));var HaskellMessageTag;!function(e){e[e.EvalExpr=0]=\"EvalExpr\",e[e.HotReload=1]=\"HotReload\",e[e.Halt=2]=\"Halt\"}(HaskellMessageTag||(HaskellMessageTag={}));const haskellMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[HaskellMessageTag.EvalExpr]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,expr}),[HaskellMessageTag.HotReload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({}),[HaskellMessageTag.Halt]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})});var JavaScriptMessageTag;!function(e){e[e.Start=0]=\"Start\",e[e.Return=1]=\"Return\",e[e.TriggerEventMsg=2]=\"TriggerEventMsg\",e[e.BeforeUnload=3]=\"BeforeUnload\"}(JavaScriptMessageTag||(JavaScriptMessageTag={}));const javascriptMessage=_binary__WEBPACK_IMPORTED_MODULE_0__.Tf({[JavaScriptMessageTag.Start]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({0:jvalue}),[JavaScriptMessageTag.Return]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({threadId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA,value:jvalue}),[JavaScriptMessageTag.TriggerEventMsg]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({arg:jvalue,callbackId:_binary__WEBPACK_IMPORTED_MODULE_0__.HA}),[JavaScriptMessageTag.BeforeUnload]:_binary__WEBPACK_IMPORTED_MODULE_0__.g1({})}),varStorage=new Map,finalizers=new Map,globalContext=[window,null];var domHelpers;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function r(e){return e instanceof Comment?e.parentElement:e}function n(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insertIntoBuilder=t,e.assignProperty=function(e,t,r){e instanceof Comment?e.parentElement[t]=r:e[t]=r},e.assignAttribute=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertBrackets=function(e){const r=document.createComment(\"ContentBrackets {{\"),n=document.createComment(\"}}\");return t(e,r),t(e,n),n},e.clearBrackets=function(e,t){if(e instanceof Comment){let _=0;for(;e.previousSibling&&(0!=_||!n(e.previousSibling));)(r=e.previousSibling)instanceof Comment&&\"}}\"==r.textContent?_++:n(e.previousSibling)&&_--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var r},e.domBuilderElement=r}(domHelpers||(domHelpers={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{function e(e,t,r,n){return new(r||(r=Promise))((function(_,a){function s(e){try{o(n.next(e))}catch(e){a(e)}}function i(e){try{o(n.throw(e))}catch(e){a(e)}}function o(e){var t;e.done?_(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(s,i)}o((n=n.apply(e,t||[])).next())}))}var t=__webpack_require__(366),r=__webpack_require__(933);const n=58;class _{static read_bytes(e,t){const r=new _;return r.buf=e.getUint32(t,!0),r.buf_len=e.getUint32(t+4,!0),r}static read_bytes_array(e,t,r){const n=[];for(let a=0;a{}}(void 0===e||e,this.prefix)}get enabled(){return this.isEnabled}constructor(e){this.isEnabled=e,this.prefix=\"wasi:\",this.enable(e)}}(!1);class l extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let c,u=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof l)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize()}constructor(e,t,r,n={}){this.args=[],this.env=[],this.fds=[],o.enable(n.debug),this.args=e,this.env=t,this.fds=r;const s=this;this.wasiImport={args_sizes_get(e,t){const r=new DataView(s.inst.exports.memory.buffer);r.setUint32(e,s.args.length,!0);let n=0;for(const e of s.args)n+=e.length+1;return r.setUint32(t,n,!0),o.log(r.getUint32(e,!0),r.getUint32(t,!0)),0},args_get(e,t){const r=new DataView(s.inst.exports.memory.buffer),n=new Uint8Array(s.inst.exports.memory.buffer),_=t;for(let _=0;_null!=s.fds[e]?s.fds[e].fd_advise(t,r,n):8,fd_allocate:(e,t,r)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,r):8,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return 8},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_datasync():8,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:r,fdstat:n}=s.fds[e].fd_fdstat_get();return null!=n&&n.write_bytes(new DataView(s.inst.exports.memory.buffer),t),r}return 8},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):8,fd_fdstat_set_rights:(e,t,r)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,r):8,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:r,filestat:n}=s.fds[e].fd_filestat_get();return null!=n&&n.write_bytes(new DataView(s.inst.exports.memory.buffer),t),r}return 8},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):8,fd_filestat_set_times:(e,t,r,n)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,r,n):8,fd_pread(e,t,r,n,a){const i=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=_.read_bytes_array(i,t,r),{ret:c,nread:u}=s.fds[e].fd_pread(o,l,n);return i.setUint32(a,u,!0),c}return 8},fd_prestat_get(e,t){const r=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:n,prestat:_}=s.fds[e].fd_prestat_get();return null!=_&&_.write_bytes(r,t),n}return 8},fd_prestat_dir_name(e,t,r){if(null!=s.fds[e]){const{ret:r,prestat_dir_name:n}=s.fds[e].fd_prestat_dir_name();return null!=n&&new Uint8Array(s.inst.exports.memory.buffer).set(n,t),r}return 8},fd_pwrite(e,t,r,n,_){const i=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=a.read_bytes_array(i,t,r),{ret:c,nwritten:u}=s.fds[e].fd_pwrite(o,l,n);return i.setUint32(_,u,!0),c}return 8},fd_read(e,t,r,n){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=_.read_bytes_array(a,t,r),{ret:l,nread:c}=s.fds[e].fd_read(i,o);return a.setUint32(n,c,!0),l}return 8},fd_readdir(e,t,r,n,_){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:l,dirent:c}=s.fds[e].fd_readdir_single(n);if(0!=l)return a.setUint32(_,o,!0),l;if(null==c)break;if(r-onull!=s.fds[e]?s.fds[e].fd_sync():8,fd_tell(e,t){const r=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:n,offset:_}=s.fds[e].fd_tell();return r.setBigUint64(t,_,!0),n}return 8},fd_write(e,t,r,n){const _=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=a.read_bytes_array(_,t,r),{ret:l,nwritten:c}=s.fds[e].fd_write(i,o);return _.setUint32(n,c,!0),l}return 8},path_create_directory(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_create_directory(_)}},path_filestat_get(e,t,r,n,_){const a=new DataView(s.inst.exports.memory.buffer),i=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(i.slice(r,r+n)),{ret:l,filestat:c}=s.fds[e].path_filestat_get(t,o);return null!=c&&c.write_bytes(a,_),l}return 8},path_filestat_set_times(e,t,r,n,_,a,i){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n));return s.fds[e].path_filestat_set_times(t,l,_,a,i)}return 8},path_link(e,t,r,n,_,a,i){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[_]){const l=new TextDecoder(\"utf-8\").decode(o.slice(r,r+n)),c=new TextDecoder(\"utf-8\").decode(o.slice(a,a+i));return s.fds[_].path_link(e,t,l,c)}return 8},path_open(e,t,r,n,_,a,i,l,c){const u=new DataView(s.inst.exports.memory.buffer),p=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const d=new TextDecoder(\"utf-8\").decode(p.slice(r,r+n));o.log(d);const{ret:E,fd_obj:f}=s.fds[e].path_open(t,d,_,a,i,l);if(0!=E)return E;s.fds.push(f);const g=s.fds.length-1;return u.setUint32(c,g,!0),0}return 8},path_readlink(e,t,r,n,_,a){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(l.slice(t,t+r));o.log(c);const{ret:u,data:p}=s.fds[e].path_readlink(c);if(null!=p){const e=(new TextEncoder).encode(p);if(e.length>_)return i.setUint32(a,0,!0),8;l.set(e,n),i.setUint32(a,e.length,!0)}return u}return 8},path_remove_directory(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_remove_directory(_)}return 8},path_rename(e,t,r,n,_,a){throw\"FIXME what is the best abstraction for this?\"},path_symlink(e,t,r,n,_){const a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[r]){const i=new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),o=new TextDecoder(\"utf-8\").decode(a.slice(n,n+_));return s.fds[r].path_symlink(i,o)}return 8},path_unlink_file(e,t,r){const n=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(n.slice(t,t+r));return s.fds[e].path_unlink_file(_)}return 8},poll_oneoff(e,t,r){throw\"async io not supported\"},proc_exit(e){throw new l(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const r=new Uint8Array(s.inst.exports.memory.buffer);for(let n=0;nthis.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-this.file_pos)),Number(this.file_pos)),this.file_pos+=BigInt(t.byteLength),r+=n.buf_len}return{ret:0,nwritten:r}}fd_pwrite(e,t,r){let n=0;if(this.file.readonly)return{ret:8,nwritten:n};for(const _ of t){const t=e.slice(_.buf,_.buf+_.buf_len);if(r+BigInt(t.byteLength)>this.file.size){const e=this.file.data;this.file.data=new Uint8Array(Number(r+BigInt(t.byteLength))),this.file.data.set(e)}this.file.data.set(t.slice(0,Number(this.file.size-r)),Number(r)),r+=BigInt(t.byteLength),n+=_.buf_len}return{ret:0,nwritten:n}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class E{open(e){const t=new d(this);return 1&e&&t.fd_seek(0n,2),t}get size(){return BigInt(this.data.byteLength)}stat(){return new i(4,this.size)}truncate(){return this.readonly?63:(this.data=new Uint8Array([]),0)}constructor(e,t){this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}class f{#e=0;#t=new Map;constructor(){}#r(){let e=this.#e;for(;;){if(!this.#t.has(e))return this.#e=e,e;e=e+1|0}}newJSVal(e){const t=this.#r();return this.#t.set(t,e),t}getJSVal(e){if(!this.#t.has(e))throw new WebAssembly.RuntimeError(`getJSVal(${e})`);return this.#t.get(e)}freeJSVal(e){if(!this.#t.delete(e))throw new WebAssembly.RuntimeError(`freeJSVal(${e})`)}}class g{#n=[];#_=new MessageChannel;constructor(){this.#_.port1.addEventListener(\"message\",(()=>{this.#n.pop()()})),this.#_.port1.start()}setImmediate(e,...t){this.#n.push((()=>e(...t))),this.#_.port2.postMessage(void 0)}}if(globalThis.setImmediate)c=globalThis.setImmediate;else{const e=new g;c=(t,...r)=>e.setImmediate(t,...r)}const b=e=>{const t=new f;return new FinalizationRegistry((t=>e.rts_freeStablePtr(t))),{newJSVal:e=>t.newJSVal(e),getJSVal:e=>t.getJSVal(e),freeJSVal:e=>t.freeJSVal(e),scheduleWork:()=>c(e.rts_schedulerLoop),ZC0ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:(t,r)=>{console.log(new TextDecoder(\"utf8\").decode(new Uint8Array(e.memory.buffer,t,r)))},ZC1ZChtmltzm0zi1zi0zi0zminplaceZCClickableziFFIZC:t=>function(e,t){const n=function(e,t){const r=new Uint8Array(e.memory.buffer,t),n=r[0]+(r[1]<<8)+(r[2]<<16)+(r[3]<<24)+(r[4]<<32)+(r[5]<<40)+(r[6]<<48)+(r[7]<<56),_=new Uint8Array(e.memory.buffer,t+8,n).slice().buffer;return new Uint8Array(_)}(e,t),_=r.sy.decode(n),a=t=>{const n=r.bR.encode(t),_=D(e,n);e.wasm_app(_)};switch(_.tag){case r.I4.EvalExpr:{const t=r.wL(_.expr,{haskellCallback:a}),n={tag:r.dB.Return,value:r.bp(t),threadId:_.threadId},s=r.bR.encode(n);return D(e,s)}case r.I4.HotReload:return window.location.reload(),0;case r.I4.Halt:return 0}}(e,t)}};function D(e,t){const r=t.byteLength,n=e.malloc(t.length+8);return new DataView(e.memory.buffer).setUint32(n,r,!0),new Uint8Array(e.memory.buffer,n+8,r).set(t),n}let T={};window.clickable={startWasm:function(t){return e(this,arguments,void 0,(function*(e,t=null){const n=new u([],[],[new d(new E([])),new d(new E([])),new d(new E([]))]),_=yield WebAssembly.compileStreaming(fetch(e)),a=yield WebAssembly.instantiate(_,{wasi_snapshot_preview1:n.wasiImport,ghc_wasm_jsffi:b(T)});Object.assign(T,a.exports),n.initialize(a),yield a.exports.hs_init();const s=r.bp(t),i={tag:r.dB.Start,0:s},o=r.bR.encode(i),l=D(T,o);yield a.exports.wasm_app(l),window.addEventListener(\"beforeunload\",(()=>{const e={tag:r.dB.BeforeUnload},t=r.bR.encode(e),n=D(T,t);T.wasm_app(n)}))}))},startDev:function(n,_=null){const a=new WebSocket(n),s=t=>e(this,void 0,void 0,(function*(){a.send(r.bR.encode(t))}));a.onopen=e=>{const t=r.bp(_),n=r.bR.encode({tag:r.dB.Start,0:t});a.send(n)},a.onmessage=n=>e(this,void 0,void 0,(function*(){const _=yield(a=n.data,new Promise(((e,t)=>{const r=new FileReader;r.onload=()=>{const t=r.result,n=new Uint8Array(t);e(n)},r.onerror=e=>{t(e)},r.readAsArrayBuffer(a)})));var a;!function(n,_){e(this,void 0,void 0,(function*(){switch(n.tag){case r.I4.EvalExpr:{const e=r.wL(n.expr,{haskellCallback:_}),t=r.bp(e),a={tag:r.dB.Return,value:t,threadId:n.threadId};return _(a)}case r.I4.HotReload:return void window.location.reload();case r.I4.Halt:return}(0,t.G)(n)}))}(r.sy.decode(_),s)})),a.onerror=e=>{console.error(\"WebSocket error:\",e)},a.onclose=e=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function e(t){const r=new WebSocket(n),_=Math.min(3e4,2*t);r.onopen=e=>window.location.reload(),r.onclose=r=>{setTimeout((()=>e(_)),t)}}(100)}},evalExpr:r.wL,evalUint8Array:r.Am}})()})();" diff --git a/src/Clickable/Main/Wasm.hs b/src/Clickable/Main/Wasm.hs deleted file mode 100644 index 352abe1..0000000 --- a/src/Clickable/Main/Wasm.hs +++ /dev/null @@ -1,67 +0,0 @@ -module Clickable.Main.Wasm where - -import Control.Monad.State -import Data.Binary (Binary) -import Data.Binary qualified as Binary -import Data.ByteString as BS -import Data.ByteString.Lazy qualified as BSL -import Data.ByteString.Unsafe qualified as BSU -import Data.Word -import Foreign.Marshal.Alloc qualified as Alloc -import Foreign.Marshal.Utils -import Foreign.Ptr -import Foreign.Storable -import System.IO.Unsafe - -import Clickable.FFI qualified as FFI -import Clickable.Protocol -import Clickable.Protocol.Value -import Clickable.Core -import Clickable.Internal qualified as Internal -import Clickable.Types - -runWasm :: (StartFlags -> ClickM ()) -> Ptr Word8 -> IO () -runWasm app p = mdo - jmsg <- loadMessage p - case jmsg of - Just (Start flags) -> - launchClickM internalEnv $ app flags - Just (TriggerEventMsg arg eid) -> - launchClickM internalEnv $ modify $ Internal.triggerEvent (unsafeFromEventId eid) arg - Just BeforeUnload -> - launchClickM internalEnv $ freeScope True $ ResourceScope Internal.emptyState.next_id - _ -> - return () - -internalEnv :: InternalEnv -internalEnv = unsafePerformIO $ Internal.newInternalEnv sendMessage - -sendMessage :: Expr -> IO Value -sendMessage expr = do - hptr <- storeByteString $ BSL.toStrict $ Binary.encode $ EvalExpr (Int32Le 0) expr - jptr <- FFI.js_evalMessage hptr - Alloc.free hptr - jmsg <- loadMessage jptr - case jmsg of - Just (Return _ v) -> return v - _ -> return Vnull - where - storeByteString :: ByteString -> IO (Ptr a) - storeByteString bs = do - let len = BS.length bs - dest <- Alloc.callocBytes (len + 8) - poke @Word64 dest (fromIntegral len) - BSU.unsafeUseAsCStringLen bs $ \(src, _) -> - copyBytes (dest `plusPtr` 8) src len - return (castPtr dest) - -loadMessage :: Binary msg => Ptr a -> IO (Maybe msg) -loadMessage p - | nullPtr /= p = fmap (Just . Binary.decode . BSL.fromStrict) . loadByteString $ p - | otherwise = return Nothing - where - loadByteString :: Ptr a -> IO ByteString - loadByteString ptr = do - len <- peek @Word64 (castPtr ptr) - let contentPtr = ptr `plusPtr` 8 - BSU.unsafePackCStringFinalizer contentPtr (fromIntegral len) (Alloc.free ptr) diff --git a/src/Clickable/Property.hs b/src/Clickable/Property.hs deleted file mode 100644 index dd8c205..0000000 --- a/src/Clickable/Property.hs +++ /dev/null @@ -1,366 +0,0 @@ -{-| -Shortcuts for common HTML5 attributes and properties --} -module Clickable.Property where - -import Clickable.Core -import Clickable.Types -import Data.Text - - --- TODO: Real-world usage has demonstrated that 'dynStyles' not --- sufficiently composable. For instance, if 'dynStyles' is used to --- set the CSS color for an element, essentially no other CSS property --- can be applied to this element, as they will be overwritten by --- 'dynStyles'. -dynStyles :: DynVal Text -> HtmlM () -dynStyles = dynProp "style" -{-# INLINE dynStyles #-} - -dynValue :: DynVal Text -> HtmlM () -dynValue = dynProp "value" -{-# INLINE dynValue #-} - -dynClass :: DynVal Text -> HtmlM () -dynClass = dynProp "className" -{-# INLINE dynClass #-} - -dynChecked :: DynVal Bool -> HtmlM () -dynChecked = dynProp "checked" -{-# INLINE dynChecked #-} - -dynDisabled :: DynVal Bool -> HtmlM () -dynDisabled = dynProp "disabled" -{-# INLINE dynDisabled #-} - -title_ :: Text -> HtmlM () -title_ = property "title" -{-# INLINE title_ #-} - -selected_ :: Bool -> HtmlM () -selected_ = property "selected" -{-# INLINE selected_ #-} - -hidden_ :: Bool -> HtmlM () -hidden_ = property "hidden" -{-# INLINE hidden_ #-} - -value_ :: Text -> HtmlM () -value_ = property "value" -{-# INLINE value_ #-} - -defaultValue_ :: Text -> HtmlM () -defaultValue_ = property "defaultValue" -{-# INLINE defaultValue_ #-} - -accept_ :: Text -> HtmlM () -accept_ = property "accept" -{-# INLINE accept_ #-} - -acceptCharset_ :: Text -> HtmlM () -acceptCharset_ = property "acceptCharset" -{-# INLINE acceptCharset_ #-} - -action_ :: Text -> HtmlM () -action_ = property "action" -{-# INLINE action_ #-} - -autocomplete_ :: Bool -> HtmlM () -autocomplete_ b = property @Text "autocomplete" (if b then "on" else "off") -{-# INLINE autocomplete_ #-} - -autosave_ :: Text -> HtmlM () -autosave_ = property "autosave" -{-# INLINE autosave_ #-} - -disabled_ :: Bool -> HtmlM () -disabled_ = property "disabled" -{-# INLINE disabled_ #-} - -enctype_ :: Text -> HtmlM () -enctype_ = property "enctype" -{-# INLINE enctype_ #-} - -formation_ :: Text -> HtmlM () -formation_ = property "formation" -{-# INLINE formation_ #-} - -list_ :: Text -> HtmlM () -list_ = property "list" -{-# INLINE list_ #-} - -maxlength_ :: Text -> HtmlM () -maxlength_ = property "maxlength" -{-# INLINE maxlength_ #-} - -minlength_ :: Text -> HtmlM () -minlength_ = property "minlength" -{-# INLINE minlength_ #-} - -method_ :: Text -> HtmlM () -method_ = property "method" -{-# INLINE method_ #-} - -multiple_ :: Bool -> HtmlM () -multiple_ = property "multiple" -{-# INLINE multiple_ #-} - -novalidate_ :: Bool -> HtmlM () -novalidate_ = property "noValidate" -{-# INLINE novalidate_ #-} - -pattern_ :: Text -> HtmlM () -pattern_ = property "pattern" -{-# INLINE pattern_ #-} - -readonly_ :: Bool -> HtmlM () -readonly_ = property "readOnly" -{-# INLINE readonly_ #-} - -required_ :: Bool -> HtmlM () -required_ = property "required" -{-# INLINE required_ #-} - -size_ :: Text -> HtmlM () -size_ = property "size" -{-# INLINE size_ #-} - -forProp_ :: Text -> HtmlM () -forProp_ = property "for" -{-# INLINE forProp_ #-} - -ref_ :: Text -> HtmlM () -ref_ = property "ref" -{-# INLINE ref_ #-} - -formProp_ :: Text -> HtmlM () -formProp_ = property "form" -{-# INLINE formProp_ #-} - -max_ :: Text -> HtmlM () -max_ = property "max" -{-# INLINE max_ #-} - -min_ :: Text -> HtmlM () -min_ = property "min" -{-# INLINE min_ #-} - -step_ :: Text -> HtmlM () -step_ = property "step" -{-# INLINE step_ #-} - -cols_ :: Text -> HtmlM () -cols_ = property "cols" -{-# INLINE cols_ #-} - -rows_ :: Text -> HtmlM () -rows_ = property "rows" -{-# INLINE rows_ #-} - -wrap_ :: Text -> HtmlM () -wrap_ = property "wrap" -{-# INLINE wrap_ #-} - -target_ :: Text -> HtmlM () -target_ = property "target" -{-# INLINE target_ #-} - -download_ :: Text -> HtmlM () -download_ = property "download" -{-# INLINE download_ #-} - -downloadAs_ :: Text -> HtmlM () -downloadAs_ = property "downloadAs" -{-# INLINE downloadAs_ #-} - -hreflang_ :: Text -> HtmlM () -hreflang_ = property "hreflang" -{-# INLINE hreflang_ #-} - -media_ :: Text -> HtmlM () -media_ = property "media" -{-# INLINE media_ #-} - -ping_ :: Text -> HtmlM () -ping_ = property "ping" -{-# INLINE ping_ #-} - -rel_ :: Text -> HtmlM () -rel_ = property "rel" -{-# INLINE rel_ #-} - -ismap_ :: Text -> HtmlM () -ismap_ = property "ismap" -{-# INLINE ismap_ #-} - -usemap_ :: Text -> HtmlM () -usemap_ = property "usemap" -{-# INLINE usemap_ #-} - -shape_ :: Text -> HtmlM () -shape_ = property "shape" -{-# INLINE shape_ #-} - -coords_ :: Text -> HtmlM () -coords_ = property "coords" -{-# INLINE coords_ #-} - -src_ :: Text -> HtmlM () -src_ = property "src" -{-# INLINE src_ #-} - -height_ :: Text -> HtmlM () -height_ = property "height" -{-# INLINE height_ #-} - -width_ :: Text -> HtmlM () -width_ = property "width" -{-# INLINE width_ #-} - -alt_ :: Text -> HtmlM () -alt_ = property "alt" -{-# INLINE alt_ #-} - -autoplay_ :: Bool -> HtmlM () -autoplay_ = property "autoplay" -{-# INLINE autoplay_ #-} - -controls_ :: Bool -> HtmlM () -controls_ = property "controls" -{-# INLINE controls_ #-} - -loop_ :: Bool -> HtmlM () -loop_ = property "loop" -{-# INLINE loop_ #-} - -preload_ :: Text -> HtmlM () -preload_ = property "preload" -{-# INLINE preload_ #-} - -poster_ :: Text -> HtmlM () -poster_ = property "poster" -{-# INLINE poster_ #-} - -default_ :: Bool -> HtmlM () -default_ = property "default" -{-# INLINE default_ #-} - -kind_ :: Text -> HtmlM () -kind_ = property "kind" -{-# INLINE kind_ #-} - -srclang_ :: Text -> HtmlM () -srclang_ = property "srclang" -{-# INLINE srclang_ #-} - -sandbox_ :: Text -> HtmlM () -sandbox_ = property "sandbox" -{-# INLINE sandbox_ #-} - -seamless_ :: Text -> HtmlM () -seamless_ = property "seamless" -{-# INLINE seamless_ #-} - -srcdoc_ :: Text -> HtmlM () -srcdoc_ = property "srcdoc" -{-# INLINE srcdoc_ #-} - -reversed_ :: Text -> HtmlM () -reversed_ = property "reversed" -{-# INLINE reversed_ #-} - -start_ :: Text -> HtmlM () -start_ = property "start" -{-# INLINE start_ #-} - -align_ :: Text -> HtmlM () -align_ = property "align" -{-# INLINE align_ #-} - -colspan_ :: Text -> HtmlM () -colspan_ = attribute "colspan" -{-# INLINE colspan_ #-} - -rowspan_ :: Text -> HtmlM () -rowspan_ = attribute "rowspan" -{-# INLINE rowspan_ #-} - -headers_ :: Text -> HtmlM () -headers_ = property "headers" -{-# INLINE headers_ #-} - -scope_ :: Text -> HtmlM () -scope_ = property "scope" -{-# INLINE scope_ #-} - -async_ :: Text -> HtmlM () -async_ = property "async" -{-# INLINE async_ #-} - -charset_ :: Text -> HtmlM () -charset_ = property "charset" -{-# INLINE charset_ #-} - -content_ :: Text -> HtmlM () -content_ = property "content" -{-# INLINE content_ #-} - -defer_ :: Text -> HtmlM () -defer_ = property "defer" -{-# INLINE defer_ #-} - -httpEquiv_ :: Text -> HtmlM () -httpEquiv_ = property "httpEquiv" -{-# INLINE httpEquiv_ #-} - -language_ :: Text -> HtmlM () -language_ = property "language" -{-# INLINE language_ #-} - -scoped_ :: Text -> HtmlM () -scoped_ = property "scoped" -{-# INLINE scoped_ #-} - -type_ :: Text -> HtmlM () -type_ = property "type" -{-# INLINE type_ #-} - -name_ :: Text -> HtmlM () -name_ = property "name" -{-# INLINE name_ #-} - -href_ :: Text -> HtmlM () -href_ = property "href" -{-# INLINE href_ #-} - -id_ :: Text -> HtmlM () -id_ = property "id" -{-# INLINE id_ #-} - -placeholder_ :: Text -> HtmlM () -placeholder_ = property "placeholder" -{-# INLINE placeholder_ #-} - -checked_ :: Bool -> HtmlM () -checked_ = property "checked" -{-# INLINE checked_ #-} - -autofocus_ :: Bool -> HtmlM () -autofocus_ = property "autofocus" -{-# INLINE autofocus_ #-} - -class_ :: Text -> HtmlM () -class_ = property "className" -{-# INLINE class_ #-} - -data_ :: Text -> Text -> HtmlM () -data_ k v = property ("data-" <> k) v -{-# INLINE data_ #-} - -role_ :: Text -> HtmlM () -role_ = attribute "role" -{-# INLINE role_ #-} - -style_ :: Text -> HtmlM () -style_ = property "style" -{-# INLINE style_ #-} diff --git a/src/Clickable/Protocol.hs b/src/Clickable/Protocol.hs deleted file mode 100644 index 754d449..0000000 --- a/src/Clickable/Protocol.hs +++ /dev/null @@ -1,210 +0,0 @@ -{-# LANGUAGE DerivingVia #-} -module Clickable.Protocol where - -import Data.Binary (Binary) -import Data.ByteString (ByteString) -import Data.Int -import Data.Text (Text) -import Data.String -import Data.Word -import GHC.Generics - -import Clickable.Protocol.Value - -data HaskellMessage - = EvalExpr I32 Expr - -- ^ Evaluate expression, expect the result to be returned by - -- 'Return' message - | HotReload - -- ^ Used under dev server, won't return anything - | Halt - -- ^ Signal that current process completed, won't return anything - deriving stock (Generic, Show) - deriving anyclass (Binary) - -data JavaScriptMessage - = Start StartFlags - | Return I32 Value - | TriggerEventMsg Value EventId - | BeforeUnload - -- ^ Fired from addEventListener("beforeunload") listener. Won't - -- work under the DevServer! - deriving (Generic, Show) - deriving anyclass (Binary) - -newtype StartFlags = StartFlags {unStartFlags :: Value} - deriving newtype (Generic, Show, Binary) - --- | Strict Lambda calculus with arbitrary side-effects, meant to be --- used as commands executed in the JavaScript side, optimized for --- non-blocking execution and minimizing round-trips. -data Expr - = Null - -- ^ null or undefined values - | Bool Bool - -- ^ JavaScript boolean value - | I8 Int8 - | I16 I16 - | I32 I32 - | I64 I64 - - | U8 Word8 - | U16 U16 - | U32 U32 - | U64 U64 - - | F32 F32 - | F64 F64 - - | Str Text -- ^ JavaScript string - | Arr [Expr] -- ^ JavaScript array - | Obj [(Text, Expr)] -- ^ JavaScript object - | U8Arr ByteString -- ^ Raw byte array - - | Dot Expr Text - -- ^ Read string property of an object. @(Dot (Id "document") - -- "body")@ is equivalent to @document.body@ JavaScript expression - | SetProp Expr Text Expr - -- ^ Assign a value to a string property of an object @(AssignProp - -- (Id "foo") "bar" (Str "baz"))@ is equivalent to @foo['bar'] = - -- baz;@ JavaScript expression. Evaluates into its right-hand side - -- expression. - | Ix Expr Int64 - -- ^ Read value from an integer index of an object. @(Ix (Id - -- "foo") 0)@ is equivalent to @foo[0]@ JavaScript expression - - | Plus Expr Expr - -- ^ Binary addition @(Add 256 5647)@ is equivalent to @256 + 5647@ - | Subtract Expr Expr - -- ^ Binary substraction @(Subtract 256 5647)@ is equivalent to @256 - 5647@ - | Multiply Expr Expr - -- ^ Binary multiplication @(Multiply 256 5647)@ is equivalent to @256 * 5647@ - | Divide Expr Expr - -- ^ Binary division @(Divide 256 5647)@ is equivalent to @256 / 5647@ - - | Id Text -- ^ Lookup an identifier in current lexical scope - | Lam Expr - -- ^ Introduce a lambda function. Arguments can be accessed via 'Arg - -- 0 0' - | Arg Word8 Word8 - -- ^ Lookup an argument in the current argument scope. Separate - -- scope for argument from regular lexical scope required for - -- performance reasons. First field is "De Bruijn index" pointing to - -- nth-lambda counting outward from current expression. Second - -- number is positional argument for that lambda (each lambda - -- receives multiple arguments in a vector, see - -- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments) - -- De Bruijn indicies are notoriously hard to write manually, it's - -- one of the reasons this protocol is much less convenient than FFI - -- with JavaScript. One solution I found is that for complex code I - -- write regular JavaScript and run it with 'Eval'. - | Apply Expr [Expr] - -- ^ Apply a function to arbitrary length arguments. @Apply (Id - -- "encodeURIComponent") [Str "#"]@ going to evaluate to @String "%23"@ - | Call Expr Text [Expr] - -- ^ Call a method of an object @Call (Id "console") "log" [Str - -- "Hi!"]@ is equivalent to @console.log('Hi!')@ JavaScript code - - | AssignVar VarId Expr - -- ^ Assign a value to VarId allocated in haskell side. This way - -- haskell can save certain values between WASM reactor invocations - | FreeVar VarId - -- ^ Free variable allocated with @AssignVar@ - | Var VarId - -- ^ Retrieve the value of the variable - | FreeScope ResourceScope - -- ^ Free all the resources assosiated with the given ResourceScope - - | AskDomBuilder - | SupplyDomBuilder DomBuilder Expr - - | InsertNode Expr - | ElementProp Text Expr - | ElementAttr Text Text - | ClassListAdd [Text] - | ClassListRemove [Text] - | InsertBrackets - | ClearBrackets Bool - - | CreateElement Text - | CreateElementNS Text Text - | CreateTextNode Text - | UpdateTextNode Expr Text - - | AddEventListener ResourceScope Expr Expr Expr - -- ^ @AddEventListener rscope target eventName listener@ is - -- equivalent to @target.addEventListener(eventName, listener)@ it - -- returns @FinalizerId@ integer identifier that can be used in - -- 'RemoveEventListener', but calling 'RemoveEventListener' is not - -- required, it'll be called authomatically when given ResourceScope - -- will be freed with 'FreeScope' - | ConnectResource ResourceScope Expr - -- ^ Returns FinalizerId - | SetTimeout ResourceScope Expr I32 - -- ^ Returns FinalizerId - | ApplyFinalizer ResourceScope Expr - -- ^ Actuate given finalizer before the ResourceScope is freed - - | RevSeq [Expr] - -- ^ Sequence of the expressions in reverse order. It will be - -- evaluated from the end to the beggining of the list. Returns - -- whatever the last expression (from the head of the list) - -- evaluates into. Order is reversed to support fast insertion of - -- new instructions - | Eval UnsafeJavaScript - -- ^ Evaluate arbitrary JavaScript code @(Eval "setTimeout(() => - -- console.log('Hi!'), 1000)")@ will print a message with one second - -- delay - | TriggerEvent EventId Expr - -- ^ Emits `TriggerEventMsg` as a side-effect - | UncaughtException Text - deriving stock (Generic, Show) - deriving anyclass (Binary) - -valueToExpr :: Value -> Expr -valueToExpr = \case - Vnull -> Null - Vbool a -> Bool a - - Vi8 a -> I8 a - Vi16 a -> I16 a - Vi32 a -> I32 a - Vi64 a -> I64 a - - Vu8 a -> U8 a - Vu16 a -> U16 a - Vu32 a -> U32 a - Vu64 a -> U64 a - - Vf64 a -> F64 a - Vf32 a -> F32 a - - Vstr a -> Str a - Varr xs -> Arr $ fmap valueToExpr xs - Vobj kv -> Obj $ fmap (\(k, v) -> (k, valueToExpr v)) kv - Vu8arr a -> U8Arr a - -toExpr :: ToValue a => a -> Expr -toExpr = valueToExpr . toValue - -newtype DomBuilder = DomBuilder {unDomBuilder :: Expr} - deriving newtype (Show, Binary) - -data VarId = VarId ResourceScope I32 - deriving stock (Generic, Show, Ord, Eq) - deriving anyclass (Binary) - -newtype FinalizerId = FinalizerId {unFinalizerId :: Int32} - deriving newtype (Show, Ord, Eq) - deriving Binary via I32 - -newtype ResourceScope = ResourceScope {unResourceScope :: Int32} - deriving newtype (Show, Ord, Eq) - deriving Binary via I32 - -newtype EventId = EventId {unEventId :: Int32} - deriving newtype (Show, Ord, Eq) - deriving Binary via I32 - -newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} - deriving newtype (IsString, Show, Semigroup, Monoid, Binary) diff --git a/src/Clickable/Protocol/Value.hs b/src/Clickable/Protocol/Value.hs deleted file mode 100644 index 0cfd723..0000000 --- a/src/Clickable/Protocol/Value.hs +++ /dev/null @@ -1,296 +0,0 @@ -module Clickable.Protocol.Value where - -import Data.Binary -import Data.Binary.Get -import Data.Binary.Put -import Data.ByteString -import Data.Kind -import Data.List qualified as List -import Data.Maybe -import Data.Text (Text) -import Data.Text qualified as Text -import GHC.Generics as G -import GHC.Int - -data Value - = Vnull - | Vbool Bool - | Vi8 Int8 - | Vi16 Int16Le - | Vi32 Int32Le - | Vi64 Int64Le - | Vu8 Word8 - | Vu16 Word16Le - | Vu32 Word32Le - | Vu64 Word64Le - | Vf32 Float32Le - | Vf64 Float64Le - | Vstr Text - | Varr [Value] - | Vobj [(Text, Value)] - | Vu8arr ByteString - deriving stock (Generic, Show) - deriving anyclass (Binary) - -class ToValue a where - toValue :: a -> Value - default toValue :: (Generic a, GToValue (Rep a)) => a -> Value - toValue = gToValue . G.from - -instance (Generic a, GToValue (Rep a)) => ToValue (Generically a) where - toValue = gToValue . G.from . (\(Generically x) -> x) - -instance ToValue Value where toValue = Prelude.id - -instance ToValue Bool where toValue = Vbool - -instance ToValue Int8 where toValue = Vi8 -instance ToValue Int16 where toValue = Vi16 . Int16Le -instance ToValue Int32 where toValue = Vi32 . Int32Le -instance ToValue Int64 where toValue = Vi64 . Int64Le - -instance ToValue Word8 where toValue = Vu8 -instance ToValue Word16 where toValue = Vu16 . Word16Le -instance ToValue Word32 where toValue = Vu32 . Word32Le -instance ToValue Word64 where toValue = Vu64 . Word64Le - -instance ToValue Float where toValue = Vf32 . Float32Le -instance ToValue Double where toValue = Vf64 . Float64Le - -instance ToValue Int where toValue = Vi64 . Int64Le . fromIntegral - -instance ToValue Char where - toValue c = Vstr $ Text.cons c Text.empty - -instance ToValue Text where toValue = Vstr - -instance ToValue ByteString where toValue = Vu8arr - -instance ToValue () where toValue _ = Vnull - -instance ToValue a => ToValue [a] where toValue = Varr . fmap toValue - -instance ToValue a => ToValue (Maybe a) where toValue = maybe Vnull toValue - -instance (ToValue a, ToValue b) => ToValue (a, b) where - toValue (a, b) = toValue [toValue a, toValue b] - -instance (ToValue a, ToValue b, ToValue c) => ToValue (a, b, c) where - toValue (a, b, c) = toValue [toValue a, toValue b, toValue c] --------------------------------------------------------------------------------- - -class FromValue a where - fromValue :: Value -> Maybe a - default fromValue :: (Generic a, GFromValue (Rep a)) => Value -> Maybe a - fromValue = fmap G.to . gFromValue - -instance (Generic a, GFromValue (Rep a)) => FromValue (Generically a) where - fromValue = fmap (Generically . G.to) . gFromValue - -instance FromValue Value where fromValue = pure - -instance FromValue Bool where - fromValue = \case Vbool a -> Just a; _ -> Nothing - -instance FromValue Int8 where - fromValue (Vi8 j) = Just j - fromValue _ = Nothing - -instance FromValue Int16 where - fromValue (Vi16 j) = Just j.unInt16Le - fromValue _ = Nothing - -instance FromValue Int32 where - fromValue = \case - Vi32 (Int32Le j) -> Just j - Vf64 j -> Just $ floor j.unFloat64Le - _ -> Nothing - -instance FromValue Int64 where - fromValue (Vi64 j) = Just j.unInt64Le - fromValue _ = Nothing - -instance FromValue Word8 where - fromValue (Vu8 j) = Just j - fromValue _ = Nothing - -instance FromValue Word16 where - fromValue (Vu16 j) = Just j.unWord16Le - fromValue _ = Nothing - -instance FromValue Word32 where - fromValue (Vu32 j) = Just j.unWord32Le - fromValue _ = Nothing - -instance FromValue Word64 where - fromValue (Vu64 j) = Just j.unWord64Le - fromValue _ = Nothing - -instance FromValue Float where - fromValue (Vf32 j) = Just j.unFloat32Le - fromValue _ = Nothing - -instance FromValue Double where - fromValue = \case - Vi32 j -> Just $ fromIntegral j.unInt32Le - Vf64 (Float64Le j) -> Just j - _ -> Nothing - -instance FromValue Int where - fromValue (Vi64 j) = Just $ fromIntegral j.unInt64Le - fromValue _ = Nothing - -instance FromValue Char where - fromValue = \case - Vstr a | Just (c, _) <- Text.uncons a -> Just c - | otherwise -> Nothing - _ -> Nothing - -instance FromValue Text where - fromValue = \case Vstr a -> Just a; _ -> Nothing - -instance FromValue ByteString where - fromValue = \case Vu8arr a -> Just a; _ -> Nothing - -instance FromValue () where - fromValue = \case Vnull -> Just (); _ -> Nothing - -instance FromValue a => FromValue [a] where - fromValue = \case - Varr xs -> Just (mapMaybe fromValue xs) - _ -> Nothing - -instance FromValue a => FromValue (Maybe a) where - fromValue = fmap Just . fromValue @a - -instance (FromValue a, FromValue b) => FromValue (a, b) where - fromValue j = fromValue j >>= \case - Just (a:b:_) -> (,) <$> fromValue a <*> fromValue b - _ -> Nothing - -instance (FromValue a, FromValue b, FromValue c) => FromValue (a, b, c) where - fromValue j = fromValue j >>= \case - Just (a:b:c:_) -> (,,) <$> fromValue a <*> fromValue b <*> fromValue c - _ -> Nothing --------------------------------------------------------------------------------- - -class GFromValue (f :: Type -> Type) where - gFromValue :: Value -> Maybe (f a) - -instance GFromValue f => GFromValue (M1 m c f) where - gFromValue = fmap M1 . gFromValue @f - -instance GFromValue U1 where - gFromValue _ = Just U1 - -instance GFromJSObject (x :*: y) => GFromValue (x :*: y) where - gFromValue (Vobj kvs) = gFromJSObject kvs - gFromValue _ = Nothing - -instance {-# OVERLAPPING #-} FromValue a => GFromValue (S1 s (Rec0 a)) where - gFromValue = fmap (M1 . K1) . fromValue @a --------------------------------------------------------------------------------- - -class GToValue (f :: Type -> Type) where - gToValue :: f x -> Value - -instance GToValue f => GToValue (M1 m c f) where - gToValue (M1 f) = gToValue f - -instance GToValue U1 where - gToValue _ = Vnull - -instance GToJSObject (x :*: y) => GToValue (x :*: y) where - gToValue (x :*: y) = Vobj $ gToJSObject (x :*: y) - -instance {-# OVERLAPPING #-} (ToValue a) => GToValue (S1 s (Rec0 a)) where - gToValue (M1 (K1 a)) = toValue a --------------------------------------------------------------------------------- - -class GToJSObject (f :: Type -> Type) where - gToJSObject :: f x -> [(Text, Value)] - -instance (GToJSObject x, GToJSObject y) => GToJSObject (x :*: y) where - gToJSObject (x :*: y) = gToJSObject x <> gToJSObject y - -instance (GToJSObject f) => GToJSObject (M1 m c f) where - gToJSObject (M1 a) = gToJSObject a - -instance {-# OVERLAPPING #-} (ToValue a, Selector s) => GToJSObject (S1 s (Rec0 a)) where - gToJSObject (M1 (K1 a)) = [(key, toValue a)] - where - key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) --------------------------------------------------------------------------------- - -class GFromJSObject (f :: Type -> Type) where - gFromJSObject :: [(Text, Value)] -> Maybe (f x) - -instance (GFromJSObject x, GFromJSObject y) => GFromJSObject (x :*: y) where - gFromJSObject kvs = liftA2 (:*:) (gFromJSObject kvs) (gFromJSObject kvs) - -instance (GFromJSObject f) => GFromJSObject (M1 m c f) where - gFromJSObject = fmap M1 . gFromJSObject - -instance {-# OVERLAPPING #-} (FromValue a, Selector s) => GFromJSObject (S1 s (Rec0 a)) where - gFromJSObject kvs = List.lookup key kvs >>= fmap (M1 . K1) . fromValue - where - key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) --------------------------------------------------------------------------------- - -newtype Float64Le = Float64Le {unFloat64Le :: Double} - deriving newtype (Show, Ord, Eq) - -instance Binary Float64Le where - put = putDoublele . unFloat64Le - get = fmap Float64Le getDoublele - -newtype Float32Le = Float32Le {unFloat32Le :: Float} - deriving newtype (Show, Ord, Eq) - -instance Binary Float32Le where - put = putFloatle . unFloat32Le - get = fmap Float32Le getFloatle --------------------------------------------------------------------------------- - -newtype Int16Le = Int16Le {unInt16Le :: Int16} - deriving newtype (Show, Ord, Eq) - -instance Binary Int16Le where - put = putInt16le . unInt16Le - get = fmap Int16Le getInt16le - -newtype Int32Le = Int32Le {unInt32Le :: Int32} - deriving newtype (Show, Ord, Eq) - -instance Binary Int32Le where - put = putInt32le . unInt32Le - get = fmap Int32Le getInt32le - -newtype Int64Le = Int64Le {unInt64Le :: Int64} - deriving newtype (Show, Ord, Eq) - -instance Binary Int64Le where - put = putInt64le . unInt64Le - get = fmap Int64Le getInt64le --------------------------------------------------------------------------------- - -newtype Word16Le = Word16Le {unWord16Le :: Word16} - deriving newtype (Show, Ord, Eq) - -instance Binary Word16Le where - put = putWord16le . unWord16Le - get = fmap Word16Le getWord16le - -newtype Word32Le = Word32Le {unWord32Le :: Word32} - deriving newtype (Show, Ord, Eq) - -instance Binary Word32Le where - put = putWord32le . unWord32Le - get = fmap Word32Le getWord32le - -newtype Word64Le = Word64Le {unWord64Le :: Word64} - deriving newtype (Show, Ord, Eq) - -instance Binary Word64Le where - put = putWord64le . unWord64Le - get = fmap Word64Le getWord64le diff --git a/src/Clickable/Types.hs b/src/Clickable/Types.hs deleted file mode 100644 index 51d3dcc..0000000 --- a/src/Clickable/Types.hs +++ /dev/null @@ -1,115 +0,0 @@ -module Clickable.Types where - -import Control.Monad.Reader -import Control.Monad.Catch -import Control.Monad.Fix -import Control.Monad.State -import Data.Binary -import Data.IORef -import Data.Tuple -import Data.Map (Map) -import GHC.Generics -import GHC.Exts -import GHC.Int - -import Clickable.Protocol -import Clickable.Protocol.Value - -newtype Event a = Event {unEvent :: EventId} - deriving newtype (Show, Ord, Eq, Binary) - -unsafeFromEventId :: EventId -> Event a -unsafeFromEventId = Event - -unsafeToEventId :: Event a -> EventId -unsafeToEventId = unEvent - -data DynVar a where - SourceVar :: Event a -> IORef a -> DynVar a - OverrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a - LensMap :: Lens' s a -> DynVar s -> DynVar a - -type UpdateFn s = forall a. (s -> (s, a)) -> ClickM a - -type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s - -data DynVal a where - ConstVal :: a -> DynVal a - FromVar :: DynVar a -> DynVal a - MapVal :: DynVal a -> (a -> b) -> DynVal b - MapHoldVal :: DynVal a -> (a -> b) -> Event b -> IORef b -> DynVal b - -- ^ todo: need redesign - SplatVal :: DynVal (a -> b) -> DynVal a -> DynVal b - OverrideSub :: (forall b. SubscribeFn a b -> SubscribeFn a b) -> DynVal a -> DynVal a - -type SubscribeFn a b = (a -> b -> ClickM b) -> ClickM () - -instance Functor DynVal where fmap = flip MapVal - -instance Applicative DynVal where pure = ConstVal; (<*>) = SplatVal - -fromVar :: DynVar a -> DynVal a -fromVar = FromVar - -newtype HtmlT m a = HtmlT {unHtmlT :: StateT (Maybe VarId) m a} - deriving newtype ( - Functor, Applicative, Monad, MonadIO, MonadFix, MonadTrans, - MonadCatch, MonadMask, MonadThrow - ) - -newtype ClickT m a = ClickT {unClickT :: ReaderT InternalEnv m a} - deriving newtype ( - Functor, Applicative, Monad, MonadIO, MonadFix, MonadReader InternalEnv, - MonadTrans, MonadCatch, MonadMask, MonadThrow - ) - -type HtmlM = HtmlT ClickM -type ClickM = ClickT IO - -instance MonadState InternalState ClickM where - state f = ClickT $ ReaderT $ \e -> atomicModifyIORef' e.internal_state_ref $ swap . f - -data InternalEnv = InternalEnv - { scope :: ResourceScope - , internal_state_ref :: IORef InternalState - , eval_expr :: Expr -> IO Value - } deriving (Generic) - -data InternalState = InternalState - { subscriptions :: [Subscription Any] - , finalizers :: [Finalizer] - , transaction_queue :: Map EventId (ClickM ()) - , evaluation_queue :: [Expr] - , next_id :: Int32 - } deriving (Generic) - -data Subscription a - = SubscriptionSimple - { ss_scope :: ResourceScope - , ss_event_id :: Event a - , ss_callback :: a -> ClickM () - } - | forall b. SubscriptionAccum - { sa_resource_scope :: ResourceScope - , sa_event_id :: Event a - , sa_callback :: a -> b -> ClickM b - , sa_accum_ref :: IORef b - } - -data Finalizer - = CustomFinalizer - { cf_resource_scope :: ResourceScope - , cf_callback :: ClickM () - } - | ScopeFinalizer - { sf_resource_scope :: ResourceScope - , sf_linked_scope :: ResourceScope - } - -finalizerScope :: Finalizer -> ResourceScope -finalizerScope CustomFinalizer{cf_resource_scope} = cf_resource_scope -finalizerScope ScopeFinalizer{sf_resource_scope} = sf_resource_scope - -subscriptionScope :: Subscription a -> ResourceScope -subscriptionScope SubscriptionSimple{ss_scope} = ss_scope -subscriptionScope SubscriptionAccum{sa_resource_scope} = sa_resource_scope diff --git a/src/Wasm/Compat/Prim.hs b/src/Wasm/Compat/Prim.hs deleted file mode 100644 index 76af87c..0000000 --- a/src/Wasm/Compat/Prim.hs +++ /dev/null @@ -1,76 +0,0 @@ -{-# LANGUAGE CPP #-} -{-# LANGUAGE GHC2021 #-} -{-# LANGUAGE MagicHash #-} -{-# LANGUAGE UnboxedTuples #-} -{-# LANGUAGE UnliftedNewtypes #-} - -#if defined(wasm32_HOST_ARCH) -module Wasm.Compat.Prim ( - module GHC.Wasm.Prim -) where -import GHC.Wasm.Prim -#else -module Wasm.Compat.Prim ( - JSVal#(..), - JSVal(..), - freeJSVal, - JSString (..), - fromJSString, - toJSString, - JSException (..), - WouldBlockException (..), - PromisePendingException (..), - mkJSCallback, - runIO, - runNonIO, -) where - -import Control.Exception -import GHC.Exts -import GHC.Stable - -newtype JSVal# - = JSVal# (Any :: UnliftedType) - -data JSVal - = forall a . JSVal JSVal# (Weak# JSVal#) (StablePtr# a) - -freeJSVal :: JSVal -> IO () -freeJSVal _ = error "freeJSVal: only implmented on Wasm Backend" - -newtype JSString = JSString JSVal - -fromJSString :: JSString -> String -fromJSString _ = error "fromJSString: only implmented on Wasm Backend" - -toJSString :: String -> JSString -toJSString _ = error "toJSString: only implmented on Wasm Backend" - -newtype JSException = JSException JSVal - -instance Show JSException where - showsPrec _ _ = error "showsPrec @JSException: only implmented on Wasm Backend" - -instance Exception JSException - -data WouldBlockException - = WouldBlockException - deriving (Show) - -instance Exception WouldBlockException - -data PromisePendingException - = PromisePendingException - deriving (Show) - -instance Exception PromisePendingException - -mkJSCallback :: (StablePtr a -> IO JSVal) -> a -> IO JSVal -mkJSCallback _ _ = error "mkJSCallback: only implmented on Wasm Backend" - -runIO :: (JSVal -> a -> IO ()) -> IO a -> IO JSVal -runIO _ _ = error "runIO: only implmented on Wasm Backend" - -runNonIO :: (JSVal -> a -> IO ()) -> a -> IO JSVal -runNonIO _ _ = error "runNonIO: only implmented on Wasm Backend" -#endif diff --git a/wasm.hs b/wasm.hs new file mode 100644 index 0000000..55b4d86 --- /dev/null +++ b/wasm.hs @@ -0,0 +1,59 @@ +{-# OPTIONS_GHC -Wno-unused-local-binds #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE RecursiveDo #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE StrictData #-} +{-# OPTIONS_GHC -Wno-unused-do-bind #-} +{-# LANGUAGE DataKinds #-} +module Main where + +import Clickable.Html +import Clickable.Internal +import Clickable.Types +import qualified Data.Text as Text +import Clickable.Wasm +import Data.Word +import Foreign (Ptr) +import Data.IORef +import Control.Monad.Reader + +test01 :: ClickM () +test01 = do + enqueueExpr $ PushStack $ Id "document" `Dot` "body" + counter <- newVar 0 + el "div" do + prop "className" (Str "container") + text "Lorem Ipsum" + el "h1" $ text "Fox jumps over a lazy dog" + el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" + el "button" do + text "Click Here" + on @"click" $ modifyVar_ counter succ + el "button" do + text "-" + on @"click" $ modifyVar_ counter pred + el "br" $ pure () + el "span" do + dynText $ fmap (Text.pack . show) $ fromVar counter + ref <- liftIO $ newIORef $ const $ pure () + el "div" do + el "button" do + text "Ask a Value" + on @"click" do + t <- asks (.hte_prompt_tag) + val <- liftIO $ control t \cont -> writeIORef ref cont + enqueueExpr $ Call (Id "console") "log" $ valueToExpr val + el "button" do + text "Fill the value" + on @"click" do + cont <- liftIO $ readIORef ref + liftIO $ cont $ pure $ Vobj [("this", Vstr "is"), ("some", Vstr "value")] + +main :: IO () +main = pure () + +foreign export ccall wasm_app :: Ptr Word8 -> IO (Ptr Word8) +wasm_app :: Ptr Word8 -> IO (Ptr Word8) +wasm_app = mkWasmApp test01 diff --git a/websocket.hs b/websocket.hs new file mode 100644 index 0000000..a13c7fe --- /dev/null +++ b/websocket.hs @@ -0,0 +1,62 @@ +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecursiveDo #-} +module Main where + +import Clickable.Html +import Clickable.Internal +import Clickable.Types +import Clickable.WebSocket +import Control.Monad.IO.Class +import Control.Monad.Reader +import Data.IORef +import Network.Wai.Handler.Warp (run) +import Unsafe.Coerce (unsafeCoerce) +import qualified Data.Text as Text + +test01 :: ClickM () +test01 = do + enqueueExpr $ PushStack $ Id "document" `Dot` "body" + counter <- newVar @Int 0 + el "div" do + prop "className" (Str "container") + text "Lorem Ipsum" + el "h1" $ text "Fox jumps over a lazy dog" + el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" + el "button" do + text "Click Here" + on @"click" $ modifyVar_ counter succ + el "button" do + text "-" + on @"click" $ modifyVar_ counter pred + el "br" $ pure () + el "span" do + dynText $ fmap (Text.pack . show) $ fromVar counter + ref <- liftIO $ newIORef $ const $ pure () + el "div" do + el "button" do + text "Ask a Value" + on @"click" do + t <- asks (.hte_prompt_tag) + val <- liftIO $ control t \cont -> writeIORef ref cont + enqueueExpr $ Call (Id "console") "log" $ val + el "button" do + text "Fill the value" + on @"click" do + cont <- liftIO $ readIORef ref + liftIO $ cont $ pure $ Obj [("this", Str "is"), ("some", Str "value")] + +main :: IO () +main = do + run 3000 $ runApp test01 + +baz :: IO Int +baz = do + let z :: Int = unsafeCoerce False + return $ z * 2 + +bar :: Int -> Int +bar dsfsd = dsfsd diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..954fb59 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,895 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@bjorn3/browser_wasi_shim@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@bjorn3/browser_wasi_shim/-/browser_wasi_shim-0.3.0.tgz#8aa310eed2298bab435bd1f73ab100fbc3f018da" + integrity sha512-FlRBYttPRLcWORzBe6g8nmYTafBkOEFeOqMYM4tAHJzFsQy4+xJA94z85a9BCs8S+Uzfh9LrkpII7DXr2iUVFg== + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@types/estree@^1.0.5": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + +"@types/json-schema@^7.0.8": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/node@*": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== + +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== + +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" + +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== + +"@webpack-cli/info@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== + +"@webpack-cli/serve@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== + +acorn@^8.7.1, acorn@^8.8.2: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.21.10: + version "4.24.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.0.tgz#a1325fe4bc80b64fda169629fc01b3d6cecd38d4" + integrity sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A== + dependencies: + caniuse-lite "^1.0.30001663" + electron-to-chromium "^1.5.28" + node-releases "^2.0.18" + update-browserslist-db "^1.1.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +caniuse-lite@^1.0.30001663: + version "1.0.30001667" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz#99fc5ea0d9c6e96897a104a8352604378377f949" + integrity sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw== + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chrome-trace-event@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +electron-to-chromium@^1.5.28: + version "1.5.33" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz#8f64698661240e70fdbc4b032e6085e391f05e09" + integrity sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA== + +enhanced-resolve@^5.0.0, enhanced-resolve@^5.17.1: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.7.3: + version "7.14.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" + integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== + +es-module-lexer@^1.2.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== + +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== + +is-core-module@^2.13.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" + integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== + dependencies: + hasown "^2.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +micromatch@^4.0.0: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" + integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.20.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +semver@^7.3.4: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser@^5.26.0: + version "5.34.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.34.1.tgz#af40386bdbe54af0d063e0670afd55c3105abeb6" + integrity sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-loader@^9.5.1: + version "9.5.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.5.1.tgz#63d5912a86312f1fbe32cef0859fb8b2193d9b89" + integrity sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" + source-map "^0.7.4" + +tslib@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + +typescript@^5.6.2: + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +update-browserslist-db@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" + integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +watchpack@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" + integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webpack-cli@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" + colorette "^2.0.14" + commander "^10.0.1" + cross-spawn "^7.0.3" + envinfo "^7.7.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^3.1.1" + rechoir "^0.8.0" + webpack-merge "^5.7.3" + +webpack-merge@^5.7.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.95.0: + version "5.95.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.95.0.tgz#8fd8c454fa60dad186fbe36c400a55848307b4c0" + integrity sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q== + dependencies: + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" + acorn "^8.7.1" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.17.1" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.11" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" + webpack-sources "^3.2.3" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== From 669bff58d2b6c601bb45154a9e241348b72de086 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 14 Oct 2024 23:55:11 +0400 Subject: [PATCH 54/64] WIP: upstream changes --- Clickable.hs | 1 - Clickable/Float.hs | 6 ++++ Clickable/Html.hs | 82 ++++++++++++++++++++++++++++++++---------- Clickable/Internal.hs | 21 ++++++++--- Clickable/Types.hs | 32 +++++++++++------ Clickable/Wasm.hs | 5 +-- Clickable/WebSocket.hs | 3 +- clickable.cabal | 1 - jsbits/#wasm.ts# | 66 ---------------------------------- jsbits/#websocket.ts# | 82 ------------------------------------------ jsbits/proto.ts | 28 ++++++++++----- jsbits/wasm.ts | 2 +- jsbits/websocket.ts | 4 +-- shell.nix | 70 ++++-------------------------------- websocket.hs | 57 ++++++++++++++--------------- 15 files changed, 170 insertions(+), 290 deletions(-) delete mode 100644 jsbits/#wasm.ts# delete mode 100644 jsbits/#websocket.ts# diff --git a/Clickable.hs b/Clickable.hs index 8a36d21..6422169 100644 --- a/Clickable.hs +++ b/Clickable.hs @@ -5,4 +5,3 @@ module Clickable (module Exports) where import Clickable.Html as Exports import Clickable.Internal as Exports import Clickable.Types as Exports -import Clickable.WebSocket as Exports diff --git a/Clickable/Float.hs b/Clickable/Float.hs index 470e6b9..5fe7069 100644 --- a/Clickable/Float.hs +++ b/Clickable/Float.hs @@ -1,4 +1,10 @@ +{-# LANGUAGE GHC2021 #-} {-# LANGUAGE StrictData #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnboxedTuples #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE DerivingStrategies #-} {-| Normal `Data.Binary.Binary` instances for floating-point numbers replacing the impractical and unnatural encoding in the default diff --git a/Clickable/Html.hs b/Clickable/Html.hs index 474f146..0e86bf0 100644 --- a/Clickable/Html.hs +++ b/Clickable/Html.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE GHC2021 #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE OverloadedRecordDot #-} @@ -7,9 +8,10 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} +{-# OPTIONS_GHC -Wall #-} module Clickable.Html where -import Clickable.Internal ( subscribe, readVal, reactive, newRefId, enqueueExpr, newRefIdOp ) +import Clickable.Internal import Clickable.Types import Control.Monad.Reader import Data.Binary qualified as Binary @@ -19,37 +21,59 @@ import Data.Text (Text) import GHC.Generics (Generic) import Unsafe.Coerce (unsafeCoerce) -el :: Text -> ClickM a -> ClickM a -el tagName child = ClickM \e -> do +el :: Text -> HtmlM a -> HtmlM a +el tagName child = HtmlM \s e -> do e.hte_send $ execPut $ Binary.put $ PushStack $ CreateElement tagName - r <- child.unClickM e + r <- child.unHtmlM s e e.hte_send $ execPut $ Binary.put PopIns pure r {-# INLINE el #-} -text :: Text -> ClickM () -text content = ClickM \e -> do +elns :: Text -> Text -> HtmlM a -> HtmlM a +elns ns tagName child = HtmlM \s e -> do + e.hte_send $ execPut $ Binary.put $ PushStack $ CreateElementNS ns tagName + r <- child.unHtmlM s e + e.hte_send $ execPut $ Binary.put PopIns + pure r +{-# INLINE elns #-} + +text :: Text -> HtmlM () +text content = HtmlM \s e -> do e.hte_send $ execPut $ Binary.put $ PushStack $ CreateTextNode content e.hte_send $ execPut $ Binary.put $ PopIns + return ((), s) {-# INLINE text #-} -dynText :: DynVal Text -> ClickM () -dynText contentDyn = ClickM \e -> do +dynText :: DynVal Text -> HtmlM () +dynText contentDyn = HtmlM \s e -> do c <- readVal contentDyn refId <- newRefId.unClickM e e.hte_send $ execPut $ Binary.put $ PushStack $ CreateTextNode c e.hte_send $ execPut $ Binary.put $ AssignRef refId (PeekStack 0) e.hte_send $ execPut $ Binary.put $ PopIns - (subscribe contentDyn \nval -> ClickM \_ -> - e.hte_send $ execPut $ Binary.put $ UpdateTextNode (Ref refId) nval - ).unClickM e + let k nval = ClickM \e' -> + e'.hte_send $ execPut $ Binary.put $ UpdateTextNode (Ref refId) nval + (subscribe contentDyn k).unClickM e + pure ((), s) {-# INLINEABLE dynText #-} -prop :: Text -> Expr -> ClickM () -prop k v = ClickM \e -> - e.hte_send $ execPut $ Binary.put $ ElementProp (PeekStack 0) k v +prop :: ToValue val => Text -> val -> HtmlM () +prop k v = HtmlM \s e -> do + e.hte_send $ execPut $ Binary.put $ ElementProp (PeekStack 0) k $ toValue v + pure ((), s) {-# INLINE prop #-} +dynProp :: ToValue val => Text -> DynVal val -> HtmlM () +dynProp propName dynVal = HtmlM \s e -> do + (refId, s') <- saveStackTip.unHtmlM s e + initVal <- readVal dynVal + e.hte_send $ execPut $ Binary.put $ ElementProp (PeekStack 0) propName $ toValue initVal + let k nval = ClickM \e' -> + e'.hte_send $ execPut $ Binary.put $ ElementProp (Ref refId) propName $ toValue nval + unClickM (subscribe dynVal k) e + pure ((), s') +{-# INLINE dynProp #-} + addEventListener :: (Event ValueExpr -> Expr) -> (ValueExpr -> ClickM ()) -> ClickM () addEventListener connectScript k = do e <- reactive \scope s -> @@ -57,7 +81,7 @@ addEventListener connectScript k = do eventId = EventId s.next_id (s', unSubRef) = newRefIdOp scope s {next_id = s.next_id + 1} newSub = SubscriptionSimple scope (unsafeFromEventId eventId) (k' . unsafeCoerce) - newFin = CustomFinalizer scope $ enqueueExpr $ Apply (Ref unSubRef) Null + newFin = CustomFinalizer scope $ enqueueExpr $ Apply (Ref unSubRef) [] s'' = s' {subscriptions = newSub : s.subscriptions, finalizers = newFin : s.finalizers} in (s'', AssignRef unSubRef (connectScript (Event eventId))) enqueueExpr e @@ -66,8 +90,8 @@ class IsEventName eventName where type EventListenerCb eventName :: Type connectEventName :: EventListenerCb eventName -> ClickM () -on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> ClickM () -on k = connectEventName @eventName k +on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HtmlM () +on k = liftClick $ connectEventName @eventName k instance IsEventName "click" where type EventListenerCb "click" = ClickM () @@ -88,7 +112,7 @@ defaultEventListenerOptions = EventListenerOptions genericEvent :: EventListenerOptions -> Text -> Event ValueExpr -> Expr genericEvent opt eventName (Event eventId) = Eval - ("(function([target, trigger]){\n\ + ("(function(target, trigger){\n\ \ function listener(event){\n\ \ " <> preventDefaultStmt <> "\n\ \ " <> stopPropagationStmt <> "\n\ @@ -96,7 +120,27 @@ genericEvent opt eventName (Event eventId) = \ }\n\ \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` Arr [PeekStack 0, Lam (TriggerEvent eventId Null)] + \})") `Apply` [PeekStack 0, Lam (TriggerEvent eventId Null)] where preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" + +attachHtml :: Expr -> HtmlM a -> ClickM a +attachHtml rootEl contents = ClickM \e -> do + e.hte_send $ execPut $ Binary.put $ PushStack rootEl + (r, _) <- contents.unHtmlM Nothing e + e.hte_send $ execPut $ Binary.put PopIns + pure r + +attachToBody :: HtmlM a -> ClickM a +attachToBody = attachHtml $ Id "document" `Dot` "body" + +saveStackTip :: HtmlM RefId +saveStackTip = HtmlM \s e -> + case s of + Nothing -> do + refId <- newRefId.unClickM e + e.hte_send $ execPut $ Binary.put $ AssignRef refId $ PeekStack 0 + return (refId, Just refId) + Just saved -> + pure (saved, s) diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index c369d7b..7cd033c 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE GHC2021 #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE BlockArguments #-} @@ -28,6 +29,20 @@ import Foreign.Ptr import GHC.Exts import Unsafe.Coerce +newEvent :: ClickM (Event a) +newEvent = state \s -> + (Event (EventId s.next_id), s {next_id = s.next_id + 1}) + +mapEvent :: (a -> b) -> Event a -> ClickM (Event b) +mapEvent f ea = do + eb <- newEvent + subscribeEvent ea $ triggerEvent eb . f + return eb + +subscribeEvent :: forall a. Event a -> (a -> ClickM ()) -> ClickM () +subscribeEvent (Event eid) k = reactive_ g where + newSub scope = SubscriptionSimple scope (coerce eid) (k . unsafeCoerce) + g scope s = s {subscriptions = newSub scope : s.subscriptions} subscribe :: forall a. DynVal a -> (a -> ClickM ()) -> ClickM () subscribe (ConstVal _) _ = return () @@ -131,9 +146,7 @@ syncPoint = ClickM \e -> void $ e.hte_flush unsafeInsertHtml :: Text -> Expr unsafeInsertHtml rawHtml = Eval - "(function(args){\ - \var parent = args[0];\ - \var rawHtml = args[1];\ + "(function(parent, rawHtml){\ \var div = document.createElement('div');\ \div.innerHTML = rawHtml;\ \var iter = div.childNodes[0];\ @@ -145,7 +158,7 @@ unsafeInsertHtml rawHtml = Eval \ parent.appendChild(iter);\ \ }\ \}\ - \})" `Apply` (Arr [PeekStack 0, Str rawHtml]) + \})" `Apply` [PeekStack 0, Str rawHtml] newScope :: ClickM ScopeId newScope = reactive newScopeOp diff --git a/Clickable/Types.hs b/Clickable/Types.hs index 11ff471..c82d948 100644 --- a/Clickable/Types.hs +++ b/Clickable/Types.hs @@ -1,13 +1,16 @@ +{-# LANGUAGE GHC2021 #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE BlockArguments #-} -{-# LANGUAGE DerivingVia #-} -{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DerivingVia #-} {-# LANGUAGE UndecidableInstances #-} -{-# LANGUAGE MagicHash #-} -{-# LANGUAGE UnboxedTuples #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# OPTIONS_GHC -Wall #-} module Clickable.Types where import Clickable.Float @@ -22,14 +25,14 @@ import Data.Int import Data.Map (Map) import Data.Maybe (mapMaybe) import Data.Text (Text) +import Data.Text qualified as Text import Data.Tuple import Data.Word import GHC.Exts -import GHC.Generics +import GHC.Generics qualified as G +import GHC.List qualified as List import GHC.Types -import qualified Data.Text as Text -import qualified GHC.Generics as G -import qualified GHC.List as List +import GHC.Generics newtype ClickM a = ClickM {unClickM :: InternalEnv -> IO a} deriving (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) @@ -59,6 +62,13 @@ data InternalState = InternalState , next_id :: Word32 } +newtype HtmlM a = HtmlM + {unHtmlM :: Maybe RefId -> InternalEnv -> IO (a, Maybe RefId)} + deriving (Functor, Applicative, Monad, MonadIO) via StateT (Maybe RefId) ClickM + +liftClick :: ClickM a -> HtmlM a +liftClick (ClickM a) = HtmlM \s e -> (,s) <$> a e + data Expr where Null :: Expr Bool :: Word8 -> Expr @@ -84,8 +94,8 @@ data Expr where Lam :: Expr -> Expr Arg :: Word8 -> Expr - Apply :: Expr -> Expr -> Expr - Call :: Expr -> Text -> Expr -> Expr + Apply :: Expr -> [Expr] -> Expr + Call :: Expr -> Text -> [Expr] -> Expr AssignRef :: RefId -> Expr -> Expr FreeRef :: RefId -> Expr @@ -214,7 +224,7 @@ subscriptionScope SubscriptionAccum{sa_resource_scope} = sa_resource_scope -- | JavaScript value, result of evaluating an 'Expr'. Should only -- contain constructors up to and including 'U8Arr'. I chose to use --- type alias rather than a new data type for easier conversion. +-- type alias rather than a data type for easier conversion. type ValueExpr = Expr class ToValue a where diff --git a/Clickable/Wasm.hs b/Clickable/Wasm.hs index 6ba50d6..2f4a896 100644 --- a/Clickable/Wasm.hs +++ b/Clickable/Wasm.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE GHC2024 #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE CPP #-} {-# LANGUAGE BlockArguments #-} @@ -33,7 +34,7 @@ foreign import ccall safe env :: InternalEnv {-# NOINLINE env #-} -continuations :: IORef (Map Word32 (IO Value -> IO ())) +continuations :: IORef (Map Word32 (IO ValueExpr -> IO ())) {-# NOINLINE continuations #-} buf :: CStringLen @@ -58,7 +59,7 @@ mkWasmApp app inmsg = do Just (ResumeMsg contId pload) -> do awatingThread <- atomicModifyIORef' continuations $ swap . Map.alterF (,Nothing) contId - forM_ awatingThread \cont -> cont $ pure $ exprToValue pload + forM_ awatingThread \cont -> cont $ pure pload _ -> error "mkWasmApp: Failed to parse incomming command" return $ castPtr $ fst buf diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index 4795673..717ce97 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE GHC2021 #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE BlockArguments #-} @@ -57,7 +58,7 @@ index content = jsrts :: Builder jsrts = - "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{AZ:()=>evalRange,JC:()=>ClientMsgTag,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalRange(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeValue(e,t),encodeValue(e,n)}))}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!0),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.InsPop=31]=\"InsPop\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DropBrackets=38]=\"DropBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateTextNode=41]=\"CreateTextNode\",e[e.UpdateTextNode=42]=\"UpdateTextNode\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.YieldResult=45]=\"YieldResult\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null){const n=new WebSocket(e),r={refs:new Map,stack:null};function s(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.EventMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))}function i(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.ResumeMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))}n.onopen=e=>{const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.StartMsg,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))},n.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.AZ({triggerEvent:s,resumeCont:i,persistent:r,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(3e4,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=Iovec.read_bytes_array(l,t,n);let o=0;for(const t of _){const{ret:n,data:_}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return l.setUint32(i,o,!0),n;if(a.set(_,t.buf),o+=_.length,r+=BigInt(_.length),_.length!=t.buf_len)break}return l.setUint32(i,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const l=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(l.slice(0,n),t),l.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=Ciovec.read_bytes_array(l,t,n);let o=0;for(const t of _){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:_,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(_!=ERRNO_SUCCESS)return l.setUint32(i,o,!0),_;if(o+=f,r+=BigInt(f),f!=n.byteLength)break}return l.setUint32(i,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const a=Iovec.read_bytes_array(i,t,n);let _=0;for(const t of a){const{ret:n,data:a}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,_,!0),n;if(l.set(a,t.buf),_+=a.length,a.length!=t.buf_len)break}return i.setUint32(r,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let _=0;for(;;){const{ret:o,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=o)return l.setUint32(i,_,!0),o;if(null==f)break;if(n-_null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const a=Ciovec.read_bytes_array(i,t,n);let _=0;for(const t of a){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:a,nwritten:o}=s.fds[e].fd_write(n);if(a!=ERRNO_SUCCESS)return i.setUint32(r,_,!0),a;if(_+=o,o!=n.byteLength)break}return i.setUint32(r,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(a.slice(n,n+r)),{ret:o,filestat:f}=s.fds[e].path_filestat_get(t,_);return null!=f&&f.write_bytes(l,i),o}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,l,a){const _=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(_.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,o,i,l,a)}return ERRNO_BADF},path_link(e,t,n,r,i,l,a){const _=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const o=new TextDecoder(\"utf-8\").decode(_.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(_.slice(l,l+a)),{ret:u,inode_obj:E}=s.fds[e].path_lookup(o,t);return null==E?u:s.fds[i].path_link(f,E,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,l,a,_,o){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const E=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(E);const{ret:c,fd_obj:R}=s.fds[e].path_open(t,E,i,l,a,_);if(0!=c)return c;s.fds.push(R);const d=s.fds.length-1;return f.setUint32(o,d,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,l){const a=new DataView(s.inst.exports.memory.buffer),_=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(_.slice(t,t+n));debug.log(o);const{ret:f,data:u}=s.fds[e].path_readlink(o);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return a.setUint32(l,0,!0),ERRNO_BADF;_.set(e,r),a.setUint32(l,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,l){const a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const _=new TextDecoder(\"utf-8\").decode(a.slice(t,t+n)),o=new TextDecoder(\"utf-8\").decode(a.slice(i,i+l));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(_);if(null==u)return f;if(f=s.fds[r].path_link(o,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(_,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const l=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(l.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(l.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:l,path:a}=Path.from(t);if(null==a)return{ret:l,fd_obj:null};let{ret:_,entry:o}=this.dir.get_entry_for_path(a);if(null==o){if(_!=ERRNO_NOENT)return{ret:_,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};o=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&o.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:o.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:l,filename:a,entry:_}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==l||null==a)return i;if(null!=_){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=_.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&_ instanceof Directory))return ERRNO_EXIST;if(0!=_.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||_.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(l.contents.set(a,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==l?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:l})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==l?r:l.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==l?r:l instanceof Directory&&l.stat().filetype===FILETYPE_DIRECTORY?0!==l.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:l,filename:a,entry:_}=this.get_parent_dir_and_entry_for_path(r,!0);return null==l||null==a?{ret:i,entry:null}:null!=_?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),l.contents.set(a,s),_=s,{ret:ERRNO_SUCCESS,entry:_})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null){const n=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]),r={refs:new Map,stack:null};function s(e,t){const n=new DataView(inst.exports.memory.buffer),s={triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)},resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},persistent:r,mem:n,isMutableMem:!0,begin:e,end:e+t};proto.AZ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:n.wasiImport,env:{clickable_eval_buffer:s}}))).then((e=>{inst=e,n.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}window.clickable={runWebsocket,runWasm}})();" + "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeValue(e,t),encodeValue(e,n)}))}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.InsPop=31]=\"InsPop\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DropBrackets=38]=\"DropBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateTextNode=41]=\"CreateTextNode\",e[e.UpdateTextNode=42]=\"UpdateTextNode\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.YieldResult=45]=\"YieldResult\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null){const n=new WebSocket(e),r={refs:new Map,stack:null};function s(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.EventMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))}function i(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.ResumeMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))}n.onopen=e=>{const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.StartMsg,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))},n.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({triggerEvent:s,resumeCont:i,persistent:r,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(3e4,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=Iovec.read_bytes_array(l,t,n);let o=0;for(const t of _){const{ret:n,data:_}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return l.setUint32(i,o,!0),n;if(a.set(_,t.buf),o+=_.length,r+=BigInt(_.length),_.length!=t.buf_len)break}return l.setUint32(i,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const l=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(l.slice(0,n),t),l.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=Ciovec.read_bytes_array(l,t,n);let o=0;for(const t of _){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:_,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(_!=ERRNO_SUCCESS)return l.setUint32(i,o,!0),_;if(o+=f,r+=BigInt(f),f!=n.byteLength)break}return l.setUint32(i,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const a=Iovec.read_bytes_array(i,t,n);let _=0;for(const t of a){const{ret:n,data:a}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,_,!0),n;if(l.set(a,t.buf),_+=a.length,a.length!=t.buf_len)break}return i.setUint32(r,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let _=0;for(;;){const{ret:o,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=o)return l.setUint32(i,_,!0),o;if(null==f)break;if(n-_null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const a=Ciovec.read_bytes_array(i,t,n);let _=0;for(const t of a){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:a,nwritten:o}=s.fds[e].fd_write(n);if(a!=ERRNO_SUCCESS)return i.setUint32(r,_,!0),a;if(_+=o,o!=n.byteLength)break}return i.setUint32(r,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(a.slice(n,n+r)),{ret:o,filestat:f}=s.fds[e].path_filestat_get(t,_);return null!=f&&f.write_bytes(l,i),o}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,l,a){const _=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(_.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,o,i,l,a)}return ERRNO_BADF},path_link(e,t,n,r,i,l,a){const _=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const o=new TextDecoder(\"utf-8\").decode(_.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(_.slice(l,l+a)),{ret:u,inode_obj:E}=s.fds[e].path_lookup(o,t);return null==E?u:s.fds[i].path_link(f,E,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,l,a,_,o){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const E=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(E);const{ret:c,fd_obj:R}=s.fds[e].path_open(t,E,i,l,a,_);if(0!=c)return c;s.fds.push(R);const d=s.fds.length-1;return f.setUint32(o,d,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,l){const a=new DataView(s.inst.exports.memory.buffer),_=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(_.slice(t,t+n));debug.log(o);const{ret:f,data:u}=s.fds[e].path_readlink(o);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return a.setUint32(l,0,!0),ERRNO_BADF;_.set(e,r),a.setUint32(l,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,l){const a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const _=new TextDecoder(\"utf-8\").decode(a.slice(t,t+n)),o=new TextDecoder(\"utf-8\").decode(a.slice(i,i+l));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(_);if(null==u)return f;if(f=s.fds[r].path_link(o,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(_,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const l=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(l.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(l.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:l,path:a}=Path.from(t);if(null==a)return{ret:l,fd_obj:null};let{ret:_,entry:o}=this.dir.get_entry_for_path(a);if(null==o){if(_!=ERRNO_NOENT)return{ret:_,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};o=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&o.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:o.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:l,filename:a,entry:_}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==l||null==a)return i;if(null!=_){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=_.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&_ instanceof Directory))return ERRNO_EXIST;if(0!=_.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||_.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(l.contents.set(a,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==l?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:l})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==l?r:l.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==l?r:l instanceof Directory&&l.stat().filetype===FILETYPE_DIRECTORY?0!==l.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:l,filename:a,entry:_}=this.get_parent_dir_and_entry_for_path(r,!0);return null==l||null==a?{ret:i,entry:null}:null!=_?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),l.contents.set(a,s),_=s,{ret:ERRNO_SUCCESS,entry:_})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null){const n=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]),r={refs:new Map,stack:null};function s(e,t){const n=new DataView(inst.exports.memory.buffer),s={triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)},resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},persistent:r,mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:n.wasiImport,env:{clickable_eval_buffer:s}}))).then((e=>{inst=e,n.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}window.clickable={runWebsocket,runWasm}})();" runApp :: ClickM () -> Application runApp app req respond = do diff --git a/clickable.cabal b/clickable.cabal index 12cb04a..e89d522 100644 --- a/clickable.cabal +++ b/clickable.cabal @@ -38,5 +38,4 @@ executable clickable wai-websockets, warp, websockets, - default-language: GHC2021 diff --git a/jsbits/#wasm.ts# b/jsbits/#wasm.ts# deleted file mode 100644 index b1bf8ab..0000000 --- a/jsbits/#wasm.ts# +++ /dev/null @@ -1,66 +0,0 @@ -import { WASI, File, OpenFile } from '@bjorn3/browser_wasi_shim'; -import { ClientMsgTag, EventId, EvalState, PersistentState, Ptr } from "./proto"; -import * as proto from "./proto"; - -let inst: WebAssembly.Instance; - -export function runWasm(wasmUri: string, startFlags: unknown = null) { - const wasi = new WASI([], [], [ - new OpenFile(new File([])), // stdin - new OpenFile(new File([])), // stdout - new OpenFile(new File([])), // stderr - ]); - - const persistent: PersistentState = { - refs: new Map(), - stack: null, - }; - - function clickable_eval_buffer(ptr: Ptr, len: number): void { - // @ts-ignore - const mem = new DataView(inst.exports.memory.buffer); - - function triggerEvent(eventId: EventId, arg: unknown) { - const encoderState = {mem, begin: ptr, end: ptr + len}; - proto.encodeClientMessage(encoderState, [ClientMsgTag.EventMsg, eventId, arg]); - // @ts-ignore - inst.exports.wasm_app(ptr); - }; - - function resumeCont(contId: number, res: unknown) { - const encoderState = {mem, begin: ptr, end: ptr + len}; - proto.encodeClientMessage(encoderState, [ClientMsgTag.ResumeMsg, contId, res]); - // @ts-ignore - inst.exports.wasm_app(ptr); - }; - - const intp: EvalState = { - triggerEvent, - resumeCont, - persistent, - mem, - isMutableMem: true, - begin: ptr, - end: ptr + len, - }; - - proto.evalMem(intp); - } - - WebAssembly.compileStreaming(fetch(wasmUri)) - .then(wasm => WebAssembly.instantiate(wasm, { - wasi_snapshot_preview1: wasi.wasiImport, - env: { - clickable_eval_buffer, - }, - })) - .then(inst1 => { - inst = inst1; - // @ts-ignore - wasi.initialize(inst1); - // @ts-ignore - inst1.exports.hs_init(); - // @ts-ignore - inst1.exports.wasm_app(0); - }); -}; diff --git a/jsbits/#websocket.ts# b/jsbits/#websocket.ts# deleted file mode 100644 index 4197f05..0000000 --- a/jsbits/#websocket.ts# +++ /dev/null @@ -1,82 +0,0 @@ -import { ClientMsgTag, EventId, EvalState, PersistentState, Ptr } from "./proto"; -import * as proto from "./proto"; - -const outBuf = new ArrayBuffer(100 * 1024); -const mem = new DataView(outBuf); - -export function runWebsocket(devSocketUri: string, startFlags: unknown = null) { - const websocket = new WebSocket(devSocketUri); - const persistent: PersistentState = { - refs: new Map(), - stack: null, - }; - - function triggerEvent(eventId: EventId, arg: unknown) { - const encoderState = {mem, begin: 0, end: outBuf.byteLength}; - proto.encodeClientMessage(encoderState, [ClientMsgTag.EventMsg, eventId, arg]); - websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); - }; - - function resumeCont(contId: number, res: unknown) { - const encoderState = {mem, begin: 0, end: outBuf.byteLength}; - proto.encodeClientMessage(encoderState, [ClientMsgTag.ResumeMsg, contId, res]); - websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); - }; - - websocket.onopen = (_event) => { - const encoderState = {mem, begin: 0, end: outBuf.byteLength}; - proto.encodeClientMessage(encoderState, [ClientMsgTag.StartMsg, startFlags]); - websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); - }; - - // Event handler for receiving messages from the server - websocket.onmessage = (event) => { - convertBlobToUint8Array(event.data).then(buf => { - proto.evalMem({ - triggerEvent, - resumeCont, - persistent, - mem: new DataView(buf), - isMutableMem: false, - begin: 0, - end: buf.byteLength, - }); - }); - }; - - // Event handler for errors - websocket.onerror = (event) => { - console.error("WebSocket error:", event); - }; - - // Event handler for when the connection is closed - websocket.onclose = (_event) => { - console.log("WebSocket connection closed, reloading the tab…"); - - function backoffLoop(timeout: number) { - // Assuming the server went down because it was re-compiled, wait - // until it comes back and reload the tab - const websocketTest = new WebSocket(devSocketUri); - const nextTimeout = Math.min(30_000, timeout * 2); - websocketTest.onopen = (_event) => window.location.reload(); - websocketTest.onclose = (_event) => { setTimeout(() => backoffLoop(nextTimeout), timeout); } - } - backoffLoop(100); - }; -} - -export function convertBlobToUint8Array(blob: Blob): Promise { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - - reader.onload = () => { - resolve(reader.result as ArrayBuffer); - }; - - reader.onerror = (error) => { - reject(error); - }; - - reader.readAsArrayBuffer(blob); - }); -} diff --git a/jsbits/proto.ts b/jsbits/proto.ts index be3e6f7..2876cc4 100644 --- a/jsbits/proto.ts +++ b/jsbits/proto.ts @@ -89,8 +89,8 @@ export enum ExprTag { YieldResult, } -/** Encode `Expr` sum type as a union of disjoint n-tuples, keep in - * sync with `Expr` definition in +/** Encode `Expr` type as a union of disjoint n-tuples, keep in + * sync with Haskell definition in * https://github.com/lagunoff/clickable/blob/master/Clickable/Types.hs */ export type Expr = | [ExprTag.Null] @@ -112,8 +112,8 @@ export type Expr = | [ExprTag.Lam, Expr] | [ExprTag.Arg, number] - | [ExprTag.Apply, Expr, Expr] - | [ExprTag.Call, Expr, string, Expr] + | [ExprTag.Apply, Expr, [Expr]] + | [ExprTag.Call, Expr, string, [Expr]] | [ExprTag.AssignRef, number, number, Expr] | [ExprTag.FreeRef, number, number] @@ -341,15 +341,25 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u throw new Error("Arg: index out of argument stack"); }; case ExprTag.Apply: { - const fn = evalNext(self, args, prevRes); - const arg = evalNext(self, args, prevRes); - return (fn as any)(arg); + const fn = evalNext(self, args, prevRes) as Function; + const fnArgNum = Number(self.mem.getBigUint64(self.begin, false)); + self.begin += 8; + const fnArgs = new Array(fnArgNum).fill(null); + for (let i = 0; i < fnArgNum; i++) { + fnArgs[i] = evalNext(self, args, prevRes); + } + return (fn).apply(undefined, fnArgs); }; case ExprTag.Call: { const obj = evalNext(self, args, prevRes); const key = decodeString(self); - const arg = evalNext(self, args, prevRes); - return (obj as any)[key].call(obj, arg); + const callArgNum = Number(self.mem.getBigUint64(self.begin, false)); + self.begin += 8; + const callArgs = new Array(callArgNum).fill(null); + for (let i = 0; i < callArgNum; i++) { + callArgs[i] = evalNext(self, args, prevRes); + } + return (obj as any)[key].apply(obj, callArgs); }; case ExprTag.AssignRef: { diff --git a/jsbits/wasm.ts b/jsbits/wasm.ts index 61b660f..b1bf8ab 100644 --- a/jsbits/wasm.ts +++ b/jsbits/wasm.ts @@ -44,7 +44,7 @@ export function runWasm(wasmUri: string, startFlags: unknown = null) { end: ptr + len, }; - proto.evalRange(intp); + proto.evalMem(intp); } WebAssembly.compileStreaming(fetch(wasmUri)) diff --git a/jsbits/websocket.ts b/jsbits/websocket.ts index 47cdab1..b98690d 100644 --- a/jsbits/websocket.ts +++ b/jsbits/websocket.ts @@ -1,4 +1,4 @@ -import { ClientMsgTag, EventId, EvalState, PersistentState, Ptr } from "./proto"; +import { ClientMsgTag, EventId, PersistentState } from "./proto"; import * as proto from "./proto"; const outBuf = new ArrayBuffer(100 * 1024); @@ -32,7 +32,7 @@ export function runWebsocket(devSocketUri: string, startFlags: unknown = null) { // Event handler for receiving messages from the server websocket.onmessage = (event) => { convertBlobToUint8Array(event.data).then(buf => { - proto.evalRange({ + proto.evalMem({ triggerEvent, resumeCont, persistent, diff --git a/shell.nix b/shell.nix index bedcaa0..1e8f38c 100644 --- a/shell.nix +++ b/shell.nix @@ -3,10 +3,6 @@ let nixpkgs = builtins.fetchTarball { url = "https://github.com/NixOS/nixpkgs/archive/refs/tags/24.05.tar.gz"; }; - http-client = builtins.fetchGit { - url = "https://github.com/lagunoff/http-client.git"; - rev = "18388fb8f2a13290279a9e69a1ca2b4719e58cca"; - }; ghc-wasm-meta = "gitlab:ghc/ghc-wasm-meta?host=gitlab.haskell.org&ref=108e4693cd147777e8d93683e58c8a5e1da74c96"; }; @@ -23,75 +19,23 @@ let enableExecutableProfiling = false; } // args); - clickable = final.callCabal2nix "clickable" ./ {}; - semirings = final.callCabal2nix "semirings" ../fullstack-hs/.overrides/semirings {}; - - th-compat = final.callCabal2nix "th-compat" (builtins.fetchGit { - url = "https://github.com/haskell-compat/th-compat.git"; - rev = "eec1edb9e09eba14e7ba17be29a9674431c63c05"; - }) {}; - - th-abstraction = final.callCabal2nix "th-abstraction" (builtins.fetchGit { - url = "https://github.com/glguy/th-abstraction.git"; - rev = "1fb59d1651ac5462f44100c62e5806665d39b6c6"; - }) {}; - - crypton-connection = final.callCabal2nix "crypton-connection" (builtins.fetchGit { - url = "https://github.com/kazu-yamamoto/crypton-connection.git"; - rev = "bab16ae4d0fa417ba315fb3d26f55418ce91fcb6"; - }) {}; - - lens = final.callCabal2nix "lens" (builtins.fetchGit { - url = "https://github.com/ekmett/lens.git"; - rev = "c1f47431d66f114262acb4023a0d79e979af5636"; - }) {}; - - ghc-exactprint = final.callCabal2nix "ghc-exactprint" (builtins.fetchGit { - url = "https://github.com/alanz/ghc-exactprint.git"; - rev = "630c4e8f36d0decb765644041a273f6ba8888d57"; - }) {}; - - hashable = final.callCabal2nix "hashable" ../fullstack-hs/.overrides/hashable {}; - - semigroupoids = final.callCabal2nix "semigroupoids" ../fullstack-hs/.overrides/semigroupoids {}; - extensions = final.callCabal2nix "extensions" ../fullstack-hs/.overrides/extensions {}; - stan = final.callCabal2nix "stan" ../fullstack-hs/.overrides/stan {}; - apply-refact = final.callCabal2nix "apply-refact" ../fullstack-hs/.overrides/apply-refact {}; - retrie = final.callCabal2nix "retrie" ../fullstack-hs/.overrides/retrie {}; - aeson-pretty = final.callCabal2nix "aeson-pretty" ../fullstack-hs/.overrides/aeson-pretty {}; - - ghcide = final.callCabal2nix "ghcide" ../fullstack-hs/.overrides/haskell-language-server/ghcide {}; - haskell-language-server = final.callCabal2nix "haskell-language-server" ../fullstack-hs/.overrides/haskell-language-server {}; - haskell-language-server-exe = final.callCabal2nix "haskell-language-server-exe" ../fullstack-hs/.overrides/haskell-language-server/exe {}; - hie-compat = final.callCabal2nix "hie-compat" ../fullstack-hs/.overrides/haskell-language-server/hie-compat {}; - hls-graph = final.callCabal2nix "hls-graph" ../fullstack-hs/.overrides/haskell-language-server/hls-graph {}; - hls-plugin-api = final.callCabal2nix "hls-plugin-api" ../fullstack-hs/.overrides/haskell-language-server/hls-plugin-api {}; - hls-test-utils = final.callCabal2nix "hls-test-utils" ../fullstack-hs/.overrides/haskell-language-server/hls-test-utils {}; - shake-bench = final.callCabal2nix "shake-bench" ../fullstack-hs/.overrides/haskell-language-server/shake-bench {}; - - cabal-add = final.callCabal2nix "cabal-add" ../fullstack-hs/.overrides/cabal-add {}; - ghc-lib-parser = final.callCabal2nix "ghc-lib-parser" ../fullstack-hs/.overrides/ghc-lib-parser-9.10.1.20240511 {}; - - aeson = final.callCabal2nix "aeson" ../fullstack-hs/.overrides/aeson {}; - attoparsec-aeson = final.callCabal2nix "attoparsec-aeson" ../fullstack-hs/.overrides/aeson/attoparsec-aeson {}; - lsp = final.callCabal2nix "lsp" ../fullstack-hs/.overrides/lsp/lsp {}; - lsp-types = final.callCabal2nix "lsp-types" ../fullstack-hs/.overrides/lsp/lsp-types {}; - lsp-test = final.callCabal2nix "lsp-test" ../fullstack-hs/.overrides/lsp/lsp-test {}; + clickable = final.callCabal2nix "clickable" ./. {}; }; haskellPackages = pkgs.haskell.packages.ghc9101.override { - inherit overrides; + overrides = pkgs.lib.composeExtensions + (import ../overrides/nixpkgs-24.05-ghc9101) overrides; }; ghc-wasm-meta = builtins.getFlake sources.ghc-wasm-meta; in - (pkgs.mkShell { - inputsFrom = [haskellPackages.clickable.env]; + pkgs.mkShell { + inputsFrom = [ + haskellPackages.clickable.env + ]; nativeBuildInputs = [ ghc-wasm-meta.packages.x86_64-linux.default haskellPackages.haskell-language-server-exe (haskellPackages.hoogleWithPackages (p: p.clickable.buildInputs)) ]; - }) // { - inherit haskellPackages; } diff --git a/websocket.hs b/websocket.hs index a13c7fe..98938f5 100644 --- a/websocket.hs +++ b/websocket.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE GHC2021 #-} {-# LANGUAGE BlockArguments #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE LambdaCase #-} @@ -19,35 +20,35 @@ import qualified Data.Text as Text test01 :: ClickM () test01 = do - enqueueExpr $ PushStack $ Id "document" `Dot` "body" counter <- newVar @Int 0 - el "div" do - prop "className" (Str "container") - text "Lorem Ipsum" - el "h1" $ text "Fox jumps over a lazy dog" - el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" - el "button" do - text "Click Here" - on @"click" $ modifyVar_ counter succ - el "button" do - text "-" - on @"click" $ modifyVar_ counter pred - el "br" $ pure () - el "span" do - dynText $ fmap (Text.pack . show) $ fromVar counter - ref <- liftIO $ newIORef $ const $ pure () - el "div" do - el "button" do - text "Ask a Value" - on @"click" do - t <- asks (.hte_prompt_tag) - val <- liftIO $ control t \cont -> writeIORef ref cont - enqueueExpr $ Call (Id "console") "log" $ val - el "button" do - text "Fill the value" - on @"click" do - cont <- liftIO $ readIORef ref - liftIO $ cont $ pure $ Obj [("this", Str "is"), ("some", Str "value")] + attachToBody do + el "div" do + prop "className" (Str "container") + text "Lorem Ipsum" + el "h1" $ text "Fox jumps over a lazy dog" + el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" + el "button" do + text "Click Here" + on @"click" $ modifyVar_ counter succ + el "button" do + text "-" + on @"click" $ modifyVar_ counter pred + el "br" $ pure () + el "span" do + dynText $ fmap (Text.pack . show) $ fromVar counter + ref <- liftIO $ newIORef $ const $ pure () + el "div" do + el "button" do + text "Ask a Value" + on @"click" do + t <- asks (.hte_prompt_tag) + val <- liftIO $ control t \cont -> writeIORef ref cont + enqueueExpr $ Call (Id "console") "log" [val] + el "button" do + text "Fill the value" + on @"click" do + cont <- liftIO $ readIORef ref + liftIO $ cont $ pure $ Obj [("this", Str "is"), ("some", Str "value")] main :: IO () main = do From 1f269ebf4b7ebef73eb8d384acbcd0173054612d Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 16 Oct 2024 00:18:01 +0400 Subject: [PATCH 55/64] Element.hs and Property.hs --- Clickable.hs | 2 + Clickable/Element.hs | 407 ++++++++++++++++++++++++++++++++++++++++++ Clickable/Html.hs | 43 ++++- Clickable/Internal.hs | 6 + Clickable/Property.hs | 371 ++++++++++++++++++++++++++++++++++++++ clickable.cabal | 6 +- hie.yaml | 5 +- 7 files changed, 826 insertions(+), 14 deletions(-) create mode 100644 Clickable/Element.hs create mode 100644 Clickable/Property.hs diff --git a/Clickable.hs b/Clickable.hs index 6422169..224933d 100644 --- a/Clickable.hs +++ b/Clickable.hs @@ -3,5 +3,7 @@ Native GHC -} module Clickable (module Exports) where import Clickable.Html as Exports +import Clickable.Element as Exports +import Clickable.Property as Exports import Clickable.Internal as Exports import Clickable.Types as Exports diff --git a/Clickable/Element.hs b/Clickable/Element.hs new file mode 100644 index 0000000..e558569 --- /dev/null +++ b/Clickable/Element.hs @@ -0,0 +1,407 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE FunctionalDependencies #-} +{-| +Shortcuts for most common HTML5 elements +-} +module Clickable.Element where + +import Clickable.Html +import Clickable.Types +import Data.Text + +-- | This typeclass allows for tag constructors to have variable +-- length arguments. Each tag constructor like 'div_' defined below +-- can be called with one or two arguments +-- +-- > div_ $ text "A Div without attributes" +-- > div_ [class_ "wrapper"] $ text "A Div with a class" +-- +-- Unceremoniously copied from @lucid@ library, see +-- https://github.com/chrisdone/lucid/blob/fb3b0e7c189c2acd8d88838d4a13923f24542ee8/src/Lucid/Base.hs#L272 +class Term arg result | result -> arg where + term + :: Text -- ^ Name. + -> arg -- ^ Some argument. + -> result -- ^ Result: either an element or an attribute. + +-- | Given attributes, expect more child input. +instance f ~ HtmlM a => Term [HtmlM ()] (f -> HtmlM a) where + term name attrs = el name . (sequence_ attrs *>) + {-# INLINE term #-} + +-- | Given children immediately, just use that and expect no +-- attributes. +instance Term (HtmlM a) (HtmlM a) where + term = el + {-# INLINE term #-} + +div_ :: Term arg result => arg -> result +div_ = term "div" +{-# INLINE div_ #-} + +table_ :: Term arg result => arg -> result +table_ = term "table" +{-# INLINE table_ #-} + +thead_ :: Term arg result => arg -> result +thead_ = term "thead" +{-# INLINE thead_ #-} + +tbody_ :: Term arg result => arg -> result +tbody_ = term "tbody" +{-# INLINE tbody_ #-} + +tr_ :: Term arg result => arg -> result +tr_ = term "tr" +{-# INLINE tr_ #-} + +th_ :: Term arg result => arg -> result +th_ = term "th" +{-# INLINE th_ #-} + +td_ :: Term arg result => arg -> result +td_ = term "td" +{-# INLINE td_ #-} + +tfoot_ :: Term arg result => arg -> result +tfoot_ = term "tfoot" +{-# INLINE tfoot_ #-} + +section_ :: Term arg result => arg -> result +section_ = term "section" +{-# INLINE section_ #-} + +header_ :: Term arg result => arg -> result +header_ = term "header" +{-# INLINE header_ #-} + +footer_ :: Term arg result => arg -> result +footer_ = term "footer" +{-# INLINE footer_ #-} + +button_ :: Term arg result => arg -> result +button_ = term "button" +{-# INLINE button_ #-} + +form_ :: Term arg result => arg -> result +form_ = term "form" +{-# INLINE form_ #-} + +p_ :: Term arg result => arg -> result +p_ = term "p" +{-# INLINE p_ #-} + +s_ :: Term arg result => arg -> result +s_ = term "s" +{-# INLINE s_ #-} + +ul_ :: Term arg result => arg -> result +ul_ = term "ul" +{-# INLINE ul_ #-} + +span_ :: Term arg result => arg -> result +span_ = term "span" +{-# INLINE span_ #-} + +strong_ :: Term arg result => arg -> result +strong_ = term "strong" +{-# INLINE strong_ #-} + +li_ :: Term arg result => arg -> result +li_ = term "li" +{-# INLINE li_ #-} + +h1_ :: Term arg result => arg -> result +h1_ = term "h1" +{-# INLINE h1_ #-} + +h2_ :: Term arg result => arg -> result +h2_ = term "h2" +{-# INLINE h2_ #-} + +h3_ :: Term arg result => arg -> result +h3_ = term "h3" +{-# INLINE h3_ #-} + +h4_ :: Term arg result => arg -> result +h4_ = term "h4" +{-# INLINE h4_ #-} + +h5_ :: Term arg result => arg -> result +h5_ = term "h5" +{-# INLINE h5_ #-} + +h6_ :: Term arg result => arg -> result +h6_ = term "h6" +{-# INLINE h6_ #-} + +hr_ :: Term arg result => arg -> result +hr_ = term "hr" +{-# INLINE hr_ #-} + +pre_ :: Term arg result => arg -> result +pre_ = term "pre" +{-# INLINE pre_ #-} + +input_ :: Term arg result => arg -> result +input_ = term "input" +{-# INLINE input_ #-} + +label_ :: Term arg result => arg -> result +label_ = term "label" +{-# INLINE label_ #-} + +a_ :: Term arg result => arg -> result +a_ = term "a" +{-# INLINE a_ #-} + +details_ :: Term arg result => arg -> result +details_ = term "details" +{-# INLINE details_ #-} + +summary_ :: Term arg result => arg -> result +summary_ = term "summary" +{-# INLINE summary_ #-} + +menuitem_ :: Term arg result => arg -> result +menuitem_ = term "menuitem" +{-# INLINE menuitem_ #-} + +menu_ :: Term arg result => arg -> result +menu_ = term "menu" +{-# INLINE menu_ #-} + +fieldset_ :: Term arg result => arg -> result +fieldset_ = term "fieldset" +{-# INLINE fieldset_ #-} + +legend_ :: Term arg result => arg -> result +legend_ = term "legend" +{-# INLINE legend_ #-} + +datalist_ :: Term arg result => arg -> result +datalist_ = term "datalist" +{-# INLINE datalist_ #-} + +optgroup_ :: Term arg result => arg -> result +optgroup_ = term "optgroup" +{-# INLINE optgroup_ #-} + +progress_ :: Term arg result => arg -> result +progress_ = term "progress" +{-# INLINE progress_ #-} + +meter_ :: Term arg result => arg -> result +meter_ = term "meter" +{-# INLINE meter_ #-} + +center_ :: Term arg result => arg -> result +center_ = term "center" +{-# INLINE center_ #-} + +audio_ :: Term arg result => arg -> result +audio_ = term "audio" +{-# INLINE audio_ #-} + +video_ :: Term arg result => arg -> result +video_ = term "video" +{-# INLINE video_ #-} + +source_ :: Term arg result => arg -> result +source_ = term "source" +{-# INLINE source_ #-} + +track_ :: Term arg result => arg -> result +track_ = term "track" +{-# INLINE track_ #-} + +embed_ :: Term arg result => arg -> result +embed_ = term "embed" +{-# INLINE embed_ #-} + +object_ :: Term arg result => arg -> result +object_ = term "object" +{-# INLINE object_ #-} + +param_ :: Term arg result => arg -> result +param_ = term "param" +{-# INLINE param_ #-} + +ins_ :: Term arg result => arg -> result +ins_ = term "ins" +{-# INLINE ins_ #-} + +del_ :: Term arg result => arg -> result +del_ = term "del" +{-# INLINE del_ #-} + +small_ :: Term arg result => arg -> result +small_ = term "small" +{-# INLINE small_ #-} + +cite_ :: Term arg result => arg -> result +cite_ = term "cite" +{-# INLINE cite_ #-} + +dfn_ :: Term arg result => arg -> result +dfn_ = term "dfn" +{-# INLINE dfn_ #-} + +abbr_ :: Term arg result => arg -> result +abbr_ = term "abbr" +{-# INLINE abbr_ #-} + +time_ :: Term arg result => arg -> result +time_ = term "time" +{-# INLINE time_ #-} + +var_ :: Term arg result => arg -> result +var_ = term "var" +{-# INLINE var_ #-} + +samp_ :: Term arg result => arg -> result +samp_ = term "samp" +{-# INLINE samp_ #-} + +kbd_ :: Term arg result => arg -> result +kbd_ = term "kbd" +{-# INLINE kbd_ #-} + +caption_ :: Term arg result => arg -> result +caption_ = term "caption" +{-# INLINE caption_ #-} + +colgroup_ :: Term arg result => arg -> result +colgroup_ = term "colgroup" +{-# INLINE colgroup_ #-} + +col_ :: Term arg result => arg -> result +col_ = term "col" +{-# INLINE col_ #-} + +nav_ :: Term arg result => arg -> result +nav_ = term "nav" +{-# INLINE nav_ #-} + +article_ :: Term arg result => arg -> result +article_ = term "article" +{-# INLINE article_ #-} + +aside_ :: Term arg result => arg -> result +aside_ = term "aside" +{-# INLINE aside_ #-} + +address_ :: Term arg result => arg -> result +address_ = term "address" +{-# INLINE address_ #-} + +main_ :: Term arg result => arg -> result +main_ = term "main" +{-# INLINE main_ #-} + +body_ :: Term arg result => arg -> result +body_ = term "body" +{-# INLINE body_ #-} + +figure_ :: Term arg result => arg -> result +figure_ = term "figure" +{-# INLINE figure_ #-} + +figcaption_ :: Term arg result => arg -> result +figcaption_ = term "figcaption" +{-# INLINE figcaption_ #-} + +dl_ :: Term arg result => arg -> result +dl_ = term "dl" +{-# INLINE dl_ #-} + +dt_ :: Term arg result => arg -> result +dt_ = term "dt" +{-# INLINE dt_ #-} + +dd_ :: Term arg result => arg -> result +dd_ = term "dd" +{-# INLINE dd_ #-} + +img_ :: Term arg result => arg -> result +img_ = term "img" +{-# INLINE img_ #-} + +iframe_ :: Term arg result => arg -> result +iframe_ = term "iframe" +{-# INLINE iframe_ #-} + +canvas_ :: Term arg result => arg -> result +canvas_ = term "canvas" +{-# INLINE canvas_ #-} + +math_ :: Term arg result => arg -> result +math_ = term "math" +{-# INLINE math_ #-} + +select_ :: Term arg result => arg -> result +select_ = term "select" +{-# INLINE select_ #-} + +option_ :: Term arg result => arg -> result +option_ = term "option" +{-# INLINE option_ #-} + +textarea_ :: Term arg result => arg -> result +textarea_ = term "textarea" +{-# INLINE textarea_ #-} + +sub_ :: Term arg result => arg -> result +sub_ = term "sub" +{-# INLINE sub_ #-} + +sup_ :: Term arg result => arg -> result +sup_ = term "sup" +{-# INLINE sup_ #-} + +br_ :: HtmlM () +br_ = el "br" blank +{-# INLINE br_ #-} + +ol_ :: Term arg result => arg -> result +ol_ = term "ol" +{-# INLINE ol_ #-} + +blockquote_ :: Term arg result => arg -> result +blockquote_ = term "blockquote" +{-# INLINE blockquote_ #-} + +code_ :: Term arg result => arg -> result +code_ = term "code" +{-# INLINE code_ #-} + +em_ :: Term arg result => arg -> result +em_ = term "em" +{-# INLINE em_ #-} + +i_ :: Term arg result => arg -> result +i_ = term "i" +{-# INLINE i_ #-} + +b_ :: Term arg result => arg -> result +b_ = term "b" +{-# INLINE b_ #-} + +u_ :: Term arg result => arg -> result +u_ = term "u" +{-# INLINE u_ #-} + +q_ :: Term arg result => arg -> result +q_ = term "q" +{-# INLINE q_ #-} + +script_ :: Term arg result => arg -> result +script_ = term "script" +{-# INLINE script_ #-} + +link_ :: Term arg result => arg -> result +link_ = term "link" +{-# INLINE link_ #-} diff --git a/Clickable/Html.hs b/Clickable/Html.hs index 0e86bf0..b87deb1 100644 --- a/Clickable/Html.hs +++ b/Clickable/Html.hs @@ -57,11 +57,11 @@ dynText contentDyn = HtmlM \s e -> do pure ((), s) {-# INLINEABLE dynText #-} -prop :: ToValue val => Text -> val -> HtmlM () -prop k v = HtmlM \s e -> do +property :: ToValue val => Text -> val -> HtmlM () +property k v = HtmlM \s e -> do e.hte_send $ execPut $ Binary.put $ ElementProp (PeekStack 0) k $ toValue v pure ((), s) -{-# INLINE prop #-} +{-# INLINE property #-} dynProp :: ToValue val => Text -> DynVal val -> HtmlM () dynProp propName dynVal = HtmlM \s e -> do @@ -74,13 +74,30 @@ dynProp propName dynVal = HtmlM \s e -> do pure ((), s') {-# INLINE dynProp #-} -addEventListener :: (Event ValueExpr -> Expr) -> (ValueExpr -> ClickM ()) -> ClickM () +attribute :: Text -> Text -> HtmlM () +attribute k v = HtmlM \s e -> do + e.hte_send $ execPut $ Binary.put $ ElementAttr (PeekStack 0) k v + pure ((), s) +{-# INLINE attribute #-} + +dynAttr :: Text -> DynVal Text -> HtmlM () +dynAttr propName dynVal = HtmlM \s e -> do + (refId, s') <- saveStackTip.unHtmlM s e + initVal <- readVal dynVal + e.hte_send $ execPut $ Binary.put $ ElementAttr (PeekStack 0) propName initVal + let k nval = ClickM \e' -> + e'.hte_send $ execPut $ Binary.put $ ElementAttr (Ref refId) propName nval + unClickM (subscribe dynVal k) e + pure ((), s') +{-# INLINE dynAttr #-} + +addEventListener :: FromValue a => (Event a -> Expr) -> (a -> ClickM ()) -> ClickM () addEventListener connectScript k = do e <- reactive \scope s -> let k' = local (\e -> e {hte_scope = scope}) . k eventId = EventId s.next_id (s', unSubRef) = newRefIdOp scope s {next_id = s.next_id + 1} - newSub = SubscriptionSimple scope (unsafeFromEventId eventId) (k' . unsafeCoerce) + newSub = SubscriptionSimple scope (unsafeFromEventId eventId) (mapM_ k' . fromValue . unsafeCoerce) newFin = CustomFinalizer scope $ enqueueExpr $ Apply (Ref unSubRef) [] s'' = s' {subscriptions = newSub : s.subscriptions, finalizers = newFin : s.finalizers} in (s'', AssignRef unSubRef (connectScript (Event eventId))) @@ -96,7 +113,7 @@ on k = liftClick $ connectEventName @eventName k instance IsEventName "click" where type EventListenerCb "click" = ClickM () connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "click") (const k) + (genericEvent defaultEventListenerOptions "click" (PeekStack 0)) (const k) data EventListenerOptions = EventListenerOptions { prevent_default :: Bool @@ -109,8 +126,8 @@ defaultEventListenerOptions = EventListenerOptions , stop_propagation = False } -genericEvent :: EventListenerOptions -> Text -> Event ValueExpr -> Expr -genericEvent opt eventName (Event eventId) = +genericEvent :: EventListenerOptions -> Text -> Expr -> Event () -> Expr +genericEvent opt eventName target (Event eventId) = Eval ("(function(target, trigger){\n\ \ function listener(event){\n\ @@ -120,11 +137,15 @@ genericEvent opt eventName (Event eventId) = \ }\n\ \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` [PeekStack 0, Lam (TriggerEvent eventId Null)] + \})") `Apply` [target, Lam (TriggerEvent eventId Null)] where preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" +unsafeConnectEvent :: Expr -> UnsafeJavaScript -> Event a -> Expr +unsafeConnectEvent target ujs (Event eid) = + Eval ujs `Apply` [target, Lam (TriggerEvent eid (Arg 0))] + attachHtml :: Expr -> HtmlM a -> ClickM a attachHtml rootEl contents = ClickM \e -> do e.hte_send $ execPut $ Binary.put $ PushStack rootEl @@ -144,3 +165,7 @@ saveStackTip = HtmlM \s e -> return (refId, Just refId) Just saved -> pure (saved, s) + +blank :: Applicative m => m () +blank = pure () +{-# INLINE blank #-} diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index 7cd033c..7415cd4 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -39,6 +39,12 @@ mapEvent f ea = do subscribeEvent ea $ triggerEvent eb . f return eb +mapMaybeEvent :: (a -> Maybe b) -> Event a -> ClickM (Event b) +mapMaybeEvent f ea = do + eb <- newEvent + subscribeEvent ea $ mapM_ (triggerEvent eb) . f + return eb + subscribeEvent :: forall a. Event a -> (a -> ClickM ()) -> ClickM () subscribeEvent (Event eid) k = reactive_ g where newSub scope = SubscriptionSimple scope (coerce eid) (k . unsafeCoerce) diff --git a/Clickable/Property.hs b/Clickable/Property.hs new file mode 100644 index 0000000..9872ba3 --- /dev/null +++ b/Clickable/Property.hs @@ -0,0 +1,371 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-| +Shortcuts for common HTML5 attributes and properties +-} +module Clickable.Property where + +import Clickable.Html +import Clickable.Types +import Data.Text + + +-- TODO: Real-world usage has demonstrated that 'dynStyles' not +-- sufficiently composable. For instance, if 'dynStyles' is used to +-- set the CSS color for an element, essentially no other CSS property +-- can be applied to this element, as they will be overwritten by +-- 'dynStyles'. +dynStyles :: DynVal Text -> HtmlM () +dynStyles = dynProp "style" +{-# INLINE dynStyles #-} + +dynValue :: DynVal Text -> HtmlM () +dynValue = dynProp "value" +{-# INLINE dynValue #-} + +dynClass :: DynVal Text -> HtmlM () +dynClass = dynProp "className" +{-# INLINE dynClass #-} + +dynChecked :: DynVal Bool -> HtmlM () +dynChecked = dynProp "checked" +{-# INLINE dynChecked #-} + +dynDisabled :: DynVal Bool -> HtmlM () +dynDisabled = dynProp "disabled" +{-# INLINE dynDisabled #-} + +title_ :: Text -> HtmlM () +title_ = property "title" +{-# INLINE title_ #-} + +selected_ :: Bool -> HtmlM () +selected_ = property "selected" +{-# INLINE selected_ #-} + +hidden_ :: Bool -> HtmlM () +hidden_ = property "hidden" +{-# INLINE hidden_ #-} + +value_ :: Text -> HtmlM () +value_ = property "value" +{-# INLINE value_ #-} + +defaultValue_ :: Text -> HtmlM () +defaultValue_ = property "defaultValue" +{-# INLINE defaultValue_ #-} + +accept_ :: Text -> HtmlM () +accept_ = property "accept" +{-# INLINE accept_ #-} + +acceptCharset_ :: Text -> HtmlM () +acceptCharset_ = property "acceptCharset" +{-# INLINE acceptCharset_ #-} + +action_ :: Text -> HtmlM () +action_ = property "action" +{-# INLINE action_ #-} + +autocomplete_ :: Bool -> HtmlM () +autocomplete_ b = property @Text "autocomplete" (if b then "on" else "off") +{-# INLINE autocomplete_ #-} + +autosave_ :: Text -> HtmlM () +autosave_ = property "autosave" +{-# INLINE autosave_ #-} + +disabled_ :: Bool -> HtmlM () +disabled_ = property "disabled" +{-# INLINE disabled_ #-} + +enctype_ :: Text -> HtmlM () +enctype_ = property "enctype" +{-# INLINE enctype_ #-} + +formation_ :: Text -> HtmlM () +formation_ = property "formation" +{-# INLINE formation_ #-} + +list_ :: Text -> HtmlM () +list_ = property "list" +{-# INLINE list_ #-} + +maxlength_ :: Text -> HtmlM () +maxlength_ = property "maxlength" +{-# INLINE maxlength_ #-} + +minlength_ :: Text -> HtmlM () +minlength_ = property "minlength" +{-# INLINE minlength_ #-} + +method_ :: Text -> HtmlM () +method_ = property "method" +{-# INLINE method_ #-} + +multiple_ :: Bool -> HtmlM () +multiple_ = property "multiple" +{-# INLINE multiple_ #-} + +novalidate_ :: Bool -> HtmlM () +novalidate_ = property "noValidate" +{-# INLINE novalidate_ #-} + +pattern_ :: Text -> HtmlM () +pattern_ = property "pattern" +{-# INLINE pattern_ #-} + +readonly_ :: Bool -> HtmlM () +readonly_ = property "readOnly" +{-# INLINE readonly_ #-} + +required_ :: Bool -> HtmlM () +required_ = property "required" +{-# INLINE required_ #-} + +size_ :: Text -> HtmlM () +size_ = property "size" +{-# INLINE size_ #-} + +forProp_ :: Text -> HtmlM () +forProp_ = property "for" +{-# INLINE forProp_ #-} + +ref_ :: Text -> HtmlM () +ref_ = property "ref" +{-# INLINE ref_ #-} + +formProp_ :: Text -> HtmlM () +formProp_ = property "form" +{-# INLINE formProp_ #-} + +max_ :: Text -> HtmlM () +max_ = property "max" +{-# INLINE max_ #-} + +min_ :: Text -> HtmlM () +min_ = property "min" +{-# INLINE min_ #-} + +step_ :: Text -> HtmlM () +step_ = property "step" +{-# INLINE step_ #-} + +cols_ :: Text -> HtmlM () +cols_ = property "cols" +{-# INLINE cols_ #-} + +rows_ :: Text -> HtmlM () +rows_ = property "rows" +{-# INLINE rows_ #-} + +wrap_ :: Text -> HtmlM () +wrap_ = property "wrap" +{-# INLINE wrap_ #-} + +target_ :: Text -> HtmlM () +target_ = property "target" +{-# INLINE target_ #-} + +download_ :: Text -> HtmlM () +download_ = property "download" +{-# INLINE download_ #-} + +downloadAs_ :: Text -> HtmlM () +downloadAs_ = property "downloadAs" +{-# INLINE downloadAs_ #-} + +hreflang_ :: Text -> HtmlM () +hreflang_ = property "hreflang" +{-# INLINE hreflang_ #-} + +media_ :: Text -> HtmlM () +media_ = property "media" +{-# INLINE media_ #-} + +ping_ :: Text -> HtmlM () +ping_ = property "ping" +{-# INLINE ping_ #-} + +rel_ :: Text -> HtmlM () +rel_ = property "rel" +{-# INLINE rel_ #-} + +ismap_ :: Text -> HtmlM () +ismap_ = property "ismap" +{-# INLINE ismap_ #-} + +usemap_ :: Text -> HtmlM () +usemap_ = property "usemap" +{-# INLINE usemap_ #-} + +shape_ :: Text -> HtmlM () +shape_ = property "shape" +{-# INLINE shape_ #-} + +coords_ :: Text -> HtmlM () +coords_ = property "coords" +{-# INLINE coords_ #-} + +src_ :: Text -> HtmlM () +src_ = property "src" +{-# INLINE src_ #-} + +height_ :: Text -> HtmlM () +height_ = property "height" +{-# INLINE height_ #-} + +width_ :: Text -> HtmlM () +width_ = property "width" +{-# INLINE width_ #-} + +alt_ :: Text -> HtmlM () +alt_ = property "alt" +{-# INLINE alt_ #-} + +autoplay_ :: Bool -> HtmlM () +autoplay_ = property "autoplay" +{-# INLINE autoplay_ #-} + +controls_ :: Bool -> HtmlM () +controls_ = property "controls" +{-# INLINE controls_ #-} + +loop_ :: Bool -> HtmlM () +loop_ = property "loop" +{-# INLINE loop_ #-} + +preload_ :: Text -> HtmlM () +preload_ = property "preload" +{-# INLINE preload_ #-} + +poster_ :: Text -> HtmlM () +poster_ = property "poster" +{-# INLINE poster_ #-} + +default_ :: Bool -> HtmlM () +default_ = property "default" +{-# INLINE default_ #-} + +kind_ :: Text -> HtmlM () +kind_ = property "kind" +{-# INLINE kind_ #-} + +srclang_ :: Text -> HtmlM () +srclang_ = property "srclang" +{-# INLINE srclang_ #-} + +sandbox_ :: Text -> HtmlM () +sandbox_ = property "sandbox" +{-# INLINE sandbox_ #-} + +seamless_ :: Text -> HtmlM () +seamless_ = property "seamless" +{-# INLINE seamless_ #-} + +srcdoc_ :: Text -> HtmlM () +srcdoc_ = property "srcdoc" +{-# INLINE srcdoc_ #-} + +reversed_ :: Text -> HtmlM () +reversed_ = property "reversed" +{-# INLINE reversed_ #-} + +start_ :: Text -> HtmlM () +start_ = property "start" +{-# INLINE start_ #-} + +align_ :: Text -> HtmlM () +align_ = property "align" +{-# INLINE align_ #-} + +colspan_ :: Text -> HtmlM () +colspan_ = attribute "colspan" +{-# INLINE colspan_ #-} + +rowspan_ :: Text -> HtmlM () +rowspan_ = attribute "rowspan" +{-# INLINE rowspan_ #-} + +headers_ :: Text -> HtmlM () +headers_ = property "headers" +{-# INLINE headers_ #-} + +scope_ :: Text -> HtmlM () +scope_ = property "scope" +{-# INLINE scope_ #-} + +async_ :: Text -> HtmlM () +async_ = property "async" +{-# INLINE async_ #-} + +charset_ :: Text -> HtmlM () +charset_ = property "charset" +{-# INLINE charset_ #-} + +content_ :: Text -> HtmlM () +content_ = property "content" +{-# INLINE content_ #-} + +defer_ :: Text -> HtmlM () +defer_ = property "defer" +{-# INLINE defer_ #-} + +httpEquiv_ :: Text -> HtmlM () +httpEquiv_ = property "httpEquiv" +{-# INLINE httpEquiv_ #-} + +language_ :: Text -> HtmlM () +language_ = property "language" +{-# INLINE language_ #-} + +scoped_ :: Text -> HtmlM () +scoped_ = property "scoped" +{-# INLINE scoped_ #-} + +type_ :: Text -> HtmlM () +type_ = property "type" +{-# INLINE type_ #-} + +name_ :: Text -> HtmlM () +name_ = property "name" +{-# INLINE name_ #-} + +href_ :: Text -> HtmlM () +href_ = property "href" +{-# INLINE href_ #-} + +id_ :: Text -> HtmlM () +id_ = property "id" +{-# INLINE id_ #-} + +placeholder_ :: Text -> HtmlM () +placeholder_ = property "placeholder" +{-# INLINE placeholder_ #-} + +checked_ :: Bool -> HtmlM () +checked_ = property "checked" +{-# INLINE checked_ #-} + +autofocus_ :: Bool -> HtmlM () +autofocus_ = property "autofocus" +{-# INLINE autofocus_ #-} + +class_ :: Text -> HtmlM () +class_ = property "className" +{-# INLINE class_ #-} + +data_ :: Text -> Text -> HtmlM () +data_ k v = property ("data-" <> k) v +{-# INLINE data_ #-} + +role_ :: Text -> HtmlM () +role_ = attribute "role" +{-# INLINE role_ #-} + +style_ :: Text -> HtmlM () +style_ = property "style" +{-# INLINE style_ #-} diff --git a/clickable.cabal b/clickable.cabal index e89d522..5d476d0 100644 --- a/clickable.cabal +++ b/clickable.cabal @@ -17,11 +17,13 @@ executable clickable hs-source-dirs: ./ other-modules: Clickable + Clickable.Element + Clickable.Float Clickable.Html - Clickable.Types Clickable.Internal + Clickable.Property + Clickable.Types Clickable.WebSocket - Clickable.Float -- other-extensions: build-depends: async, diff --git a/hie.yaml b/hie.yaml index d15699f..8245581 100644 --- a/hie.yaml +++ b/hie.yaml @@ -1,4 +1,3 @@ cradle: - cabal: - - path: "./" - component: "exe:clickable" + direct: + arguments: [] From 70a7844c33c12da819de2fba209cd04b8772f605 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 11 Nov 2024 20:09:53 +0400 Subject: [PATCH 56/64] First usable version --- .dir-locals.el | 3 + Clickable/Html.hs | 79 +++++---- Clickable/Internal.hs | 83 ++++----- Clickable/Types.hs | 162 ++++++++++++------ Clickable/WebSocket.hs | 103 ++++++----- bin/nix-bins | 4 +- jsbits/proto.ts | 378 ++++++++++++++++------------------------- jsbits/websocket.ts | 8 +- wasm.hs | 59 ------- websocket.hs | 63 ------- 10 files changed, 408 insertions(+), 534 deletions(-) delete mode 100644 wasm.hs delete mode 100644 websocket.hs diff --git a/.dir-locals.el b/.dir-locals.el index 998faf6..f51a98f 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -7,11 +7,14 @@ lsp-haskell-server-path (concat my-proj-dir "/bin/haskell-language-server")))) (haskell-mode + (haskell-process-type . ghci) + (haskell-process-args-ghci . ("-ferror-spans" "-fdiagnostics-color=never")) (eval . (setq my-proj-dir (file-name-directory (let ((d (dir-locals-find-file "."))) (if (stringp d) d (car d)))) + haskell-process-path-ghci (concat my-proj-dir "bin/ghci") haskell-hoogle-server-command (lambda (port) (list (concat my-proj-dir "bin/hoogle") "server" diff --git a/Clickable/Html.hs b/Clickable/Html.hs index b87deb1..1e15303 100644 --- a/Clickable/Html.hs +++ b/Clickable/Html.hs @@ -14,8 +14,6 @@ module Clickable.Html where import Clickable.Internal import Clickable.Types import Control.Monad.Reader -import Data.Binary qualified as Binary -import Data.Binary.Put (execPut) import Data.Kind (Type) import Data.Text (Text) import GHC.Generics (Generic) @@ -23,24 +21,24 @@ import Unsafe.Coerce (unsafeCoerce) el :: Text -> HtmlM a -> HtmlM a el tagName child = HtmlM \s e -> do - e.hte_send $ execPut $ Binary.put $ PushStack $ CreateElement tagName - r <- child.unHtmlM s e - e.hte_send $ execPut $ Binary.put PopIns - pure r + e.hte_send $ PushStack $ CreateElement tagName + (r, _) <- child.unHtmlM Nothing e + e.hte_send PopIns + pure (r, s) {-# INLINE el #-} elns :: Text -> Text -> HtmlM a -> HtmlM a elns ns tagName child = HtmlM \s e -> do - e.hte_send $ execPut $ Binary.put $ PushStack $ CreateElementNS ns tagName - r <- child.unHtmlM s e - e.hte_send $ execPut $ Binary.put PopIns - pure r + e.hte_send $ PushStack $ CreateElementNS ns tagName + (r, _) <- child.unHtmlM s e + e.hte_send PopIns + pure (r, s) {-# INLINE elns #-} text :: Text -> HtmlM () text content = HtmlM \s e -> do - e.hte_send $ execPut $ Binary.put $ PushStack $ CreateTextNode content - e.hte_send $ execPut $ Binary.put $ PopIns + e.hte_send $ PushStack $ CreateTextNode content + e.hte_send PopIns return ((), s) {-# INLINE text #-} @@ -48,18 +46,18 @@ dynText :: DynVal Text -> HtmlM () dynText contentDyn = HtmlM \s e -> do c <- readVal contentDyn refId <- newRefId.unClickM e - e.hte_send $ execPut $ Binary.put $ PushStack $ CreateTextNode c - e.hte_send $ execPut $ Binary.put $ AssignRef refId (PeekStack 0) - e.hte_send $ execPut $ Binary.put $ PopIns + e.hte_send $ PushStack $ CreateTextNode c + e.hte_send $ AssignRef refId (PeekStack 0) + e.hte_send PopIns let k nval = ClickM \e' -> - e'.hte_send $ execPut $ Binary.put $ UpdateTextNode (Ref refId) nval + e'.hte_send $ UpdateTextNode (Ref refId) nval (subscribe contentDyn k).unClickM e pure ((), s) {-# INLINEABLE dynText #-} property :: ToValue val => Text -> val -> HtmlM () property k v = HtmlM \s e -> do - e.hte_send $ execPut $ Binary.put $ ElementProp (PeekStack 0) k $ toValue v + e.hte_send $ ElementProp (PeekStack 0) k $ toValue v pure ((), s) {-# INLINE property #-} @@ -67,16 +65,16 @@ dynProp :: ToValue val => Text -> DynVal val -> HtmlM () dynProp propName dynVal = HtmlM \s e -> do (refId, s') <- saveStackTip.unHtmlM s e initVal <- readVal dynVal - e.hte_send $ execPut $ Binary.put $ ElementProp (PeekStack 0) propName $ toValue initVal + e.hte_send $ ElementProp (PeekStack 0) propName $ toValue initVal let k nval = ClickM \e' -> - e'.hte_send $ execPut $ Binary.put $ ElementProp (Ref refId) propName $ toValue nval + e'.hte_send $ ElementProp (Ref refId) propName $ toValue nval unClickM (subscribe dynVal k) e pure ((), s') {-# INLINE dynProp #-} attribute :: Text -> Text -> HtmlM () attribute k v = HtmlM \s e -> do - e.hte_send $ execPut $ Binary.put $ ElementAttr (PeekStack 0) k v + e.hte_send $ ElementAttr (PeekStack 0) k v pure ((), s) {-# INLINE attribute #-} @@ -84,13 +82,26 @@ dynAttr :: Text -> DynVal Text -> HtmlM () dynAttr propName dynVal = HtmlM \s e -> do (refId, s') <- saveStackTip.unHtmlM s e initVal <- readVal dynVal - e.hte_send $ execPut $ Binary.put $ ElementAttr (PeekStack 0) propName initVal + e.hte_send $ ElementAttr (PeekStack 0) propName initVal let k nval = ClickM \e' -> - e'.hte_send $ execPut $ Binary.put $ ElementAttr (Ref refId) propName nval + e'.hte_send $ ElementAttr (Ref refId) propName nval unClickM (subscribe dynVal k) e pure ((), s') {-# INLINE dynAttr #-} +toggleClass :: Text -> DynVal Bool -> HtmlM () +toggleClass className dynEnable = HtmlM \s e -> do + (refId, s') <- saveStackTip.unHtmlM s e + v <- readVal dynEnable + let k enable = ClickM \e' -> e'.hte_send + if enable + then ClassListAdd (Ref refId) className + else ClassListRemove (Ref refId) className + unClickM (k v) e + unClickM (subscribe dynEnable k) e + pure ((), s') +{-# INLINE toggleClass #-} + addEventListener :: FromValue a => (Event a -> Expr) -> (a -> ClickM ()) -> ClickM () addEventListener connectScript k = do e <- reactive \scope s -> @@ -108,23 +119,23 @@ class IsEventName eventName where connectEventName :: EventListenerCb eventName -> ClickM () on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HtmlM () -on k = liftClick $ connectEventName @eventName k +on k = liftC $ connectEventName @eventName k instance IsEventName "click" where type EventListenerCb "click" = ClickM () connectEventName k = addEventListener (genericEvent defaultEventListenerOptions "click" (PeekStack 0)) (const k) -data EventListenerOptions = EventListenerOptions - { prevent_default :: Bool - , stop_propagation :: Bool - } deriving stock (Generic, Show, Eq) +data EventListenerOptions = EventListenerOptions { + prevent_default :: Bool, + stop_propagation :: Bool +} deriving stock (Generic, Show, Eq) defaultEventListenerOptions :: EventListenerOptions -defaultEventListenerOptions = EventListenerOptions - { prevent_default = False - , stop_propagation = False - } +defaultEventListenerOptions = EventListenerOptions { + prevent_default = False, + stop_propagation = False +} genericEvent :: EventListenerOptions -> Text -> Expr -> Event () -> Expr genericEvent opt eventName target (Event eventId) = @@ -148,9 +159,9 @@ unsafeConnectEvent target ujs (Event eid) = attachHtml :: Expr -> HtmlM a -> ClickM a attachHtml rootEl contents = ClickM \e -> do - e.hte_send $ execPut $ Binary.put $ PushStack rootEl + e.hte_send $ PushStack rootEl (r, _) <- contents.unHtmlM Nothing e - e.hte_send $ execPut $ Binary.put PopIns + e.hte_send PopStack pure r attachToBody :: HtmlM a -> ClickM a @@ -161,7 +172,7 @@ saveStackTip = HtmlM \s e -> case s of Nothing -> do refId <- newRefId.unClickM e - e.hte_send $ execPut $ Binary.put $ AssignRef refId $ PeekStack 0 + e.hte_send $ AssignRef refId $ PeekStack 0 return (refId, Just refId) Just saved -> pure (saved, s) diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index 7415cd4..4c3892c 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -3,7 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE BlockArguments #-} {-# LANGUAGE OverloadedRecordDot #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wall #-} module Clickable.Internal where import Clickable.Types @@ -12,13 +12,11 @@ import Control.Monad.Reader import Control.Monad.State.Strict import Data.Binary qualified as Binary import Data.Binary.Put (execPut) -import Data.ByteString.Builder ( Builder ) +import Data.ByteString.Builder ( Builder, byteString ) import Data.ByteString.Builder.Extra (runBuilder, Next (..), BufferWriter) -import Data.ByteString.Unsafe import Data.Functor.Const import Data.IORef import Data.List qualified as List -import Data.Map (Map) import Data.Map qualified as Map import Data.Text (Text) import Data.Tuple (swap) @@ -28,6 +26,7 @@ import Foreign.Marshal.Alloc (mallocBytes) import Foreign.Ptr import GHC.Exts import Unsafe.Coerce +import Data.ByteString.Unsafe newEvent :: ClickM (Event a) newEvent = state \s -> @@ -305,61 +304,63 @@ writeVarQuiet var = modifyVarQuiet_ var . const {-# INLINE writeVarQuiet #-} enqueueExpr :: Expr -> ClickM () -enqueueExpr exp = ClickM \e -> - e.hte_send $ execPut $ Binary.put exp +enqueueExpr cmd = ClickM \e -> + e.hte_send cmd {-# INLINE enqueueExpr #-} evalExpr :: Expr -> ClickM Expr -evalExpr exp = ClickM \e -> do - e.hte_send $ execPut $ Binary.put exp - return undefined +evalExpr cmd = ClickM \e -> do + e.hte_send cmd + e.hte_flush {-# INLINE evalExpr #-} -withBuffer :: Ptr Word8 -> Int -> (CStringLen -> IO ()) -> IO (Builder -> IO (), IO ()) -withBuffer buf bufSize consume = do - -- buf <- mallocBytes bufSize +withBuffer :: CStringLen -> (CStringLen -> IO ()) -> IO (Expr -> IO (), IO ()) +withBuffer (buf, bufSize) consume = do offset <- newIORef 0 - let write b = do + let write cmd = do off <- readIORef offset - newOff <- writeLoop (runBuilder b) off + let b = runBuilder $ execPut $ Binary.put cmd + newOff <- writeLoop b off writeIORef offset newOff writeLoop :: BufferWriter -> Int -> IO Int writeLoop bufWrite off = do (written, next) <- bufWrite (buf `plusPtr` off) (bufSize - off) + let off' = off + written case next of - Done -> pure $ off + written - More _size moreWrite -> do - consume (castPtr buf, bufSize) - writeLoop moreWrite 0 - Chunk chunk moreWrite -> do - unsafeUseAsCStringLen chunk consume - writeLoop moreWrite off + Done -> pure off' + More minSize _moreWrite + | off == 0 -> error $ "Buffer too small for this command, required at least " <> show minSize <> " bytes" + | otherwise -> do + unless (off == 0) $ consume (castPtr buf, off) + writeLoop bufWrite 0 + -- Chunk chunk moreWrite -> do + -- writeLoop (byteString chunk <> moreWrite) 0 flush = do off <- atomicModifyIORef' offset (0,) consume (castPtr buf, off) return (write, flush) -newInternalEnv :: Int -> (CStringLen -> IO ()) -> IO - ( InternalEnv - , IORef (Map Word32 (IO ValueExpr -> IO ())) - , CStringLen ) +newInternalEnv :: Int -> (CStringLen -> IO ()) -> IO (InternalEnv, CStringLen) newInternalEnv bufSize consume = do buf <- mallocBytes bufSize hte_state <- newIORef emptyState - (send', flush) <- withBuffer buf bufSize consume + (write, flush) <- withBuffer (buf, bufSize) consume hte_prompt_tag <- newPromptTag - continuations <- newIORef Map.empty - let env = InternalEnv - { hte_send = send' - , hte_flush = do - tid <- atomicModifyIORef' hte_state \s -> - (s {next_id = s.next_id + 1}, s.next_id) - send' $ execPut $ Binary.put $ YieldResult tid - flush - control hte_prompt_tag \c -> - modifyIORef' continuations $ Map.insert tid c - , hte_state - , hte_scope = ScopeId 0 - , hte_prompt_tag - } - pure (env, continuations, (castPtr buf, bufSize)) + hte_continuations <- newIORef Map.empty + let bufResult = (castPtr buf, bufSize) + pure ( + InternalEnv { + hte_send = write, + hte_flush = do + tid <- atomicModifyIORef' hte_state \s -> + (s {next_id = s.next_id + 1}, ContId s.next_id) + write $ Resume tid + flush + control hte_prompt_tag \c -> + modifyIORef' hte_continuations $ Map.insert tid c, + hte_state, + hte_scope = ScopeId 0, + hte_prompt_tag, + hte_continuations + }, bufResult + ) diff --git a/Clickable/Types.hs b/Clickable/Types.hs index c82d948..67c825b 100644 --- a/Clickable/Types.hs +++ b/Clickable/Types.hs @@ -35,8 +35,13 @@ import GHC.Types import GHC.Generics newtype ClickM a = ClickM {unClickM :: InternalEnv -> IO a} - deriving (Functor, Applicative, Monad, MonadIO, MonadReader InternalEnv) - via ReaderT InternalEnv IO + deriving ( + Functor, + Applicative, + Monad, + MonadIO, + MonadReader InternalEnv + ) via ReaderT InternalEnv IO instance MonadState InternalState ClickM where state f = ClickM \e -> @@ -47,27 +52,32 @@ instance MonadState InternalState ClickM where put s = ClickM \e -> writeIORef e.hte_state s {-# INLINE put #-} -data InternalEnv = InternalEnv - { hte_send :: Builder -> IO () - , hte_flush :: IO ValueExpr - , hte_state :: IORef InternalState - , hte_scope :: ScopeId - , hte_prompt_tag :: PromptTag () - } - -data InternalState = InternalState - { subscriptions :: [Subscription Any] - , finalizers :: [Finalizer] - , transaction_queue :: Map EventId (ClickM ()) - , next_id :: Word32 - } - -newtype HtmlM a = HtmlM - {unHtmlM :: Maybe RefId -> InternalEnv -> IO (a, Maybe RefId)} - deriving (Functor, Applicative, Monad, MonadIO) via StateT (Maybe RefId) ClickM - -liftClick :: ClickM a -> HtmlM a -liftClick (ClickM a) = HtmlM \s e -> (,s) <$> a e +data InternalEnv = InternalEnv { + hte_send :: Expr -> IO (), + hte_flush :: IO ValueExpr, + hte_state :: IORef InternalState, + hte_scope :: ScopeId, + hte_prompt_tag :: PromptTag (), + hte_continuations :: IORef (Map ContId (IO ValueExpr -> IO ())) +} + +data InternalState = InternalState { + subscriptions :: [Subscription Any], + finalizers :: [Finalizer], + transaction_queue :: Map EventId (ClickM ()), + next_id :: Word32 +} + +newtype HtmlM a = HtmlM {unHtmlM :: Maybe RefId -> InternalEnv -> IO (a, Maybe RefId)} + deriving ( + Functor, + Applicative, + Monad, + MonadIO + ) via StateT (Maybe RefId) ClickM + +liftC :: ClickM a -> HtmlM a +liftC (ClickM a) = HtmlM \s e -> (,s) <$> a e data Expr where Null :: Expr @@ -109,8 +119,8 @@ data Expr where PopIns :: Expr ElementProp :: Expr -> Text -> Expr -> Expr ElementAttr :: Expr -> Text -> Text -> Expr - ClassListAdd :: [Text] -> Expr - ClassListRemove :: [Text] -> Expr + ClassListAdd :: Expr -> Text -> Expr + ClassListRemove :: Expr -> Text -> Expr InsertBrackets :: Expr ClearBrackets :: Expr -> Expr DropBrackets :: Expr -> Expr @@ -122,7 +132,7 @@ data Expr where Eval :: UnsafeJavaScript -> Expr TriggerEvent :: EventId -> Expr -> Expr - YieldResult :: Word32 -> Expr + Resume :: ContId -> Expr deriving stock Generic deriving anyclass Binary @@ -130,7 +140,7 @@ data Expr where data ClientMsg where StartMsg :: StartFlags -> ClientMsg EventMsg :: EventId -> Expr -> ClientMsg - ResumeMsg :: Word32 -> Expr -> ClientMsg + ResumeMsg :: ContId -> Expr -> ClientMsg deriving stock Generic deriving anyclass Binary @@ -145,8 +155,10 @@ data RefId = RefId ScopeId Word32 deriving anyclass (Binary) newtype EventId = EventId {unEventId :: Word32} - deriving newtype (Show, Ord, Eq) - deriving newtype (Binary) + deriving newtype (Show, Ord, Eq, Binary) + +newtype ContId = ContId {unContId :: Word32} + deriving newtype (Show, Ord, Eq, Binary) newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} deriving newtype (IsString, Show, Semigroup, Monoid, Binary) @@ -192,27 +204,27 @@ fromVar = FromVar {-# INLINE fromVar #-} data Subscription a - = SubscriptionSimple - { ss_scope :: ScopeId - , ss_event_id :: Event a - , ss_callback :: a -> ClickM () - } - | forall b. SubscriptionAccum - { sa_resource_scope :: ScopeId - , sa_event_id :: Event a - , sa_callback :: a -> b -> ClickM b - , sa_accum_ref :: IORef b - } + = SubscriptionSimple { + ss_scope :: ScopeId, + ss_event_id :: Event a, + ss_callback :: a -> ClickM () + } + | forall b. SubscriptionAccum { + sa_resource_scope :: ScopeId, + sa_event_id :: Event a, + sa_callback :: a -> b -> ClickM b, + sa_accum_ref :: IORef b + } data Finalizer - = CustomFinalizer - { cf_resource_scope :: ScopeId - , cf_callback :: ClickM () - } - | ScopeFinalizer - { sf_resource_scope :: ScopeId - , sf_linked_scope :: ScopeId - } + = CustomFinalizer { + cf_resource_scope :: ScopeId, + cf_callback :: ClickM () + } + | ScopeFinalizer { + sf_resource_scope :: ScopeId, + sf_linked_scope :: ScopeId + } finalizerScope :: Finalizer -> ScopeId finalizerScope CustomFinalizer{cf_resource_scope} = cf_resource_scope @@ -403,6 +415,10 @@ instance GFromJSObject (x :*: y) => GFromValue (x :*: y) where gFromValue (Obj kvs) = gFromJSObject kvs gFromValue _ = Nothing +instance GFromJSSum (x :+: y) => GFromValue (x :+: y) where + gFromValue (Arr [Str tag, v]) = gFromJSSum tag v + gFromValue _ = Nothing + instance {-# OVERLAPPING #-} FromValue a => GFromValue (S1 s (Rec0 a)) where gFromValue = fmap (M1 . K1) . fromValue @a -------------------------------------------------------------------------------- @@ -419,6 +435,9 @@ instance GToValue U1 where instance GToJSObject (x :*: y) => GToValue (x :*: y) where gToValue (x :*: y) = Obj $ gToJSObject (x :*: y) +instance GToJSSum (x :+: y) => GToValue (x :+: y) where + gToValue = gToJSSum + instance {-# OVERLAPPING #-} (ToValue a) => GToValue (S1 s (Rec0 a)) where gToValue (M1 (K1 a)) = toValue a -------------------------------------------------------------------------------- @@ -453,6 +472,53 @@ instance {-# OVERLAPPING #-} (FromValue a, Selector s) => GFromJSObject (S1 s (R key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) -------------------------------------------------------------------------------- +class GFromJSSum (f :: Type -> Type) where + gFromJSSum :: Text -> ValueExpr -> Maybe (f x) + +instance (GFromJSSum x, GFromJSSum y) => GFromJSSum (x :+: y) where + gFromJSSum tag v = case gFromJSSum @x tag v of + Just a -> Just $ L1 a + Nothing -> case gFromJSSum @y tag v of + Just b -> Just $ R1 b + Nothing -> Nothing + +instance FromValue a => GFromValue (K1 R a) where + gFromValue v = fmap K1 $ fromValue @a v + +instance {-# OVERLAPPING #-} (GFromValue (f a), Constructor s) => GFromJSSum (C1 s (f a)) where + gFromJSSum tag v = + if tag == key then fmap M1 $ gFromValue v else Nothing + where + key = Text.pack $ conName (undefined :: C1 s (f a) x) + +instance {-# OVERLAPPING #-} Constructor s => GFromJSSum (C1 s U1) where + gFromJSSum tag _ = + if tag == key then Just (M1 U1) else Nothing + where + key = Text.pack $ conName (undefined :: C1 s (f a) x) +-------------------------------------------------------------------------------- + +class GToJSSum (f :: Type -> Type) where + gToJSSum :: f x -> ValueExpr + +instance (GToJSSum x, GToJSSum y) => GToJSSum (x :+: y) where + gToJSSum (L1 v) = gToJSSum v + gToJSSum (R1 v) = gToJSSum v + +instance ToValue a => GToValue (K1 R a) where + gToValue (K1 v) = toValue @a v + +instance {-# OVERLAPPING #-} (GToValue (f a), Constructor s) => GToJSSum (C1 s (f a)) where + gToJSSum (M1 v) = + Arr [Str key, gToValue v] + where + key = Text.pack $ conName (undefined :: C1 s (f a) x) + +instance {-# OVERLAPPING #-} Constructor s => GToJSSum (C1 s U1) where + gToJSSum (M1 U1) = Arr [Str key] where + key = Text.pack $ conName (undefined :: C1 s (f a) x) +-------------------------------------------------------------------------------- + {-| Boxed versions of [Delimited Continuation](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0313-delimited-continuation-primops.rst) primops. If you are not familiar with the concept, I highly recommend diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index 717ce97..670e6f0 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -16,28 +16,28 @@ import Control.Concurrent.Async (race) import Control.Exception (bracket, try) import Control.Monad import Control.Monad.State.Strict (modify) +import Data.Binary qualified as Binary import Data.Binary.Builder ( Builder ) import Data.ByteString (ByteString) import Data.ByteString.Base64.Lazy qualified as B64 +import Data.ByteString.Builder qualified as Builder +import Data.ByteString.Lazy qualified as BSL import Data.ByteString.Unsafe (unsafePackCStringLen) import Data.Data import Data.IORef import Data.Map (Map) +import Data.Map qualified as Map import Data.Tuple +import Data.Word import Foreign.Ptr import GHC.Generics import Network.HTTP.Types import Network.Wai import Network.Wai.Handler.WebSockets import Network.WebSockets -import qualified Data.Binary as Binary -import qualified Data.ByteString.Builder as Builder -import qualified Data.ByteString.Lazy as BSL -import qualified Data.Map as Map -import Data.Word -index :: Builder -> Builder -index content = +indexHtml :: Builder +indexHtml = "\n\ \\n\ \ \n\ @@ -48,65 +48,63 @@ index content = \ function fromB64(b64) {\n\ \ return Uint8Array.from(atob(b64), function(c) { return c.charCodeAt(0); });\n\ \ }\n\ - \ /*clickable.evalBuf(fromB64('" <> Builder.lazyByteString b64 <> "'));*/\n\ \ clickable.runWebsocket('/dev.sock');\n\ \ \n\ \ \n\ \" - where - b64 = B64.encode $ Builder.toLazyByteString content jsrts :: Builder jsrts = - "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeValue(e,t),encodeValue(e,n)}))}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.InsPop=31]=\"InsPop\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DropBrackets=38]=\"DropBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateTextNode=41]=\"CreateTextNode\",e[e.UpdateTextNode=42]=\"UpdateTextNode\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.YieldResult=45]=\"YieldResult\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null){const n=new WebSocket(e),r={refs:new Map,stack:null};function s(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.EventMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))}function i(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.ResumeMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))}n.onopen=e=>{const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.StartMsg,t]),n.send(new Uint8Array(outBuf).subarray(0,r.end))},n.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({triggerEvent:s,resumeCont:i,persistent:r,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(3e4,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=Iovec.read_bytes_array(l,t,n);let o=0;for(const t of _){const{ret:n,data:_}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return l.setUint32(i,o,!0),n;if(a.set(_,t.buf),o+=_.length,r+=BigInt(_.length),_.length!=t.buf_len)break}return l.setUint32(i,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const l=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(l.slice(0,n),t),l.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=Ciovec.read_bytes_array(l,t,n);let o=0;for(const t of _){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:_,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(_!=ERRNO_SUCCESS)return l.setUint32(i,o,!0),_;if(o+=f,r+=BigInt(f),f!=n.byteLength)break}return l.setUint32(i,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const a=Iovec.read_bytes_array(i,t,n);let _=0;for(const t of a){const{ret:n,data:a}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,_,!0),n;if(l.set(a,t.buf),_+=a.length,a.length!=t.buf_len)break}return i.setUint32(r,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let _=0;for(;;){const{ret:o,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=o)return l.setUint32(i,_,!0),o;if(null==f)break;if(n-_null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const a=Ciovec.read_bytes_array(i,t,n);let _=0;for(const t of a){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:a,nwritten:o}=s.fds[e].fd_write(n);if(a!=ERRNO_SUCCESS)return i.setUint32(r,_,!0),a;if(_+=o,o!=n.byteLength)break}return i.setUint32(r,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const l=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(a.slice(n,n+r)),{ret:o,filestat:f}=s.fds[e].path_filestat_get(t,_);return null!=f&&f.write_bytes(l,i),o}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,l,a){const _=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(_.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,o,i,l,a)}return ERRNO_BADF},path_link(e,t,n,r,i,l,a){const _=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const o=new TextDecoder(\"utf-8\").decode(_.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(_.slice(l,l+a)),{ret:u,inode_obj:E}=s.fds[e].path_lookup(o,t);return null==E?u:s.fds[i].path_link(f,E,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,l,a,_,o){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const E=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(E);const{ret:c,fd_obj:R}=s.fds[e].path_open(t,E,i,l,a,_);if(0!=c)return c;s.fds.push(R);const d=s.fds.length-1;return f.setUint32(o,d,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,l){const a=new DataView(s.inst.exports.memory.buffer),_=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(_.slice(t,t+n));debug.log(o);const{ret:f,data:u}=s.fds[e].path_readlink(o);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return a.setUint32(l,0,!0),ERRNO_BADF;_.set(e,r),a.setUint32(l,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,l){const a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const _=new TextDecoder(\"utf-8\").decode(a.slice(t,t+n)),o=new TextDecoder(\"utf-8\").decode(a.slice(i,i+l));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(_);if(null==u)return f;if(f=s.fds[r].path_link(o,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(_,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const l=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(l.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(l.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:l,path:a}=Path.from(t);if(null==a)return{ret:l,fd_obj:null};let{ret:_,entry:o}=this.dir.get_entry_for_path(a);if(null==o){if(_!=ERRNO_NOENT)return{ret:_,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};o=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&o.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:o.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:l,filename:a,entry:_}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==l||null==a)return i;if(null!=_){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=_.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&_ instanceof Directory))return ERRNO_EXIST;if(0!=_.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||_.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(l.contents.set(a,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==l?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:l})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==l?r:l.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:l}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==l?r:l instanceof Directory&&l.stat().filetype===FILETYPE_DIRECTORY?0!==l.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:l,filename:a,entry:_}=this.get_parent_dir_and_entry_for_path(r,!0);return null==l||null==a?{ret:i,entry:null}:null!=_?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),l.contents.set(a,s),_=s,{ret:ERRNO_SUCCESS,entry:_})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null){const n=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]),r={refs:new Map,stack:null};function s(e,t){const n=new DataView(inst.exports.memory.buffer),s={triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)},resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},persistent:r,mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:n.wasiImport,env:{clickable_eval_buffer:s}}))).then((e=>{inst=e,n.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}window.clickable={runWebsocket,runWasm}})();" + "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeValue(e,t),encodeValue(e,n)}))}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DropBrackets=38]=\"DropBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateTextNode=41]=\"CreateTextNode\",e[e.UpdateTextNode=42]=\"UpdateTextNode\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.YieldResult=45]=\"YieldResult\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null){const n=new WebSocket(e),r={refs:new Map,stack:null};function s(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.EventMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))}function i(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.ResumeMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))}n.onopen=e=>{const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.StartMsg,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))},n.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({triggerEvent:s,resumeCont:i,persistent:r,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(3e4,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null){const n=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]),r={refs:new Map,stack:null};function s(e,t){const n=new DataView(inst.exports.memory.buffer),s={triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)},resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},persistent:r,mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:n.wasiImport,env:{clickable_eval_buffer:s}}))).then((e=>{inst=e,n.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}window.clickable={runWebsocket,runWasm}})();" runApp :: ClickM () -> Application runApp app req respond = do let path = pathInfo req - html200 = respond . responseBuilder status200 [("Content-Type", "text/html")] - text200 = respond . responseBuilder status200 [("Content-Type", "text/plain")] wsi <- newWebSocketInstance () (const app) fallbackApp case path of [] -> - html200 $ index mempty - ["about"] -> text200 ("About Page") - ["dev.sock"] -> websocketsOr defaultConnectionOptions (websocketApp wsi) - fallbackApp req respond - _ -> text200 ("404 Not Found") + respond $ responseBuilder status200 [("Content-Type", "text/html")] indexHtml + ["dev.sock"] -> + websocketsOr defaultConnectionOptions (websocketApp wsi) + fallbackApp req respond + _ -> + respond $ responseLBS status404 [("Content-Type", "text/html")] "" fallbackApp :: Application fallbackApp _ respond = respond $ responseLBS status404 [(hContentType, "text/html; charset=utf-8")] "

Not found

\n" -data WebSocketInstance = forall a. Typeable a => WebSocketInstance - { conn_state_ref :: IORef (Map ConnectionId WebSocketConn) - , resource :: a - , client_app :: WebSocketConn -> StartFlags -> ClickM () - , server_app :: Application - , connection_lost :: WebSocketConn -> IO () - } +data WebSocketInstance = forall a. Typeable a => WebSocketInstance { + conn_state_ref :: IORef (Map ConnectionId WebSocketConn), + resource :: a, + client_app :: WebSocketConn -> StartFlags -> ClickM (), + server_app :: Application, + connection_lost :: WebSocketConn -> IO () +} -newWebSocketInstance :: Typeable a => - a -> (StartFlags -> ClickM ()) -> Application -> IO WebSocketInstance +newWebSocketInstance :: + Typeable a => + a -> + (StartFlags -> ClickM ()) -> + Application -> + IO WebSocketInstance newWebSocketInstance resource clientApp serverApp = do conn_state_ref <- newIORef Map.empty - return WebSocketInstance - { conn_state_ref - , resource - , client_app = const clientApp - , server_app = serverApp - , connection_lost = \_ -> pure () - } + return WebSocketInstance { + conn_state_ref, + resource, + client_app = const clientApp, + server_app = serverApp, + connection_lost = \_ -> pure () + } -data WebSocketConn = WebSocketConn - { connection :: Connection - , continuations :: IORef (Map Word32 (IO ValueExpr -> IO ())) - , internal_env :: InternalEnv - , command_chan :: Chan (ClickM ()) - -- ^ Writing to the Chan sends a command to the browser to execute - , connection_id :: ConnectionId - } deriving Generic +data WebSocketConn = WebSocketConn { + connection :: Connection, + internal_env :: InternalEnv, + command_chan :: Chan (ClickM ()), -- ^ Writing to the Chan sends a command to the browser to execute + connection_id :: ConnectionId +} newtype ConnectionId = ConnectionId {unConnectionId :: Int} deriving newtype (Ord, Show, Eq, Num, Enum) @@ -143,28 +141,25 @@ websocketApp self p = $ self.client_app conn flags reader conn (Right (ResumeMsg contId pload)) = prompt conn.internal_env.hte_prompt_tag do - awatingThread <- atomicModifyIORef' conn.continuations $ + awatingThread <- atomicModifyIORef' conn.internal_env.hte_continuations $ swap . Map.alterF (,Nothing) contId forM_ awatingThread \cont -> cont $ pure pload reader conn (Right (EventMsg eid arg)) = void $ runTransition conn.internal_env $ modify (triggerEventOp (unsafeFromEventId eid) arg) - -- BrowserMessage BeforeUnload -> - -- return () reader conn (Left a) = void $ runTransition conn.internal_env a newConn connection = mdo command_chan <- newChan - (internal_env, continuations, _) <- newInternalEnv (100 * 1024) \(ptr, len) -> do + (internal_env, _) <- newInternalEnv (100 * 1024) \(ptr, len) -> do bs <- unsafePackCStringLen (castPtr ptr, len) sendDataMessage connection $ Network.WebSockets.Binary $ BSL.fromStrict bs atomicModifyIORef' self.conn_state_ref \m -> - let conn = WebSocketConn - { internal_env - , connection - , command_chan - , connection_id = maybe 0 (succ . fst) $ Map.lookupMax m - , continuations - } - in (Map.insert conn.connection_id conn m, conn) + let conn = WebSocketConn { + internal_env, + connection, + command_chan, + connection_id = maybe 0 (succ . fst) $ Map.lookupMax m + } + in (Map.insert conn.connection_id conn m, conn) diff --git a/bin/nix-bins b/bin/nix-bins index 89e42f8..c118295 100755 --- a/bin/nix-bins +++ b/bin/nix-bins @@ -42,9 +42,7 @@ for command in "${commands[@]}"; do cat << EOF > "$script_path" #!/usr/bin/env sh -SCRIPT_DIR=\$(dirname "\$(realpath "\$0")") - -source "\${SCRIPT_DIR}/nix-shell-cache.sh" +source "\$(dirname "\$(realpath "\$0")")/nix-shell-cache.sh" ${command} "\$@" EOF diff --git a/jsbits/proto.ts b/jsbits/proto.ts index 2876cc4..7633c81 100644 --- a/jsbits/proto.ts +++ b/jsbits/proto.ts @@ -70,7 +70,7 @@ export enum ExprTag { PushStack, PopStack, - InsPop, + PopIns, ElementProp, ElementAttr, ClassListAdd, @@ -86,7 +86,7 @@ export enum ExprTag { Eval, TriggerEvent, - YieldResult, + Resume, } /** Encode `Expr` type as a union of disjoint n-tuples, keep in @@ -124,11 +124,11 @@ export type Expr = | [ExprTag.PushStack, Expr] | [ExprTag.PopStack] - | [ExprTag.InsPop, Expr, Expr] + | [ExprTag.PopIns, Expr, Expr] | [ExprTag.ElementProp, string, Expr] | [ExprTag.ElementAttr, string, string] - | [ExprTag.ClassListAdd, string[]] - | [ExprTag.ClassListRemove, string[]] + | [ExprTag.ClassListAdd, Expr, string[]] + | [ExprTag.ClassListRemove, Expr, string[]] | [ExprTag.InsertBrackets] | [ExprTag.ClearBrackets, Expr] | [ExprTag.DropBrackets, Expr] @@ -140,7 +140,7 @@ export type Expr = | [ExprTag.Eval, string] | [ExprTag.TriggerEvent, number, Expr] - | [ExprTag.YieldResult, number] + | [ExprTag.Resume, number] ; export type Ptr = number; @@ -298,7 +298,7 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u }; case ExprTag.Lam: { - const ptrEnd = lookAheadExpr(self.mem, self.begin); + const ptrEnd = lookaheadNext(self.mem, self.begin); if (self.isMutableMem) { const clonedBody = new Uint8Array(self.mem.buffer).slice(self.begin, ptrEnd); const ctxNew: EvalState = { @@ -430,14 +430,14 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u return res; }; - case ExprTag.InsPop: { + case ExprTag.PopIns: { if (!self.persistent.stack) { - throw new Error("InsPop: empty stack"); + throw new Error("PopIns: empty stack"); } const tip = self.persistent.stack[VAL] as Node; self.persistent.stack = self.persistent.stack[NEXT]; if (!self.persistent.stack) { - throw new Error("InsPop: empty stack"); + throw new Error("PopIns: empty stack"); } const parent = self.persistent.stack[VAL] as Element; utils.insert(parent, tip); @@ -458,10 +458,14 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u return null; }; case ExprTag.ClassListAdd: { - throw new Error("Unimplemented"); + const el = evalNext(self, args, prevRes) as Element; + const className = decodeString(self); + return el.classList.add(className); }; case ExprTag.ClassListRemove: { - throw new Error("Unimplemented"); + const el = evalNext(self, args, prevRes) as Element; + const className = decodeString(self); + return el.classList.remove(className); }; case ExprTag.InsertBrackets: { if (!self.persistent.stack) { @@ -510,7 +514,7 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u self.triggerEvent(eventId, pload); return null; }; - case ExprTag.YieldResult: { + case ExprTag.Resume: { const contId = self.mem.getUint32(self.begin, false); self.begin += 4; self.resumeCont(contId, prevRes); @@ -519,10 +523,10 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u } } -/** Parse next Expr without evaluating it. This is needed to clone - * body expression of the Lam +/** Parse next Expr without evaluating it. Required to clone lambda + * body to be able to run it later */ -export function lookAheadExpr(mem: DataView, ptr: Ptr): Ptr { +export function lookaheadNext(mem: DataView, ptr: Ptr): Ptr { const tag: ExprTag = mem.getInt8(ptr++); switch (tag) { @@ -570,229 +574,147 @@ export function lookAheadExpr(mem: DataView, ptr: Ptr): Ptr { const len = Number(mem.getBigUint64(ptr, false)); return ptr + 8 + len; }; - // case ExprTag.Arr: { - // const len = Number(view.getBigUint64(ptr, false)); - // const result = new Array(len).fill(undefined); - // let iter = ptr + 8; - // for (let i = 0; i < len; i++) { - // const [newIter, val] = interpBytes(self, mem, iter); - // result[i] = val; - // iter = newIter; - // } - // return [iter, result]; - // }; - // case ExprTag.Obj: { - // const len = Number(view.getBigUint64(ptr, false)); - // const result: Record = {}; - // let iter = ptr + 8; - - // for (let i = 0; i < len; i++) { - // const [newIter1, key] = decodeString(self, mem, iter); - // const [newIter2, val] = interpBytes(self, mem, newIter1); - - // result[key] = val; - // iter = newIter2; - // } - // return [iter, result]; - // }; - // case ExprTag.U8Arr: { - // const len = Number(view.getBigUint64(ptr, false)); - // const res = mem.subarray(ptr + 8, ptr + 8 + len); - // return [ptr + 8 + len, res]; - // }; - - // case ExprTag.Dot: { - // const [newPtr1, obj] = interpBytes(self, mem, ptr); - // const [newPtr2, key] = decodeString(self, mem, newPtr1); - // return [newPtr2, (obj as any)[key]]; - // }; - // case ExprTag.SetProp: { - // const [newPtr1, obj] = interpBytes(self, mem, ptr); - // const [newPtr2, key] = decodeString(self, mem, newPtr1); - // const [newPtr3, val] = interpBytes(self, mem, newPtr2); - // (obj as any)[key] = val; - // return [newPtr3, null]; - // }; - // case ExprTag.Ix: { - // const [newPtr1, obj] = interpBytes(self, mem, ptr); - // const key = view.getUint32(newPtr1); - // return [newPtr1 + 4, (obj as any)[key]] - // }; - // case ExprTag.Id: { - // const [newPtr, iden] = decodeString(self, mem, ptr); - // return [newPtr, (global as any)[iden]]; - // }; - - // case ExprTag.Lam: { - // throw new Error("Unimplemented"); - // }; - // case ExprTag.Arg: { - // const _argIx = view.getUint8(ptr); - // throw new Error("Unimplemented"); - // }; - // case ExprTag.Apply: { - // const [newPtr1, fn] = interpBytes(self, mem, ptr); - // const [newPtr2, arg] = interpBytes(self, mem, newPtr1); - // return [newPtr2, (fn as any)(arg)]; - // }; - // case ExprTag.Call: { - // const [newPtr1, obj] = interpBytes(self, mem, ptr); - // const [newPtr2, key] = decodeString(self, mem, newPtr1); - // const [newPtr3, arg] = interpBytes(self, mem, newPtr2); - // return [newPtr3, (obj as any)[key].call(obj, arg)]; - // }; - - // case ExprTag.AssignRef: { - // const scopeId = view.getUint32(ptr, true); - // const refId = view.getUint32(ptr + 4, true); - // const [newPtr, val] = interpBytes(self, mem, ptr + 8); - // if (self.refs.has(scopeId)) { - // const scopeMap = self.refs.get(scopeId)!; - // scopeMap.set(refId, val); - // } else { - // const scopeMap = new Map(); - // scopeMap.set(refId, val); - // self.refs.set(scopeId, scopeMap); - // } - // return [newPtr, val]; - // }; - // case ExprTag.FreeRef: { - // const scopeId = view.getUint32(ptr, true); - // const refId = view.getUint32(ptr + 4, true); - // const scopeMap = self.refs.get(scopeId); - // if (!scopeMap) return [ptr + 8, null]; - // scopeMap.delete(refId); - // if (scopeMap.size == 0) { - // self.refs.delete(scopeId); - // } - // return [ptr + 8, null]; - // }; - // case ExprTag.Ref: { - // const scopeId = view.getUint32(ptr, true); - // const refId = view.getUint32(ptr + 4, true); - // const val = self.refs.get(scopeId)?.get(refId); - // return [ptr + 8, val]; - // }; - // case ExprTag.FreeScope: { - // const scopeId = view.getUint32(ptr, true); - // self.refs.delete(scopeId); - // return [ptr + 4, null]; - // }; - - // case ExprTag.PeekStack: { - // const stackIx = view.getInt8(ptr); - // let iter = self.stack; - // let i = 0; - // while (iter) { - // if (i == stackIx) { - // return [ptr + 1, iter[VAL]]; - // } - // iter = iter[NEXT]; - // i++; - // } - // throw new Error("PeekStack: index out of stack size"); - // }; - // case ExprTag.PushStack: { - // const [newPtr, val] = interpBytes(self, mem, ptr); - // self.stack = Cons(val, self.stack); - // return [newPtr, val]; - // }; - // case ExprTag.PopStack: { - // if (!self.stack) { - // throw new Error("PopStack: empty stack"); - // } - // const val = self.stack[VAL]; - // self.stack = self.stack[NEXT]; - // return [ptr, val]; - // }; - - // case ExprTag.InsPop: { - // if (!self.stack) { - // throw new Error("InsPop: empty stack"); - // } - // const tip = self.stack[VAL] as Node; - // self.stack = self.stack[NEXT]; - // if (!self.stack) { - // throw new Error("InsPop: empty stack"); - // } - // const parent = self.stack[VAL] as Element; - // utils.insert(parent, tip); - // return [ptr, tip]; - // }; - // case ExprTag.ElementProp: { - // const [newPtr1, el] = interpBytes(self, mem, ptr); - // const [newPtr2, key] = decodeString(self, mem, newPtr1); - // const [newPtr3, val] = interpBytes(self, mem, newPtr2); - // utils.prop(el as any, key, val); - // return [newPtr3, null]; - // }; - // case ExprTag.ElementAttr: { - // const [newPtr1, el] = interpBytes(self, mem, ptr); - // const [newPtr2, key] = decodeString(self, mem, newPtr1); - // const [newPtr3, val] = decodeString(self, mem, newPtr2); - // utils.attr(el as any, key, val); - // return [newPtr3, null]; - // }; - // case ExprTag.ClassListAdd: { - // throw new Error("Unimplemented"); - // }; - // case ExprTag.ClassListRemove: { - // throw new Error("Unimplemented"); - // }; - // case ExprTag.InsertBrackets: { - // if (!self.stack) { - // throw new Error("InsertBrackets: empty stack"); - // } - // const el = self.stack[VAL] as any; - // const node = utils.insertBrackets(el); - // return [ptr, node]; - // }; - // case ExprTag.ClearBrackets: { - // const [newPtr, node] = interpBytes(self, mem, ptr); - // utils.clearBrackets(node as any, false); - // return [newPtr, null]; - // }; - // case ExprTag.DropBrackets: { - // const [newPtr, node] = interpBytes(self, mem, ptr); - // utils.clearBrackets(node as any, true); - // return [newPtr, null]; - // }; - // case ExprTag.CreateElement: { - // const [newPtr, tagName] = decodeString(self, mem, ptr); - // const el = document.createElement(tagName); - // return [newPtr, el]; - // }; - // case ExprTag.CreateElementNS: { - // const [newPtr1, tagName] = decodeString(self, mem, ptr); - // const [newPtr2, ns] = decodeString(self, mem, newPtr1); - // const el = document.createElementNS(tagName, ns); - // return [newPtr2, el]; - // }; - // case ExprTag.CreateTextNode: { - // const [newPtr, content] = decodeString(self, mem, ptr); - // const node = document.createTextNode(content); - // return [newPtr, node]; - // }; - // case ExprTag.UpdateTextNode: { - // const [newPtr1, node] = interpBytes(self, mem, ptr); - // const [newPtr2, content] = decodeString(self, mem, newPtr1); - // (node as Text).textContent = content; - // return [newPtr2, null]; - // }; - case ExprTag.Eval: { + case ExprTag.Arr: { + const len = Number(mem.getBigUint64(ptr, false)); + let iter = ptr + 8; + for (let i = 0; i < len; i++) { + iter = lookaheadNext(mem, iter); + } + return iter; + }; + case ExprTag.Obj: { + const len = Number(mem.getBigUint64(ptr, false)); + let iter = ptr + 8; + + for (let i = 0; i < len; i++) { + iter = lookaheadString(mem, iter); + iter = lookaheadNext(mem, iter); + } + return iter; + }; + case ExprTag.U8Arr: { const len = Number(mem.getBigUint64(ptr, false)); return ptr + 8 + len; }; + + case ExprTag.Dot: { + const newPtr = lookaheadNext(mem, ptr); + return lookaheadString(mem, newPtr); + }; + case ExprTag.SetProp: { + const newPtr0 = lookaheadNext(mem, ptr); + const newPtr1 = lookaheadString(mem, newPtr0); + return lookaheadNext(mem, newPtr1); + }; + case ExprTag.Ix: { + const newPtr = lookaheadNext(mem, ptr); + return newPtr + 4; + }; + case ExprTag.Id: { + return lookaheadString(mem, ptr); + }; + + case ExprTag.Lam: { + return lookaheadNext(mem, ptr); + }; + case ExprTag.Arg: { + return ptr + 1; + }; + case ExprTag.Apply: { + const newPtr0 = lookaheadNext(mem, ptr); + return lookaheadNext(mem, newPtr0); + }; + case ExprTag.Call: { + const newPtr0 = lookaheadNext(mem, ptr); + const newPtr1 = lookaheadString(mem, newPtr0); + return lookaheadNext(mem, newPtr1); + }; + + case ExprTag.AssignRef: { + return ptr + 8; + }; + case ExprTag.FreeRef: { + return ptr + 8; + }; + case ExprTag.Ref: { + return ptr + 8; + }; + case ExprTag.FreeScope: { + return ptr + 4; + }; + + case ExprTag.PeekStack: { + return ptr + 1; + }; + case ExprTag.PushStack: { + return lookaheadNext(mem, ptr); + }; + case ExprTag.PopStack: { + return ptr; + }; + + case ExprTag.PopIns: { + return ptr; + }; + case ExprTag.ElementProp: { + const newPtr0 = lookaheadNext(mem, ptr); + const newPtr1 = lookaheadString(mem, newPtr0); + return lookaheadNext(mem, newPtr1); + }; + case ExprTag.ElementAttr: { + const newPtr0 = lookaheadNext(mem, ptr); + const newPtr1 = lookaheadString(mem, newPtr0); + return lookaheadString(mem, newPtr1); + }; + case ExprTag.ClassListAdd: { + const newPtr0 = lookaheadNext(mem, ptr); + return lookaheadString(mem, newPtr0); + }; + case ExprTag.ClassListRemove: { + const newPtr0 = lookaheadNext(mem, ptr); + return lookaheadString(mem, newPtr0); + }; + case ExprTag.InsertBrackets: { + return ptr; + }; + case ExprTag.ClearBrackets: { + return lookaheadNext(mem, ptr); + }; + case ExprTag.DropBrackets: { + return lookaheadNext(mem, ptr); + }; + case ExprTag.CreateElement: { + return lookaheadString(mem, ptr); + }; + case ExprTag.CreateElementNS: { + const newPtr0 = lookaheadString(mem, ptr); + return lookaheadString(mem, newPtr0); + }; + case ExprTag.CreateTextNode: { + return lookaheadString(mem, ptr); + }; + case ExprTag.UpdateTextNode: { + const newPtr0 = lookaheadNext(mem, ptr); + return lookaheadString(mem, newPtr0); + }; + case ExprTag.Eval: { + return lookaheadString(mem, ptr); + }; case ExprTag.TriggerEvent: { - return lookAheadExpr(mem, ptr + 4); + return lookaheadNext(mem, ptr + 4); }; - case ExprTag.YieldResult: { + case ExprTag.Resume: { return ptr + 4; }; } throw new Error("lookAheadExpr: unimplemented"); } +export function lookaheadString(mem: DataView, ptr: Ptr): Ptr { + const len = Number(mem.getBigUint64(ptr, false)); + return ptr + 8 + len; +} + export type EncoderState = { readonly mem: DataView; begin: Ptr; diff --git a/jsbits/websocket.ts b/jsbits/websocket.ts index b98690d..bf2251c 100644 --- a/jsbits/websocket.ts +++ b/jsbits/websocket.ts @@ -14,19 +14,19 @@ export function runWebsocket(devSocketUri: string, startFlags: unknown = null) { function triggerEvent(eventId: EventId, arg: unknown) { const encoderState = {mem, begin: 0, end: outBuf.byteLength}; proto.encodeClientMessage(encoderState, [ClientMsgTag.EventMsg, eventId, arg]); - websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); + websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.begin)); }; function resumeCont(contId: number, res: unknown) { const encoderState = {mem, begin: 0, end: outBuf.byteLength}; proto.encodeClientMessage(encoderState, [ClientMsgTag.ResumeMsg, contId, res]); - websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); + websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.begin)); }; websocket.onopen = (_event) => { const encoderState = {mem, begin: 0, end: outBuf.byteLength}; proto.encodeClientMessage(encoderState, [ClientMsgTag.StartMsg, startFlags]); - websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.end)); + websocket.send(new Uint8Array(outBuf).subarray(0, encoderState.begin)); }; // Event handler for receiving messages from the server @@ -57,7 +57,7 @@ export function runWebsocket(devSocketUri: string, startFlags: unknown = null) { // Assuming the server went down because it was re-compiled, wait // until it comes back and reload the tab const websocketTest = new WebSocket(devSocketUri); - const nextTimeout = Math.min(30_000, timeout * 2); + const nextTimeout = Math.min(5_000, timeout * 2); websocketTest.onopen = (_event) => window.location.reload(); websocketTest.onclose = (_event) => { setTimeout(() => backoffLoop(nextTimeout), timeout); } } diff --git a/wasm.hs b/wasm.hs deleted file mode 100644 index 55b4d86..0000000 --- a/wasm.hs +++ /dev/null @@ -1,59 +0,0 @@ -{-# OPTIONS_GHC -Wno-unused-local-binds #-} -{-# LANGUAGE BlockArguments #-} -{-# LANGUAGE RecursiveDo #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE OverloadedRecordDot #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE StrictData #-} -{-# OPTIONS_GHC -Wno-unused-do-bind #-} -{-# LANGUAGE DataKinds #-} -module Main where - -import Clickable.Html -import Clickable.Internal -import Clickable.Types -import qualified Data.Text as Text -import Clickable.Wasm -import Data.Word -import Foreign (Ptr) -import Data.IORef -import Control.Monad.Reader - -test01 :: ClickM () -test01 = do - enqueueExpr $ PushStack $ Id "document" `Dot` "body" - counter <- newVar 0 - el "div" do - prop "className" (Str "container") - text "Lorem Ipsum" - el "h1" $ text "Fox jumps over a lazy dog" - el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" - el "button" do - text "Click Here" - on @"click" $ modifyVar_ counter succ - el "button" do - text "-" - on @"click" $ modifyVar_ counter pred - el "br" $ pure () - el "span" do - dynText $ fmap (Text.pack . show) $ fromVar counter - ref <- liftIO $ newIORef $ const $ pure () - el "div" do - el "button" do - text "Ask a Value" - on @"click" do - t <- asks (.hte_prompt_tag) - val <- liftIO $ control t \cont -> writeIORef ref cont - enqueueExpr $ Call (Id "console") "log" $ valueToExpr val - el "button" do - text "Fill the value" - on @"click" do - cont <- liftIO $ readIORef ref - liftIO $ cont $ pure $ Vobj [("this", Vstr "is"), ("some", Vstr "value")] - -main :: IO () -main = pure () - -foreign export ccall wasm_app :: Ptr Word8 -> IO (Ptr Word8) -wasm_app :: Ptr Word8 -> IO (Ptr Word8) -wasm_app = mkWasmApp test01 diff --git a/websocket.hs b/websocket.hs deleted file mode 100644 index 98938f5..0000000 --- a/websocket.hs +++ /dev/null @@ -1,63 +0,0 @@ -{-# LANGUAGE GHC2021 #-} -{-# LANGUAGE BlockArguments #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE OverloadedRecordDot #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE RecursiveDo #-} -module Main where - -import Clickable.Html -import Clickable.Internal -import Clickable.Types -import Clickable.WebSocket -import Control.Monad.IO.Class -import Control.Monad.Reader -import Data.IORef -import Network.Wai.Handler.Warp (run) -import Unsafe.Coerce (unsafeCoerce) -import qualified Data.Text as Text - -test01 :: ClickM () -test01 = do - counter <- newVar @Int 0 - attachToBody do - el "div" do - prop "className" (Str "container") - text "Lorem Ipsum" - el "h1" $ text "Fox jumps over a lazy dog" - el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" - el "button" do - text "Click Here" - on @"click" $ modifyVar_ counter succ - el "button" do - text "-" - on @"click" $ modifyVar_ counter pred - el "br" $ pure () - el "span" do - dynText $ fmap (Text.pack . show) $ fromVar counter - ref <- liftIO $ newIORef $ const $ pure () - el "div" do - el "button" do - text "Ask a Value" - on @"click" do - t <- asks (.hte_prompt_tag) - val <- liftIO $ control t \cont -> writeIORef ref cont - enqueueExpr $ Call (Id "console") "log" [val] - el "button" do - text "Fill the value" - on @"click" do - cont <- liftIO $ readIORef ref - liftIO $ cont $ pure $ Obj [("this", Str "is"), ("some", Str "value")] - -main :: IO () -main = do - run 3000 $ runApp test01 - -baz :: IO Int -baz = do - let z :: Int = unsafeCoerce False - return $ z * 2 - -bar :: Int -> Int -bar dsfsd = dsfsd From a37bec37e795c7ee0f01e5c462b08daee4697550 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 12 Nov 2024 10:28:38 +0400 Subject: [PATCH 57/64] Improve WebSocket Server --- Clickable/Internal.hs | 73 +++++++++++------ Clickable/WebSocket.hs | 179 ++++++++++++++++++++++++----------------- 2 files changed, 154 insertions(+), 98 deletions(-) diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index 4c3892c..509288f 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -27,6 +27,7 @@ import Foreign.Ptr import GHC.Exts import Unsafe.Coerce import Data.ByteString.Unsafe +import Data.ByteString (ByteString) newEvent :: ClickM (Event a) newEvent = state \s -> @@ -314,37 +315,57 @@ evalExpr cmd = ClickM \e -> do e.hte_flush {-# INLINE evalExpr #-} -withBuffer :: CStringLen -> (CStringLen -> IO ()) -> IO (Expr -> IO (), IO ()) -withBuffer (buf, bufSize) consume = do - offset <- newIORef 0 - let write cmd = do - off <- readIORef offset - let b = runBuilder $ execPut $ Binary.put cmd - newOff <- writeLoop b off - writeIORef offset newOff - writeLoop :: BufferWriter -> Int -> IO Int - writeLoop bufWrite off = do - (written, next) <- bufWrite (buf `plusPtr` off) (bufSize - off) - let off' = off + written - case next of - Done -> pure off' - More minSize _moreWrite - | off == 0 -> error $ "Buffer too small for this command, required at least " <> show minSize <> " bytes" - | otherwise -> do - unless (off == 0) $ consume (castPtr buf, off) - writeLoop bufWrite 0 - -- Chunk chunk moreWrite -> do - -- writeLoop (byteString chunk <> moreWrite) 0 - flush = do - off <- atomicModifyIORef' offset (0,) - consume (castPtr buf, off) - return (write, flush) +commandBuffer :: CStringLen -> (CStringLen -> IO ()) -> IO (Expr -> IO (), IO ()) +commandBuffer (buf, bufSize) consume = do + ref <- newIORef 0 + return (write ref, flush ref) + where + write :: IORef Int -> Expr -> IO () + write ref cmd = do + off <- readIORef ref + let b = runBuilder $ execPut $ Binary.put cmd + newOff <- writeCommand b off + writeIORef ref newOff + + writeCommand :: BufferWriter -> Int -> IO Int + writeCommand bufWrite off = do + (written, next) <- bufWrite (buf `plusPtr` off) (bufSize - off) + let off' = off + written + case next of + Done -> pure off' + More minSize _moreWrite + | off == 0 -> + error $ "Buffer too small, encountered command that requires at \ + \least " <> show minSize <> " bytes" + | otherwise -> do + consume (castPtr buf, off) + writeRemains bufWrite 0 + Chunk chunk moreWrite -> do + off1 <- writeRemains (runBuilder $ execPut $ Binary.put chunk) off + writeRemains moreWrite off1 + + writeRemains :: BufferWriter -> Int -> IO Int + writeRemains bufWrite off = do + (written, next) <- bufWrite (buf `plusPtr` off) (bufSize - off) + let off' = off + written + case next of + Done -> pure off' + More _minSize _moreWrite -> + error $ "Buffer too small, inscrease the buffer size" + Chunk chunk moreWrite -> do + off1 <- writeRemains (runBuilder $ execPut $ Binary.put chunk) off + writeRemains moreWrite off1 + + flush :: IORef Int -> IO () + flush ref = do + off <- atomicModifyIORef' ref (0,) + consume (castPtr buf, off) newInternalEnv :: Int -> (CStringLen -> IO ()) -> IO (InternalEnv, CStringLen) newInternalEnv bufSize consume = do buf <- mallocBytes bufSize hte_state <- newIORef emptyState - (write, flush) <- withBuffer (buf, bufSize) consume + (write, flush) <- commandBuffer (buf, bufSize) consume hte_prompt_tag <- newPromptTag hte_continuations <- newIORef Map.empty let bufResult = (castPtr buf, bufSize) diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index 670e6f0..22553f8 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -7,110 +7,96 @@ {-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DerivingStrategies #-} +{-# OPTIONS_GHC -Wall #-} module Clickable.WebSocket where import Clickable.Internal import Clickable.Types import Control.Concurrent import Control.Concurrent.Async (race) -import Control.Exception (bracket, try) +import Control.Exception import Control.Monad import Control.Monad.State.Strict (modify) import Data.Binary qualified as Binary import Data.Binary.Builder ( Builder ) import Data.ByteString (ByteString) -import Data.ByteString.Base64.Lazy qualified as B64 -import Data.ByteString.Builder qualified as Builder import Data.ByteString.Lazy qualified as BSL import Data.ByteString.Unsafe (unsafePackCStringLen) -import Data.Data import Data.IORef import Data.Map (Map) import Data.Map qualified as Map import Data.Tuple -import Data.Word import Foreign.Ptr -import GHC.Generics +import GHC.IO.Exception import Network.HTTP.Types import Network.Wai +import Network.Wai.Application.Static +import Network.Wai.Handler.Warp qualified as Warp import Network.Wai.Handler.WebSockets import Network.WebSockets +import System.IO -indexHtml :: Builder -indexHtml = - "\n\ - \\n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \" - -jsrts :: Builder -jsrts = - "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeValue(e,t),encodeValue(e,n)}))}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DropBrackets=38]=\"DropBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateTextNode=41]=\"CreateTextNode\",e[e.UpdateTextNode=42]=\"UpdateTextNode\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.YieldResult=45]=\"YieldResult\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null){const n=new WebSocket(e),r={refs:new Map,stack:null};function s(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.EventMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))}function i(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.ResumeMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))}n.onopen=e=>{const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.StartMsg,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))},n.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({triggerEvent:s,resumeCont:i,persistent:r,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(3e4,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null){const n=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]),r={refs:new Map,stack:null};function s(e,t){const n=new DataView(inst.exports.memory.buffer),s={triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)},resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},persistent:r,mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:n.wasiImport,env:{clickable_eval_buffer:s}}))).then((e=>{inst=e,n.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}window.clickable={runWebsocket,runWasm}})();" - -runApp :: ClickM () -> Application -runApp app req respond = do - let path = pathInfo req - wsi <- newWebSocketInstance () (const app) fallbackApp - case path of - [] -> - respond $ responseBuilder status200 [("Content-Type", "text/html")] indexHtml - ["dev.sock"] -> - websocketsOr defaultConnectionOptions (websocketApp wsi) - fallbackApp req respond - _ -> - respond $ responseLBS status404 [("Content-Type", "text/html")] "" - -fallbackApp :: Application -fallbackApp _ respond = respond $ responseLBS status404 - [(hContentType, "text/html; charset=utf-8")] - "

Not found

\n" +data ServerConfig = ServerConfig { + srv_html_template :: TemplateConfig -> Builder, + srv_docroots :: [FilePath], + srv_client :: WebSocketConn -> StartFlags -> ClickM (), + srv_connection_lost :: WebSocketConn -> IO () +} -data WebSocketInstance = forall a. Typeable a => WebSocketInstance { - conn_state_ref :: IORef (Map ConnectionId WebSocketConn), - resource :: a, - client_app :: WebSocketConn -> StartFlags -> ClickM (), - server_app :: Application, - connection_lost :: WebSocketConn -> IO () +data ServerInstance = ServerInstance { + sri_connection_state :: IORef (Map ConnectionId WebSocketConn) } -newWebSocketInstance :: - Typeable a => - a -> - (StartFlags -> ClickM ()) -> - Application -> - IO WebSocketInstance -newWebSocketInstance resource clientApp serverApp = do - conn_state_ref <- newIORef Map.empty - return WebSocketInstance { - conn_state_ref, - resource, - client_app = const clientApp, - server_app = serverApp, - connection_lost = \_ -> pure () - } +data TemplateConfig = TemplateConfig { + tpc_jsrts :: Builder, + tpc_websocket_addr :: Builder +} data WebSocketConn = WebSocketConn { connection :: Connection, internal_env :: InternalEnv, - command_chan :: Chan (ClickM ()), -- ^ Writing to the Chan sends a command to the browser to execute + -- | Writing to the Chan sends a command to the browser to execute + command_chan :: Chan (ClickM ()), connection_id :: ConnectionId } newtype ConnectionId = ConnectionId {unConnectionId :: Int} deriving newtype (Ord, Show, Eq, Num, Enum) -websocketApp :: WebSocketInstance -> ServerApp -websocketApp self p = +newServer :: IO ServerInstance +newServer = do + sri_connection_state <- newIORef Map.empty + pure ServerInstance { + sri_connection_state + } + +waiApp :: ServerConfig -> ServerInstance -> Application +waiApp cfg self req respond = route $ pathInfo req + where + route [] = respond $ responseBuilder ok200 + [("Content-Type", "text/html")] template + route ["dev.sock"] = websocketsOr + defaultConnectionOptions (websocketApp cfg self) fallbackApp req respond + route _ = staticApp' cfg.srv_docroots fallbackApp req respond + + staticApp' :: [FilePath] -> Middleware + staticApp' [] next = next + staticApp' (docroot:docroots) next = + staticApp (defaultFileServerSettings docroot) + {ss404Handler = Just (staticApp' docroots next)} + + template = cfg.srv_html_template TemplateConfig { + tpc_jsrts = jsrts, + tpc_websocket_addr = "/dev.sock" + } + +fallbackApp :: Application +fallbackApp _ respond = respond $ responseLBS status404 + [(hContentType, "text/html; charset=utf-8")] + "

Not found

\n" + +websocketApp :: ServerConfig -> ServerInstance -> ServerApp +websocketApp cfg self p = bracket acceptConn dropConn \connInfo -> withPingThread connInfo.connection 30 (pure ()) $ loop connInfo where @@ -118,8 +104,8 @@ websocketApp self p = conn <- acceptRequest p newConn conn dropConn (conn::WebSocketConn) = do - modifyIORef' (conn_state_ref self) $ Map.delete conn.connection_id - self.connection_lost conn + modifyIORef' self.sri_connection_state $ Map.delete conn.connection_id + cfg.srv_connection_lost conn loop (conn::WebSocketConn) = do raceResult <- race (try @ConnectionException (receiveData conn.connection)) @@ -138,7 +124,7 @@ websocketApp self p = reader :: WebSocketConn -> Either (ClickM ()) ClientMsg -> IO () reader conn (Right (StartMsg flags)) = void $ runTransition conn.internal_env - $ self.client_app conn flags + $ cfg.srv_client conn flags reader conn (Right (ResumeMsg contId pload)) = prompt conn.internal_env.hte_prompt_tag do awatingThread <- atomicModifyIORef' conn.internal_env.hte_continuations $ @@ -155,7 +141,7 @@ websocketApp self p = (internal_env, _) <- newInternalEnv (100 * 1024) \(ptr, len) -> do bs <- unsafePackCStringLen (castPtr ptr, len) sendDataMessage connection $ Network.WebSockets.Binary $ BSL.fromStrict bs - atomicModifyIORef' self.conn_state_ref \m -> + atomicModifyIORef' self.sri_connection_state \m -> let conn = WebSocketConn { internal_env, connection, @@ -163,3 +149,52 @@ websocketApp self p = connection_id = maybe 0 (succ . fst) $ Map.lookupMax m } in (Map.insert conn.connection_id conn m, conn) + +tryPorts :: Warp.Settings -> Application -> IO () +tryPorts set app = do + hPutStrLn stderr $ "Development Server is running at http://localhost:" <> + show (Warp.getPort set) <> "/" + result <- try $ Warp.runSettings set app + case result of + Right () -> return () + Left (e::IOException) + | ioe_type e == ResourceBusy -> do + hPutStrLn stderr $ "Already in use, trying next port…" + tryPorts (Warp.setPort (Warp.getPort set + 1) set) app + | otherwise -> throwIO e + +runDefault :: ClickM () -> IO () +runDefault client = runConfig + ServerConfig { + srv_html_template = defaultTemplate, + srv_docroots = [], + srv_client = const $ const client, + srv_connection_lost = const $ pure () + } + +runConfig :: ServerConfig -> IO () +runConfig = runConfig' Warp.defaultSettings + +runConfig' :: Warp.Settings -> ServerConfig -> IO () +runConfig' set cfg = do + self <- newServer + tryPorts set $ waiApp cfg self + +defaultTemplate :: TemplateConfig -> Builder +defaultTemplate cfg = + "\n\ + \\n\ + \ \n\ + \ \n\ + \ \n\ + \ \n\ + \ \n\ + \" + +-- yarn run webpack --mode production && cat dist-newstyle/index.bundle.js | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' +jsrts :: Builder +jsrts = + "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeValue(e,t),encodeValue(e,n)}))}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DropBrackets=38]=\"DropBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateTextNode=41]=\"CreateTextNode\",e[e.UpdateTextNode=42]=\"UpdateTextNode\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.YieldResult=45]=\"YieldResult\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null){const n=new WebSocket(e),r={refs:new Map,stack:null};function s(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.EventMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))}function i(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.ResumeMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))}n.onopen=e=>{const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.StartMsg,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))},n.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({triggerEvent:s,resumeCont:i,persistent:r,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(3e4,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null){const n=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]),r={refs:new Map,stack:null};function s(e,t){const n=new DataView(inst.exports.memory.buffer),s={triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)},resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},persistent:r,mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:n.wasiImport,env:{clickable_eval_buffer:s}}))).then((e=>{inst=e,n.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}window.clickable={runWebsocket,runWasm}})();" From 6bb36443e7d35f9772f05a3d98a63bc6947b11ef Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 15 Nov 2024 18:59:19 +0400 Subject: [PATCH 58/64] Renaming --- Clickable.hs | 2 +- Clickable/Element.hs | 8 +- Clickable/{Html.hs => HTML.hs} | 133 +++++++++++++++--------- Clickable/Internal.hs | 84 ++++++++-------- Clickable/Property.hs | 178 ++++++++++++++++----------------- Clickable/Types.hs | 52 +++++----- Clickable/Wasm.hs | 2 +- Clickable/WebSocket.hs | 44 ++++---- clickable.cabal | 2 +- wasm.hs | 59 +++++++++++ websocket.hs | 63 ++++++++++++ 11 files changed, 395 insertions(+), 232 deletions(-) rename Clickable/{Html.hs => HTML.hs} (57%) create mode 100644 wasm.hs create mode 100644 websocket.hs diff --git a/Clickable.hs b/Clickable.hs index 224933d..0e080a5 100644 --- a/Clickable.hs +++ b/Clickable.hs @@ -2,7 +2,7 @@ Native GHC -} module Clickable (module Exports) where -import Clickable.Html as Exports +import Clickable.HTML as Exports import Clickable.Element as Exports import Clickable.Property as Exports import Clickable.Internal as Exports diff --git a/Clickable/Element.hs b/Clickable/Element.hs index e558569..2c0a821 100644 --- a/Clickable/Element.hs +++ b/Clickable/Element.hs @@ -8,7 +8,7 @@ Shortcuts for most common HTML5 elements -} module Clickable.Element where -import Clickable.Html +import Clickable.HTML import Clickable.Types import Data.Text @@ -28,13 +28,13 @@ class Term arg result | result -> arg where -> result -- ^ Result: either an element or an attribute. -- | Given attributes, expect more child input. -instance f ~ HtmlM a => Term [HtmlM ()] (f -> HtmlM a) where +instance f ~ HTML a => Term [HTML ()] (f -> HTML a) where term name attrs = el name . (sequence_ attrs *>) {-# INLINE term #-} -- | Given children immediately, just use that and expect no -- attributes. -instance Term (HtmlM a) (HtmlM a) where +instance Term (HTML a) (HTML a) where term = el {-# INLINE term #-} @@ -362,7 +362,7 @@ sup_ :: Term arg result => arg -> result sup_ = term "sup" {-# INLINE sup_ #-} -br_ :: HtmlM () +br_ :: HTML () br_ = el "br" blank {-# INLINE br_ #-} diff --git a/Clickable/Html.hs b/Clickable/HTML.hs similarity index 57% rename from Clickable/Html.hs rename to Clickable/HTML.hs index 1e15303..1eed52c 100644 --- a/Clickable/Html.hs +++ b/Clickable/HTML.hs @@ -9,7 +9,7 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# OPTIONS_GHC -Wall #-} -module Clickable.Html where +module Clickable.HTML where import Clickable.Internal import Clickable.Types @@ -19,90 +19,90 @@ import Data.Text (Text) import GHC.Generics (Generic) import Unsafe.Coerce (unsafeCoerce) -el :: Text -> HtmlM a -> HtmlM a -el tagName child = HtmlM \s e -> do +el :: Text -> HTML a -> HTML a +el tagName child = HTML \s e -> do e.hte_send $ PushStack $ CreateElement tagName - (r, _) <- child.unHtmlM Nothing e + (r, _) <- child.unHTML Nothing e e.hte_send PopIns pure (r, s) {-# INLINE el #-} -elns :: Text -> Text -> HtmlM a -> HtmlM a -elns ns tagName child = HtmlM \s e -> do +elns :: Text -> Text -> HTML a -> HTML a +elns ns tagName child = HTML \s e -> do e.hte_send $ PushStack $ CreateElementNS ns tagName - (r, _) <- child.unHtmlM s e + (r, _) <- child.unHTML s e e.hte_send PopIns pure (r, s) {-# INLINE elns #-} -text :: Text -> HtmlM () -text content = HtmlM \s e -> do +text :: Text -> HTML () +text content = HTML \s e -> do e.hte_send $ PushStack $ CreateTextNode content e.hte_send PopIns return ((), s) {-# INLINE text #-} -dynText :: DynVal Text -> HtmlM () -dynText contentDyn = HtmlM \s e -> do +dynText :: Dynamic Text -> HTML () +dynText contentDyn = HTML \s e -> do c <- readVal contentDyn - refId <- newRefId.unClickM e + refId <- newRefId.unJSM e e.hte_send $ PushStack $ CreateTextNode c e.hte_send $ AssignRef refId (PeekStack 0) e.hte_send PopIns - let k nval = ClickM \e' -> + let k nval = JSM \e' -> e'.hte_send $ UpdateTextNode (Ref refId) nval - (subscribe contentDyn k).unClickM e + (subscribe contentDyn k).unJSM e pure ((), s) {-# INLINEABLE dynText #-} -property :: ToValue val => Text -> val -> HtmlM () -property k v = HtmlM \s e -> do +property :: ToValue val => Text -> val -> HTML () +property k v = HTML \s e -> do e.hte_send $ ElementProp (PeekStack 0) k $ toValue v pure ((), s) {-# INLINE property #-} -dynProp :: ToValue val => Text -> DynVal val -> HtmlM () -dynProp propName dynVal = HtmlM \s e -> do - (refId, s') <- saveStackTip.unHtmlM s e +dynProp :: ToValue val => Text -> Dynamic val -> HTML () +dynProp propName dynVal = HTML \s e -> do + (refId, s') <- saveStackTip.unHTML s e initVal <- readVal dynVal e.hte_send $ ElementProp (PeekStack 0) propName $ toValue initVal - let k nval = ClickM \e' -> + let k nval = JSM \e' -> e'.hte_send $ ElementProp (Ref refId) propName $ toValue nval - unClickM (subscribe dynVal k) e + unJSM (subscribe dynVal k) e pure ((), s') {-# INLINE dynProp #-} -attribute :: Text -> Text -> HtmlM () -attribute k v = HtmlM \s e -> do +attribute :: Text -> Text -> HTML () +attribute k v = HTML \s e -> do e.hte_send $ ElementAttr (PeekStack 0) k v pure ((), s) {-# INLINE attribute #-} -dynAttr :: Text -> DynVal Text -> HtmlM () -dynAttr propName dynVal = HtmlM \s e -> do - (refId, s') <- saveStackTip.unHtmlM s e +dynAttr :: Text -> Dynamic Text -> HTML () +dynAttr propName dynVal = HTML \s e -> do + (refId, s') <- saveStackTip.unHTML s e initVal <- readVal dynVal e.hte_send $ ElementAttr (PeekStack 0) propName initVal - let k nval = ClickM \e' -> + let k nval = JSM \e' -> e'.hte_send $ ElementAttr (Ref refId) propName nval - unClickM (subscribe dynVal k) e + unJSM (subscribe dynVal k) e pure ((), s') {-# INLINE dynAttr #-} -toggleClass :: Text -> DynVal Bool -> HtmlM () -toggleClass className dynEnable = HtmlM \s e -> do - (refId, s') <- saveStackTip.unHtmlM s e +toggleClass :: Text -> Dynamic Bool -> HTML () +toggleClass className dynEnable = HTML \s e -> do + (refId, s') <- saveStackTip.unHTML s e v <- readVal dynEnable - let k enable = ClickM \e' -> e'.hte_send + let k enable = JSM \e' -> e'.hte_send if enable then ClassListAdd (Ref refId) className else ClassListRemove (Ref refId) className - unClickM (k v) e - unClickM (subscribe dynEnable k) e + unJSM (k v) e + unJSM (subscribe dynEnable k) e pure ((), s') {-# INLINE toggleClass #-} -addEventListener :: FromValue a => (Event a -> Expr) -> (a -> ClickM ()) -> ClickM () +addEventListener :: FromValue a => (Event a -> Expr) -> (a -> JSM ()) -> JSM () addEventListener connectScript k = do e <- reactive \scope s -> let k' = local (\e -> e {hte_scope = scope}) . k @@ -116,13 +116,13 @@ addEventListener connectScript k = do class IsEventName eventName where type EventListenerCb eventName :: Type - connectEventName :: EventListenerCb eventName -> ClickM () + connectEventName :: EventListenerCb eventName -> JSM () -on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HtmlM () -on k = liftC $ connectEventName @eventName k +on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HTML () +on k = liftJSM $ connectEventName @eventName k instance IsEventName "click" where - type EventListenerCb "click" = ClickM () + type EventListenerCb "click" = JSM () connectEventName k = addEventListener (genericEvent defaultEventListenerOptions "click" (PeekStack 0)) (const k) @@ -157,21 +157,21 @@ unsafeConnectEvent :: Expr -> UnsafeJavaScript -> Event a -> Expr unsafeConnectEvent target ujs (Event eid) = Eval ujs `Apply` [target, Lam (TriggerEvent eid (Arg 0))] -attachHtml :: Expr -> HtmlM a -> ClickM a -attachHtml rootEl contents = ClickM \e -> do +attachHTML :: Expr -> HTML a -> JSM a +attachHTML rootEl contents = JSM \e -> do e.hte_send $ PushStack rootEl - (r, _) <- contents.unHtmlM Nothing e + (r, _) <- contents.unHTML Nothing e e.hte_send PopStack pure r -attachToBody :: HtmlM a -> ClickM a -attachToBody = attachHtml $ Id "document" `Dot` "body" +attachToBody :: HTML a -> JSM a +attachToBody = attachHTML $ Id "document" `Dot` "body" -saveStackTip :: HtmlM RefId -saveStackTip = HtmlM \s e -> +saveStackTip :: HTML RefId +saveStackTip = HTML \s e -> case s of Nothing -> do - refId <- newRefId.unClickM e + refId <- newRefId.unJSM e e.hte_send $ AssignRef refId $ PeekStack 0 return (refId, Just refId) Just saved -> @@ -180,3 +180,42 @@ saveStackTip = HtmlM \s e -> blank :: Applicative m => m () blank = pure () {-# INLINE blank #-} + +data Location = Location { + -- | A string containing the protocol scheme of the URL, including + -- the final ':' + protocol :: Text, + -- | A string containing the domain of the URL. + hostname :: Text, + -- | A string containing the port number of the URL. + port :: Text, + -- | A string containing an initial '/' followed by the path of the + -- URL, not including the query string or fragment. + pathname :: Text, + -- | String containing a '?' followed by the parameters or + -- "querystring" of the URL + search :: Text, + -- | String containing a '#' followed by the fragment identifier + -- of the URL. + hash :: Text +} deriving stock (Show, Eq, Generic) + deriving anyclass (FromValue, ToValue) + +-- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event +popstateEvent :: Event Location -> Expr +popstateEvent (Event eventId) = + Eval + "(function(target, trigger){\n\ + \ function listener(){\n\ + \ trigger({\n\ + \ protocol: location.protocol,\n\ + \ hostname: location.hostname,\n\ + \ port: location.port,\n\ + \ pathname: location.pathname,\n\ + \ search: location.search,\n\ + \ hash: location.hash\n\ + \ });\n\ + \ }\n\ + \ target.addEventListener('popstate', listener);\n\ + \ return () => target.removeEventListener('popstate', listener);\n\ + \})" `Apply` [Id "window", Lam (TriggerEvent eventId (Arg 0))] diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index 509288f..4f507eb 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -12,7 +12,6 @@ import Control.Monad.Reader import Control.Monad.State.Strict import Data.Binary qualified as Binary import Data.Binary.Put (execPut) -import Data.ByteString.Builder ( Builder, byteString ) import Data.ByteString.Builder.Extra (runBuilder, Next (..), BufferWriter) import Data.Functor.Const import Data.IORef @@ -20,37 +19,34 @@ import Data.List qualified as List import Data.Map qualified as Map import Data.Text (Text) import Data.Tuple (swap) -import Data.Word import Foreign.C.String (CStringLen) import Foreign.Marshal.Alloc (mallocBytes) import Foreign.Ptr import GHC.Exts import Unsafe.Coerce -import Data.ByteString.Unsafe -import Data.ByteString (ByteString) -newEvent :: ClickM (Event a) +newEvent :: JSM (Event a) newEvent = state \s -> (Event (EventId s.next_id), s {next_id = s.next_id + 1}) -mapEvent :: (a -> b) -> Event a -> ClickM (Event b) +mapEvent :: (a -> b) -> Event a -> JSM (Event b) mapEvent f ea = do eb <- newEvent subscribeEvent ea $ triggerEvent eb . f return eb -mapMaybeEvent :: (a -> Maybe b) -> Event a -> ClickM (Event b) +mapMaybeEvent :: (a -> Maybe b) -> Event a -> JSM (Event b) mapMaybeEvent f ea = do eb <- newEvent subscribeEvent ea $ mapM_ (triggerEvent eb) . f return eb -subscribeEvent :: forall a. Event a -> (a -> ClickM ()) -> ClickM () +subscribeEvent :: forall a. Event a -> (a -> JSM ()) -> JSM () subscribeEvent (Event eid) k = reactive_ g where newSub scope = SubscriptionSimple scope (coerce eid) (k . unsafeCoerce) g scope s = s {subscriptions = newSub scope : s.subscriptions} -subscribe :: forall a. DynVal a -> (a -> ClickM ()) -> ClickM () +subscribe :: forall a. Dynamic a -> (a -> JSM ()) -> JSM () subscribe (ConstVal _) _ = return () subscribe (FromVar (SourceVar srcid _)) k = reactive_ g where newSub scope = SubscriptionSimple scope (coerce srcid) (k . unsafeCoerce) @@ -89,7 +85,7 @@ triggerEventOp event pload = eventEq :: forall a b. Event a -> Event b -> Bool eventEq (Event a) (Event b) = a == b - notify :: [Subscription Any] -> ClickM () + notify :: [Subscription Any] -> JSM () notify [] = return () notify (SubscriptionSimple {ss_event_id, ss_callback} : xs) | ss_event_id `eventEq` event = ss_callback (unsafeCoerce pload) >> notify xs @@ -97,58 +93,58 @@ triggerEventOp event pload = notify (SubscriptionAccum {sa_event_id, sa_callback, sa_accum_ref} : xs) | sa_event_id `eventEq` event = notifyAcc sa_callback sa_accum_ref >> notify xs | otherwise = notify xs - notifyAcc :: forall b. (Any -> b -> ClickM b) -> IORef b -> ClickM () + notifyAcc :: forall b. (Any -> b -> JSM b) -> IORef b -> JSM () notifyAcc k ref = do acc <- liftIO $ readIORef ref acc' <- k (unsafeCoerce pload) acc liftIO $ writeIORef ref acc' - defer :: Event a -> ClickM () -> InternalState -> InternalState + defer :: Event a -> JSM () -> InternalState -> InternalState defer k act s = s {transaction_queue = Map.insert k.unEvent act s.transaction_queue} -triggerEvent :: Event a -> a -> ClickM () +triggerEvent :: Event a -> a -> JSM () triggerEvent e a = modify $ triggerEventOp e a {-# INLINE triggerEvent #-} -reactive :: (ScopeId -> InternalState -> (InternalState, a)) -> ClickM a -reactive f = ClickM \e -> atomicModifyIORef' e.hte_state $ f e.hte_scope +reactive :: (ScopeId -> InternalState -> (InternalState, a)) -> JSM a +reactive f = JSM \e -> atomicModifyIORef' e.hte_state $ f e.hte_scope {-# INLINE reactive #-} -reactive_ :: (ScopeId -> InternalState -> InternalState) -> ClickM () +reactive_ :: (ScopeId -> InternalState -> InternalState) -> JSM () reactive_ f = reactive \scope s -> (f scope s, ()) {-# INLINE reactive_ #-} -- | Loop until transaction_queue is empty. -- --- Makes possible to implement @Applicative DynVal@ without invoking +-- Makes possible to implement @Applicative Dynamic@ without invoking -- subscribers redundantly when multiple events are fired in the same -- transition -trampoline :: ClickM a -> ClickM a +trampoline :: JSM a -> JSM a trampoline act = loop0 act where - loop0 :: ClickM a -> ClickM a + loop0 :: JSM a -> JSM a loop0 before = do r <- before mcont <- popQueue forM_ mcont loop1 return r - loop1 :: ClickM () -> ClickM () + loop1 :: JSM () -> JSM () loop1 before = do before mcont <- popQueue forM_ mcont loop1 - popQueue :: ClickM (Maybe (ClickM ())) + popQueue :: JSM (Maybe (JSM ())) popQueue = state \s -> case Map.minViewWithKey s.transaction_queue of Nothing -> (Nothing, s) Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) -runTransition :: InternalEnv -> ClickM () -> IO () +runTransition :: InternalEnv -> JSM () -> IO () runTransition e c = prompt e.hte_prompt_tag $ - ($ e) . unClickM . (<* syncPoint) . trampoline $ c + ($ e) . unJSM . (<* syncPoint) . trampoline $ c -syncPoint :: ClickM () -syncPoint = ClickM \e -> void $ e.hte_flush +syncPoint :: JSM () +syncPoint = JSM \e -> void $ e.hte_flush unsafeInsertHtml :: Text -> Expr unsafeInsertHtml rawHtml = Eval @@ -166,7 +162,7 @@ unsafeInsertHtml rawHtml = Eval \}\ \})" `Apply` [PeekStack 0, Str rawHtml] -newScope :: ClickM ScopeId +newScope :: JSM ScopeId newScope = reactive newScopeOp {-# INLINE newScope #-} @@ -178,7 +174,7 @@ newScopeOp p s = (s', scope) scope = ScopeId s.next_id {-# INLINE newScopeOp #-} -newRefId :: ClickM RefId +newRefId :: JSM RefId newRefId = reactive newRefIdOp {-# INLINE newRefId #-} @@ -186,7 +182,7 @@ newRefIdOp :: ScopeId -> InternalState -> (InternalState, RefId) newRefIdOp e s = (s {next_id = s.next_id + 1}, RefId e s.next_id) {-# INLINE newRefIdOp #-} -freeScope :: Bool -> ScopeId -> ClickM () +freeScope :: Bool -> ScopeId -> JSM () freeScope unlink s = reactive (const (freeScopeOp unlink s)) >>= applyFin where @@ -208,11 +204,11 @@ freeScopeOp unlink scope s = subscriptions = List.filter chkSub s.subscriptions {-# INLINE freeScopeOp #-} -installFinalizer :: ClickM () -> ClickM () +installFinalizer :: JSM () -> JSM () installFinalizer = reactive_ . installFinalizerOp {-# INLINE installFinalizer #-} -installFinalizerOp :: ClickM () -> ScopeId -> InternalState -> InternalState +installFinalizerOp :: JSM () -> ScopeId -> InternalState -> InternalState installFinalizerOp k scope s = s {finalizers = CustomFinalizer scope k : s.finalizers} {-# INLINE installFinalizerOp #-} @@ -224,7 +220,7 @@ emptyState = InternalState [] [] Map.empty 0 -- OPERATIONS OVER DYNAMIC VARIABLES -- --------------------------------------- -readVal :: MonadIO m => DynVal a -> m a +readVal :: MonadIO m => Dynamic a -> m a readVal (ConstVal a) = pure a readVal (FromVar var) = readVar var readVal (MapVal val f) = fmap f $ readVal val @@ -236,7 +232,7 @@ readVar (SourceVar _ ref) = liftIO $ readIORef ref readVar (LensMap l var) = fmap (getConst . l Const) $ readVar var readVar (OverrideVar _ var) = readVar var -newVar :: a -> ClickM (DynVar a) +newVar :: a -> JSM (DynVar a) newVar a = do ref <- liftIO $ newIORef a let mkEv s = unsafeFromEventId $ EventId s.next_id @@ -248,7 +244,7 @@ overrideVar = OverrideVar lensMap :: Lens' s a -> DynVar s -> DynVar a lensMap = LensMap -modifyVar :: DynVar s -> (s -> (s, a)) -> ClickM a +modifyVar :: DynVar s -> (s -> (s, a)) -> JSM a modifyVar (SourceVar varId ref) f = do (newVal, a) <- liftIO $ atomicModifyIORef' ref g triggerEvent varId newVal @@ -259,16 +255,16 @@ modifyVar (OverrideVar ufn var) f = ufn (modifyVar var) f modifyVar (LensMap l var) f = modifyVar var (swap . l (swap . f)) -modifyVar_ :: DynVar s -> (s -> s) -> ClickM () +modifyVar_ :: DynVar s -> (s -> s) -> JSM () modifyVar_ var f = modifyVar var ((,()) . f) -writeVar :: DynVar s -> s -> ClickM () +writeVar :: DynVar s -> s -> JSM () writeVar var s = modifyVar_ var $ const s -forDyn :: DynVal a -> (a -> ClickM ()) -> ClickM () +forDyn :: Dynamic a -> (a -> JSM ()) -> JSM () forDyn dval action = readVal dval >>= action >> subscribe dval action -forVar :: DynVar a -> (a -> ClickM ()) -> ClickM () +forVar :: DynVar a -> (a -> JSM ()) -> JSM () forVar = forDyn . fromVar -- | Update the value inside a DynVar without notifying @@ -287,7 +283,7 @@ forVar = forDyn . fromVar -- button_ do {text "-"; on @"click" $ modifyVar_ counter pred;} -- button_ do {text "+"; on @"click" $ modifyVar_ counter succ;} -- @ -modifyVarQuiet :: DynVar s -> (s -> (s, a)) -> ClickM a +modifyVarQuiet :: DynVar s -> (s -> (s, a)) -> JSM a modifyVarQuiet (SourceVar _varId ref) f = do liftIO $ atomicModifyIORef' ref f modifyVarQuiet (OverrideVar ufn var) f = @@ -296,21 +292,21 @@ modifyVarQuiet (LensMap l var) f = modifyVarQuiet var (swap . l (swap . f)) {-# INLINEABLE modifyVarQuiet #-} -modifyVarQuiet_ :: DynVar s -> (s -> s) -> ClickM () +modifyVarQuiet_ :: DynVar s -> (s -> s) -> JSM () modifyVarQuiet_ var f = modifyVarQuiet var ((,()) . f) {-# INLINE modifyVarQuiet_ #-} -writeVarQuiet :: DynVar s -> s -> ClickM () +writeVarQuiet :: DynVar s -> s -> JSM () writeVarQuiet var = modifyVarQuiet_ var . const {-# INLINE writeVarQuiet #-} -enqueueExpr :: Expr -> ClickM () -enqueueExpr cmd = ClickM \e -> +enqueueExpr :: Expr -> JSM () +enqueueExpr cmd = JSM \e -> e.hte_send cmd {-# INLINE enqueueExpr #-} -evalExpr :: Expr -> ClickM Expr -evalExpr cmd = ClickM \e -> do +evalExpr :: Expr -> JSM Expr +evalExpr cmd = JSM \e -> do e.hte_send cmd e.hte_flush {-# INLINE evalExpr #-} diff --git a/Clickable/Property.hs b/Clickable/Property.hs index 9872ba3..a82ed89 100644 --- a/Clickable/Property.hs +++ b/Clickable/Property.hs @@ -8,7 +8,7 @@ Shortcuts for common HTML5 attributes and properties -} module Clickable.Property where -import Clickable.Html +import Clickable.HTML import Clickable.Types import Data.Text @@ -18,354 +18,354 @@ import Data.Text -- set the CSS color for an element, essentially no other CSS property -- can be applied to this element, as they will be overwritten by -- 'dynStyles'. -dynStyles :: DynVal Text -> HtmlM () +dynStyles :: Dynamic Text -> HTML () dynStyles = dynProp "style" {-# INLINE dynStyles #-} -dynValue :: DynVal Text -> HtmlM () +dynValue :: Dynamic Text -> HTML () dynValue = dynProp "value" {-# INLINE dynValue #-} -dynClass :: DynVal Text -> HtmlM () +dynClass :: Dynamic Text -> HTML () dynClass = dynProp "className" {-# INLINE dynClass #-} -dynChecked :: DynVal Bool -> HtmlM () +dynChecked :: Dynamic Bool -> HTML () dynChecked = dynProp "checked" {-# INLINE dynChecked #-} -dynDisabled :: DynVal Bool -> HtmlM () +dynDisabled :: Dynamic Bool -> HTML () dynDisabled = dynProp "disabled" {-# INLINE dynDisabled #-} -title_ :: Text -> HtmlM () +title_ :: Text -> HTML () title_ = property "title" {-# INLINE title_ #-} -selected_ :: Bool -> HtmlM () +selected_ :: Bool -> HTML () selected_ = property "selected" {-# INLINE selected_ #-} -hidden_ :: Bool -> HtmlM () +hidden_ :: Bool -> HTML () hidden_ = property "hidden" {-# INLINE hidden_ #-} -value_ :: Text -> HtmlM () +value_ :: Text -> HTML () value_ = property "value" {-# INLINE value_ #-} -defaultValue_ :: Text -> HtmlM () +defaultValue_ :: Text -> HTML () defaultValue_ = property "defaultValue" {-# INLINE defaultValue_ #-} -accept_ :: Text -> HtmlM () +accept_ :: Text -> HTML () accept_ = property "accept" {-# INLINE accept_ #-} -acceptCharset_ :: Text -> HtmlM () +acceptCharset_ :: Text -> HTML () acceptCharset_ = property "acceptCharset" {-# INLINE acceptCharset_ #-} -action_ :: Text -> HtmlM () +action_ :: Text -> HTML () action_ = property "action" {-# INLINE action_ #-} -autocomplete_ :: Bool -> HtmlM () +autocomplete_ :: Bool -> HTML () autocomplete_ b = property @Text "autocomplete" (if b then "on" else "off") {-# INLINE autocomplete_ #-} -autosave_ :: Text -> HtmlM () +autosave_ :: Text -> HTML () autosave_ = property "autosave" {-# INLINE autosave_ #-} -disabled_ :: Bool -> HtmlM () +disabled_ :: Bool -> HTML () disabled_ = property "disabled" {-# INLINE disabled_ #-} -enctype_ :: Text -> HtmlM () +enctype_ :: Text -> HTML () enctype_ = property "enctype" {-# INLINE enctype_ #-} -formation_ :: Text -> HtmlM () +formation_ :: Text -> HTML () formation_ = property "formation" {-# INLINE formation_ #-} -list_ :: Text -> HtmlM () +list_ :: Text -> HTML () list_ = property "list" {-# INLINE list_ #-} -maxlength_ :: Text -> HtmlM () +maxlength_ :: Text -> HTML () maxlength_ = property "maxlength" {-# INLINE maxlength_ #-} -minlength_ :: Text -> HtmlM () +minlength_ :: Text -> HTML () minlength_ = property "minlength" {-# INLINE minlength_ #-} -method_ :: Text -> HtmlM () +method_ :: Text -> HTML () method_ = property "method" {-# INLINE method_ #-} -multiple_ :: Bool -> HtmlM () +multiple_ :: Bool -> HTML () multiple_ = property "multiple" {-# INLINE multiple_ #-} -novalidate_ :: Bool -> HtmlM () +novalidate_ :: Bool -> HTML () novalidate_ = property "noValidate" {-# INLINE novalidate_ #-} -pattern_ :: Text -> HtmlM () +pattern_ :: Text -> HTML () pattern_ = property "pattern" {-# INLINE pattern_ #-} -readonly_ :: Bool -> HtmlM () +readonly_ :: Bool -> HTML () readonly_ = property "readOnly" {-# INLINE readonly_ #-} -required_ :: Bool -> HtmlM () +required_ :: Bool -> HTML () required_ = property "required" {-# INLINE required_ #-} -size_ :: Text -> HtmlM () +size_ :: Text -> HTML () size_ = property "size" {-# INLINE size_ #-} -forProp_ :: Text -> HtmlM () +forProp_ :: Text -> HTML () forProp_ = property "for" {-# INLINE forProp_ #-} -ref_ :: Text -> HtmlM () +ref_ :: Text -> HTML () ref_ = property "ref" {-# INLINE ref_ #-} -formProp_ :: Text -> HtmlM () +formProp_ :: Text -> HTML () formProp_ = property "form" {-# INLINE formProp_ #-} -max_ :: Text -> HtmlM () +max_ :: Text -> HTML () max_ = property "max" {-# INLINE max_ #-} -min_ :: Text -> HtmlM () +min_ :: Text -> HTML () min_ = property "min" {-# INLINE min_ #-} -step_ :: Text -> HtmlM () +step_ :: Text -> HTML () step_ = property "step" {-# INLINE step_ #-} -cols_ :: Text -> HtmlM () +cols_ :: Text -> HTML () cols_ = property "cols" {-# INLINE cols_ #-} -rows_ :: Text -> HtmlM () +rows_ :: Text -> HTML () rows_ = property "rows" {-# INLINE rows_ #-} -wrap_ :: Text -> HtmlM () +wrap_ :: Text -> HTML () wrap_ = property "wrap" {-# INLINE wrap_ #-} -target_ :: Text -> HtmlM () +target_ :: Text -> HTML () target_ = property "target" {-# INLINE target_ #-} -download_ :: Text -> HtmlM () +download_ :: Text -> HTML () download_ = property "download" {-# INLINE download_ #-} -downloadAs_ :: Text -> HtmlM () +downloadAs_ :: Text -> HTML () downloadAs_ = property "downloadAs" {-# INLINE downloadAs_ #-} -hreflang_ :: Text -> HtmlM () +hreflang_ :: Text -> HTML () hreflang_ = property "hreflang" {-# INLINE hreflang_ #-} -media_ :: Text -> HtmlM () +media_ :: Text -> HTML () media_ = property "media" {-# INLINE media_ #-} -ping_ :: Text -> HtmlM () +ping_ :: Text -> HTML () ping_ = property "ping" {-# INLINE ping_ #-} -rel_ :: Text -> HtmlM () +rel_ :: Text -> HTML () rel_ = property "rel" {-# INLINE rel_ #-} -ismap_ :: Text -> HtmlM () +ismap_ :: Text -> HTML () ismap_ = property "ismap" {-# INLINE ismap_ #-} -usemap_ :: Text -> HtmlM () +usemap_ :: Text -> HTML () usemap_ = property "usemap" {-# INLINE usemap_ #-} -shape_ :: Text -> HtmlM () +shape_ :: Text -> HTML () shape_ = property "shape" {-# INLINE shape_ #-} -coords_ :: Text -> HtmlM () +coords_ :: Text -> HTML () coords_ = property "coords" {-# INLINE coords_ #-} -src_ :: Text -> HtmlM () +src_ :: Text -> HTML () src_ = property "src" {-# INLINE src_ #-} -height_ :: Text -> HtmlM () +height_ :: Text -> HTML () height_ = property "height" {-# INLINE height_ #-} -width_ :: Text -> HtmlM () +width_ :: Text -> HTML () width_ = property "width" {-# INLINE width_ #-} -alt_ :: Text -> HtmlM () +alt_ :: Text -> HTML () alt_ = property "alt" {-# INLINE alt_ #-} -autoplay_ :: Bool -> HtmlM () +autoplay_ :: Bool -> HTML () autoplay_ = property "autoplay" {-# INLINE autoplay_ #-} -controls_ :: Bool -> HtmlM () +controls_ :: Bool -> HTML () controls_ = property "controls" {-# INLINE controls_ #-} -loop_ :: Bool -> HtmlM () +loop_ :: Bool -> HTML () loop_ = property "loop" {-# INLINE loop_ #-} -preload_ :: Text -> HtmlM () +preload_ :: Text -> HTML () preload_ = property "preload" {-# INLINE preload_ #-} -poster_ :: Text -> HtmlM () +poster_ :: Text -> HTML () poster_ = property "poster" {-# INLINE poster_ #-} -default_ :: Bool -> HtmlM () +default_ :: Bool -> HTML () default_ = property "default" {-# INLINE default_ #-} -kind_ :: Text -> HtmlM () +kind_ :: Text -> HTML () kind_ = property "kind" {-# INLINE kind_ #-} -srclang_ :: Text -> HtmlM () +srclang_ :: Text -> HTML () srclang_ = property "srclang" {-# INLINE srclang_ #-} -sandbox_ :: Text -> HtmlM () +sandbox_ :: Text -> HTML () sandbox_ = property "sandbox" {-# INLINE sandbox_ #-} -seamless_ :: Text -> HtmlM () +seamless_ :: Text -> HTML () seamless_ = property "seamless" {-# INLINE seamless_ #-} -srcdoc_ :: Text -> HtmlM () +srcdoc_ :: Text -> HTML () srcdoc_ = property "srcdoc" {-# INLINE srcdoc_ #-} -reversed_ :: Text -> HtmlM () +reversed_ :: Text -> HTML () reversed_ = property "reversed" {-# INLINE reversed_ #-} -start_ :: Text -> HtmlM () +start_ :: Text -> HTML () start_ = property "start" {-# INLINE start_ #-} -align_ :: Text -> HtmlM () +align_ :: Text -> HTML () align_ = property "align" {-# INLINE align_ #-} -colspan_ :: Text -> HtmlM () +colspan_ :: Text -> HTML () colspan_ = attribute "colspan" {-# INLINE colspan_ #-} -rowspan_ :: Text -> HtmlM () +rowspan_ :: Text -> HTML () rowspan_ = attribute "rowspan" {-# INLINE rowspan_ #-} -headers_ :: Text -> HtmlM () +headers_ :: Text -> HTML () headers_ = property "headers" {-# INLINE headers_ #-} -scope_ :: Text -> HtmlM () +scope_ :: Text -> HTML () scope_ = property "scope" {-# INLINE scope_ #-} -async_ :: Text -> HtmlM () +async_ :: Text -> HTML () async_ = property "async" {-# INLINE async_ #-} -charset_ :: Text -> HtmlM () +charset_ :: Text -> HTML () charset_ = property "charset" {-# INLINE charset_ #-} -content_ :: Text -> HtmlM () +content_ :: Text -> HTML () content_ = property "content" {-# INLINE content_ #-} -defer_ :: Text -> HtmlM () +defer_ :: Text -> HTML () defer_ = property "defer" {-# INLINE defer_ #-} -httpEquiv_ :: Text -> HtmlM () +httpEquiv_ :: Text -> HTML () httpEquiv_ = property "httpEquiv" {-# INLINE httpEquiv_ #-} -language_ :: Text -> HtmlM () +language_ :: Text -> HTML () language_ = property "language" {-# INLINE language_ #-} -scoped_ :: Text -> HtmlM () +scoped_ :: Text -> HTML () scoped_ = property "scoped" {-# INLINE scoped_ #-} -type_ :: Text -> HtmlM () +type_ :: Text -> HTML () type_ = property "type" {-# INLINE type_ #-} -name_ :: Text -> HtmlM () +name_ :: Text -> HTML () name_ = property "name" {-# INLINE name_ #-} -href_ :: Text -> HtmlM () +href_ :: Text -> HTML () href_ = property "href" {-# INLINE href_ #-} -id_ :: Text -> HtmlM () +id_ :: Text -> HTML () id_ = property "id" {-# INLINE id_ #-} -placeholder_ :: Text -> HtmlM () +placeholder_ :: Text -> HTML () placeholder_ = property "placeholder" {-# INLINE placeholder_ #-} -checked_ :: Bool -> HtmlM () +checked_ :: Bool -> HTML () checked_ = property "checked" {-# INLINE checked_ #-} -autofocus_ :: Bool -> HtmlM () +autofocus_ :: Bool -> HTML () autofocus_ = property "autofocus" {-# INLINE autofocus_ #-} -class_ :: Text -> HtmlM () +class_ :: Text -> HTML () class_ = property "className" {-# INLINE class_ #-} -data_ :: Text -> Text -> HtmlM () +data_ :: Text -> Text -> HTML () data_ k v = property ("data-" <> k) v {-# INLINE data_ #-} -role_ :: Text -> HtmlM () +role_ :: Text -> HTML () role_ = attribute "role" {-# INLINE role_ #-} -style_ :: Text -> HtmlM () +style_ :: Text -> HTML () style_ = property "style" {-# INLINE style_ #-} diff --git a/Clickable/Types.hs b/Clickable/Types.hs index 67c825b..726a48f 100644 --- a/Clickable/Types.hs +++ b/Clickable/Types.hs @@ -34,7 +34,7 @@ import GHC.List qualified as List import GHC.Types import GHC.Generics -newtype ClickM a = ClickM {unClickM :: InternalEnv -> IO a} +newtype JSM a = JSM {unJSM :: InternalEnv -> IO a} deriving ( Functor, Applicative, @@ -43,15 +43,18 @@ newtype ClickM a = ClickM {unClickM :: InternalEnv -> IO a} MonadReader InternalEnv ) via ReaderT InternalEnv IO -instance MonadState InternalState ClickM where - state f = ClickM \e -> +instance MonadState InternalState JSM where + state f = JSM \e -> atomicModifyIORef' e.hte_state (swap . f) {-# INLINE state #-} - get = ClickM \e -> readIORef e.hte_state + get = JSM \e -> readIORef e.hte_state {-# INLINE get #-} - put s = ClickM \e -> writeIORef e.hte_state s + put s = JSM \e -> writeIORef e.hte_state s {-# INLINE put #-} +class MonadJSM m where + liftJSM :: JSM a -> m a + data InternalEnv = InternalEnv { hte_send :: Expr -> IO (), hte_flush :: IO ValueExpr, @@ -64,20 +67,21 @@ data InternalEnv = InternalEnv { data InternalState = InternalState { subscriptions :: [Subscription Any], finalizers :: [Finalizer], - transaction_queue :: Map EventId (ClickM ()), + transaction_queue :: Map EventId (JSM ()), next_id :: Word32 } -newtype HtmlM a = HtmlM {unHtmlM :: Maybe RefId -> InternalEnv -> IO (a, Maybe RefId)} +newtype HTML a = HTML {unHTML :: Maybe RefId -> InternalEnv -> IO (a, Maybe RefId)} deriving ( Functor, Applicative, Monad, MonadIO - ) via StateT (Maybe RefId) ClickM + ) via StateT (Maybe RefId) JSM -liftC :: ClickM a -> HtmlM a -liftC (ClickM a) = HtmlM \s e -> (,s) <$> a e +instance MonadJSM HTML where + liftJSM (JSM a) = HTML \s e -> (,s) <$> a e + {-# INLINE liftJSM #-} data Expr where Null :: Expr @@ -177,29 +181,29 @@ data DynVar a where OverrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a LensMap :: Lens' s a -> DynVar s -> DynVar a -type UpdateFn s = forall a. (s -> (s, a)) -> ClickM a +type UpdateFn s = forall a. (s -> (s, a)) -> JSM a type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s -data DynVal a where - ConstVal :: a -> DynVal a - FromVar :: DynVar a -> DynVal a - MapVal :: DynVal a -> (a -> b) -> DynVal b - SplatVal :: DynVal (a -> b) -> DynVal a -> DynVal b - OverrideSub :: (forall b. SubscribeFn a b -> SubscribeFn a b) -> DynVal a -> DynVal a +data Dynamic a where + ConstVal :: a -> Dynamic a + FromVar :: DynVar a -> Dynamic a + MapVal :: Dynamic a -> (a -> b) -> Dynamic b + SplatVal :: Dynamic (a -> b) -> Dynamic a -> Dynamic b + OverrideSub :: (forall b. SubscribeFn a b -> SubscribeFn a b) -> Dynamic a -> Dynamic a -type SubscribeFn a b = (a -> b -> ClickM b) -> ClickM () +type SubscribeFn a b = (a -> b -> JSM b) -> JSM () -instance Functor DynVal where +instance Functor Dynamic where fmap = flip MapVal {-# INLINE fmap #-} -instance Applicative DynVal where +instance Applicative Dynamic where pure = ConstVal {-# INLINE pure #-} (<*>) = SplatVal {-# INLINE (<*>) #-} -fromVar :: DynVar a -> DynVal a +fromVar :: DynVar a -> Dynamic a fromVar = FromVar {-# INLINE fromVar #-} @@ -207,19 +211,19 @@ data Subscription a = SubscriptionSimple { ss_scope :: ScopeId, ss_event_id :: Event a, - ss_callback :: a -> ClickM () + ss_callback :: a -> JSM () } | forall b. SubscriptionAccum { sa_resource_scope :: ScopeId, sa_event_id :: Event a, - sa_callback :: a -> b -> ClickM b, + sa_callback :: a -> b -> JSM b, sa_accum_ref :: IORef b } data Finalizer = CustomFinalizer { cf_resource_scope :: ScopeId, - cf_callback :: ClickM () + cf_callback :: JSM () } | ScopeFinalizer { sf_resource_scope :: ScopeId, diff --git a/Clickable/Wasm.hs b/Clickable/Wasm.hs index 2f4a896..f1a4eda 100644 --- a/Clickable/Wasm.hs +++ b/Clickable/Wasm.hs @@ -44,7 +44,7 @@ buf :: CStringLen newInternalEnv (100 * 1024) \(ptr, len) -> clickable_eval_buffer (castPtr ptr) len -mkWasmApp :: ClickM () -> Ptr Word8 -> IO (Ptr Word8) +mkWasmApp :: JSM () -> Ptr Word8 -> IO (Ptr Word8) mkWasmApp app p | p == nullPtr = do runTransition env app return $ castPtr $ fst buf diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index 22553f8..b57b124 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -37,14 +37,15 @@ import Network.WebSockets import System.IO data ServerConfig = ServerConfig { - srv_html_template :: TemplateConfig -> Builder, - srv_docroots :: [FilePath], - srv_client :: WebSocketConn -> StartFlags -> ClickM (), - srv_connection_lost :: WebSocketConn -> IO () + cfg_html_template :: TemplateConfig -> Builder, + cfg_docroots :: [FilePath], + cfg_client :: ClientConnection -> StartFlags -> JSM (), + cfg_connection_lost :: ClientConnection -> IO (), + cfg_middleware :: Middleware } data ServerInstance = ServerInstance { - sri_connection_state :: IORef (Map ConnectionId WebSocketConn) + sri_connection_state :: IORef (Map ConnectionId ClientConnection) } data TemplateConfig = TemplateConfig { @@ -52,11 +53,11 @@ data TemplateConfig = TemplateConfig { tpc_websocket_addr :: Builder } -data WebSocketConn = WebSocketConn { +data ClientConnection = ClientConnection { connection :: Connection, internal_env :: InternalEnv, -- | Writing to the Chan sends a command to the browser to execute - command_chan :: Chan (ClickM ()), + command_chan :: Chan (JSM ()), connection_id :: ConnectionId } @@ -77,7 +78,7 @@ waiApp cfg self req respond = route $ pathInfo req [("Content-Type", "text/html")] template route ["dev.sock"] = websocketsOr defaultConnectionOptions (websocketApp cfg self) fallbackApp req respond - route _ = staticApp' cfg.srv_docroots fallbackApp req respond + route _ = staticApp' cfg.cfg_docroots fallbackApp req respond staticApp' :: [FilePath] -> Middleware staticApp' [] next = next @@ -85,7 +86,7 @@ waiApp cfg self req respond = route $ pathInfo req staticApp (defaultFileServerSettings docroot) {ss404Handler = Just (staticApp' docroots next)} - template = cfg.srv_html_template TemplateConfig { + template = cfg.cfg_html_template TemplateConfig { tpc_jsrts = jsrts, tpc_websocket_addr = "/dev.sock" } @@ -103,10 +104,10 @@ websocketApp cfg self p = acceptConn = mdo conn <- acceptRequest p newConn conn - dropConn (conn::WebSocketConn) = do + dropConn (conn::ClientConnection) = do modifyIORef' self.sri_connection_state $ Map.delete conn.connection_id - cfg.srv_connection_lost conn - loop (conn::WebSocketConn) = do + cfg.cfg_connection_lost conn + loop (conn::ClientConnection) = do raceResult <- race (try @ConnectionException (receiveData conn.connection)) (readChan conn.command_chan) @@ -121,10 +122,10 @@ websocketApp cfg self p = reader conn $ Left jsAction loop conn - reader :: WebSocketConn -> Either (ClickM ()) ClientMsg -> IO () + reader :: ClientConnection -> Either (JSM ()) ClientMsg -> IO () reader conn (Right (StartMsg flags)) = void $ runTransition conn.internal_env - $ cfg.srv_client conn flags + $ cfg.cfg_client conn flags reader conn (Right (ResumeMsg contId pload)) = prompt conn.internal_env.hte_prompt_tag do awatingThread <- atomicModifyIORef' conn.internal_env.hte_continuations $ @@ -142,7 +143,7 @@ websocketApp cfg self p = bs <- unsafePackCStringLen (castPtr ptr, len) sendDataMessage connection $ Network.WebSockets.Binary $ BSL.fromStrict bs atomicModifyIORef' self.sri_connection_state \m -> - let conn = WebSocketConn { + let conn = ClientConnection { internal_env, connection, command_chan, @@ -163,13 +164,14 @@ tryPorts set app = do tryPorts (Warp.setPort (Warp.getPort set + 1) set) app | otherwise -> throwIO e -runDefault :: ClickM () -> IO () +runDefault :: JSM () -> IO () runDefault client = runConfig ServerConfig { - srv_html_template = defaultTemplate, - srv_docroots = [], - srv_client = const $ const client, - srv_connection_lost = const $ pure () + cfg_html_template = defaultTemplate, + cfg_docroots = [], + cfg_client = const $ const client, + cfg_connection_lost = const $ pure (), + cfg_middleware = Prelude.id } runConfig :: ServerConfig -> IO () @@ -178,7 +180,7 @@ runConfig = runConfig' Warp.defaultSettings runConfig' :: Warp.Settings -> ServerConfig -> IO () runConfig' set cfg = do self <- newServer - tryPorts set $ waiApp cfg self + tryPorts set $ cfg.cfg_middleware $ waiApp cfg self defaultTemplate :: TemplateConfig -> Builder defaultTemplate cfg = diff --git a/clickable.cabal b/clickable.cabal index 5d476d0..3219fa6 100644 --- a/clickable.cabal +++ b/clickable.cabal @@ -19,7 +19,7 @@ executable clickable Clickable Clickable.Element Clickable.Float - Clickable.Html + Clickable.HTML Clickable.Internal Clickable.Property Clickable.Types diff --git a/wasm.hs b/wasm.hs new file mode 100644 index 0000000..7b91ee5 --- /dev/null +++ b/wasm.hs @@ -0,0 +1,59 @@ +{-# OPTIONS_GHC -Wno-unused-local-binds #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE RecursiveDo #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE StrictData #-} +{-# OPTIONS_GHC -Wno-unused-do-bind #-} +{-# LANGUAGE DataKinds #-} +module Main where + +import Clickable.HTML +import Clickable.Internal +import Clickable.Types +import qualified Data.Text as Text +import Clickable.Wasm +import Data.Word +import Foreign (Ptr) +import Data.IORef +import Control.Monad.Reader + +test01 :: JSM () +test01 = do + enqueueExpr $ PushStack $ Id "document" `Dot` "body" + counter <- newVar 0 + el "div" do + prop "className" (Str "container") + text "Lorem Ipsum" + el "h1" $ text "Fox jumps over a lazy dog" + el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" + el "button" do + text "Click Here" + on @"click" $ modifyVar_ counter succ + el "button" do + text "-" + on @"click" $ modifyVar_ counter pred + el "br" $ pure () + el "span" do + dynText $ fmap (Text.pack . show) $ fromVar counter + ref <- liftIO $ newIORef $ const $ pure () + el "div" do + el "button" do + text "Ask a Value" + on @"click" do + t <- asks (.hte_prompt_tag) + val <- liftIO $ control t \cont -> writeIORef ref cont + enqueueExpr $ Call (Id "console") "log" $ valueToExpr val + el "button" do + text "Fill the value" + on @"click" do + cont <- liftIO $ readIORef ref + liftIO $ cont $ pure $ Vobj [("this", Vstr "is"), ("some", Vstr "value")] + +main :: IO () +main = pure () + +foreign export ccall wasm_app :: Ptr Word8 -> IO (Ptr Word8) +wasm_app :: Ptr Word8 -> IO (Ptr Word8) +wasm_app = mkWasmApp test01 diff --git a/websocket.hs b/websocket.hs new file mode 100644 index 0000000..cd7911d --- /dev/null +++ b/websocket.hs @@ -0,0 +1,63 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecursiveDo #-} +module Main where + +import Clickable.Html +import Clickable.Internal +import Clickable.Types +import Clickable.WebSocket +import Control.Monad.IO.Class +import Control.Monad.Reader +import Data.IORef +import Network.Wai.Handler.Warp (run) +import Unsafe.Coerce (unsafeCoerce) +import qualified Data.Text as Text + +test01 :: JSM () +test01 = do + counter <- newVar @Int 0 + attachToBody do + el "div" do + prop "className" (Str "container") + text "Lorem Ipsum" + el "h1" $ text "Fox jumps over a lazy dog" + el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" + el "button" do + text "Click Here" + on @"click" $ modifyVar_ counter succ + el "button" do + text "-" + on @"click" $ modifyVar_ counter pred + el "br" $ pure () + el "span" do + dynText $ fmap (Text.pack . show) $ fromVar counter + ref <- liftIO $ newIORef $ const $ pure () + el "div" do + el "button" do + text "Ask a Value" + on @"click" do + t <- asks (.hte_prompt_tag) + val <- liftIO $ control t \cont -> writeIORef ref cont + enqueueExpr $ Call (Id "console") "log" [val] + el "button" do + text "Fill the value" + on @"click" do + cont <- liftIO $ readIORef ref + liftIO $ cont $ pure $ Obj [("this", Str "is"), ("some", Str "value")] + +main :: IO () +main = do + run 3000 $ runApp test01 + +baz :: IO Int +baz = do + let z :: Int = unsafeCoerce False + return $ z * 2 + +bar :: Int -> Int +bar dsfsd = dsfsd From 93de34fc6a1f53125393aaec9d38f9da8d71049e Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sun, 17 Nov 2024 17:04:49 +0400 Subject: [PATCH 59/64] More renaming --- Clickable/{Float.hs => Binary.hs} | 6 +- Clickable/HTML.hs | 254 +++++++++----- Clickable/Internal.hs | 311 +++++++++-------- Clickable/Property.hs | 7 +- Clickable/Types.hs | 552 ++++++++++++++---------------- Clickable/Wasm.hs | 2 +- Clickable/WebSocket.hs | 77 ++--- clickable.cabal | 2 +- jsbits/proto.ts | 24 +- wasm.hs | 6 +- websocket.hs | 4 +- 11 files changed, 675 insertions(+), 570 deletions(-) rename Clickable/{Float.hs => Binary.hs} (77%) diff --git a/Clickable/Float.hs b/Clickable/Binary.hs similarity index 77% rename from Clickable/Float.hs rename to Clickable/Binary.hs index 5fe7069..8066c15 100644 --- a/Clickable/Float.hs +++ b/Clickable/Binary.hs @@ -6,11 +6,9 @@ {-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE DerivingStrategies #-} -{-| Normal `Data.Binary.Binary` instances for floating-point numbers -replacing the impractical and unnatural encoding in the default -instances for `Float` and `Double` +{-| Override `Data.Binary.Binary` instances for floating-point numbers -} -module Clickable.Float where +module Clickable.Binary where import Data.Binary import Data.Binary.Get diff --git a/Clickable/HTML.hs b/Clickable/HTML.hs index 1eed52c..c7a4923 100644 --- a/Clickable/HTML.hs +++ b/Clickable/HTML.hs @@ -13,87 +13,89 @@ module Clickable.HTML where import Clickable.Internal import Clickable.Types -import Control.Monad.Reader import Data.Kind (Type) import Data.Text (Text) import GHC.Generics (Generic) import Unsafe.Coerce (unsafeCoerce) +import Control.Monad.Trans +import Data.IORef +import Control.Monad el :: Text -> HTML a -> HTML a el tagName child = HTML \s e -> do - e.hte_send $ PushStack $ CreateElement tagName + e.ien_command $ PushStack $ CreateElement tagName (r, _) <- child.unHTML Nothing e - e.hte_send PopIns + e.ien_command PopIns pure (r, s) {-# INLINE el #-} elns :: Text -> Text -> HTML a -> HTML a elns ns tagName child = HTML \s e -> do - e.hte_send $ PushStack $ CreateElementNS ns tagName + e.ien_command $ PushStack $ CreateElementNS ns tagName (r, _) <- child.unHTML s e - e.hte_send PopIns + e.ien_command PopIns pure (r, s) {-# INLINE elns #-} text :: Text -> HTML () text content = HTML \s e -> do - e.hte_send $ PushStack $ CreateTextNode content - e.hte_send PopIns + e.ien_command $ PushStack $ CreateText content + e.ien_command PopIns return ((), s) {-# INLINE text #-} dynText :: Dynamic Text -> HTML () dynText contentDyn = HTML \s e -> do - c <- readVal contentDyn + c <- readDyn contentDyn refId <- newRefId.unJSM e - e.hte_send $ PushStack $ CreateTextNode c - e.hte_send $ AssignRef refId (PeekStack 0) - e.hte_send PopIns + e.ien_command $ PushStack $ CreateText c + e.ien_command $ AssignRef refId (PeekStack 0) + e.ien_command PopIns let k nval = JSM \e' -> - e'.hte_send $ UpdateTextNode (Ref refId) nval + e'.ien_command $ UpdateText (Ref refId) nval (subscribe contentDyn k).unJSM e pure ((), s) {-# INLINEABLE dynText #-} -property :: ToValue val => Text -> val -> HTML () +property :: ToJSVal val => Text -> val -> HTML () property k v = HTML \s e -> do - e.hte_send $ ElementProp (PeekStack 0) k $ toValue v + e.ien_command $ ElementProp (PeekStack 0) k $ toJSVal v pure ((), s) {-# INLINE property #-} -dynProp :: ToValue val => Text -> Dynamic val -> HTML () +dynProp :: ToJSVal val => Text -> Dynamic val -> HTML () dynProp propName dynVal = HTML \s e -> do - (refId, s') <- saveStackTip.unHTML s e - initVal <- readVal dynVal - e.hte_send $ ElementProp (PeekStack 0) propName $ toValue initVal + (refId, s') <- saveStackHead.unHTML s e + initVal <- readDyn dynVal + e.ien_command $ ElementProp (PeekStack 0) propName $ toJSVal initVal let k nval = JSM \e' -> - e'.hte_send $ ElementProp (Ref refId) propName $ toValue nval + e'.ien_command $ ElementProp (Ref refId) propName $ toJSVal nval unJSM (subscribe dynVal k) e pure ((), s') {-# INLINE dynProp #-} attribute :: Text -> Text -> HTML () attribute k v = HTML \s e -> do - e.hte_send $ ElementAttr (PeekStack 0) k v + e.ien_command $ ElementAttr (PeekStack 0) k v pure ((), s) {-# INLINE attribute #-} dynAttr :: Text -> Dynamic Text -> HTML () dynAttr propName dynVal = HTML \s e -> do - (refId, s') <- saveStackTip.unHTML s e - initVal <- readVal dynVal - e.hte_send $ ElementAttr (PeekStack 0) propName initVal + (refId, s') <- saveStackHead.unHTML s e + initVal <- readDyn dynVal + e.ien_command $ ElementAttr (PeekStack 0) propName initVal let k nval = JSM \e' -> - e'.hte_send $ ElementAttr (Ref refId) propName nval + e'.ien_command $ ElementAttr (Ref refId) propName nval unJSM (subscribe dynVal k) e pure ((), s') {-# INLINE dynAttr #-} toggleClass :: Text -> Dynamic Bool -> HTML () toggleClass className dynEnable = HTML \s e -> do - (refId, s') <- saveStackTip.unHTML s e - v <- readVal dynEnable - let k enable = JSM \e' -> e'.hte_send + (refId, s') <- saveStackHead.unHTML s e + v <- readDyn dynEnable + let k enable = JSM \e' -> e'.ien_command if enable then ClassListAdd (Ref refId) className else ClassListRemove (Ref refId) className @@ -102,17 +104,17 @@ toggleClass className dynEnable = HTML \s e -> do pure ((), s') {-# INLINE toggleClass #-} -addEventListener :: FromValue a => (Event a -> Expr) -> (a -> JSM ()) -> JSM () -addEventListener connectScript k = do - e <- reactive \scope s -> - let k' = local (\e -> e {hte_scope = scope}) . k - eventId = EventId s.next_id - (s', unSubRef) = newRefIdOp scope s {next_id = s.next_id + 1} - newSub = SubscriptionSimple scope (unsafeFromEventId eventId) (mapM_ k' . fromValue . unsafeCoerce) - newFin = CustomFinalizer scope $ enqueueExpr $ Apply (Ref unSubRef) [] - s'' = s' {subscriptions = newSub : s.subscriptions, finalizers = newFin : s.finalizers} - in (s'', AssignRef unSubRef (connectScript (Event eventId))) - enqueueExpr e +addEventListener :: FromJSVal a => (Event a -> JSExp) -> (a -> JSM ()) -> JSM () +addEventListener addScript k = + reactive add >>= jsCmd where + add scope s = (s''', cmd) where + k' = localScope scope . k + eventId = EventId s.ist_id_supply + (s', unsub) = newRefIdFn scope s {ist_id_supply = s.ist_id_supply + 1} + s'' = subscribeEventFn (unsafeFromEventId eventId) + (mapM_ k' . fromJSVal . unsafeCoerce) scope s' + s''' = installFinalizerFn (jsCmd $ Apply (Ref unsub) []) scope s'' + cmd = AssignRef unsub $ addScript $ Event eventId class IsEventName eventName where type EventListenerCb eventName :: Type @@ -137,42 +139,43 @@ defaultEventListenerOptions = EventListenerOptions { stop_propagation = False } -genericEvent :: EventListenerOptions -> Text -> Expr -> Event () -> Expr -genericEvent opt eventName target (Event eventId) = - Eval - ("(function(target, trigger){\n\ - \ function listener(event){\n\ - \ " <> preventDefaultStmt <> "\n\ - \ " <> stopPropagationStmt <> "\n\ - \ trigger();\n\ - \ }\n\ - \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") `Apply` [target, Lam (TriggerEvent eventId Null)] +genericEvent :: EventListenerOptions -> Text -> JSExp -> Event () -> JSExp +genericEvent opt eventName target (Event eid) = + Eval script `Apply` [target, Lam (TriggerEvent eid Null)] where + script = + ("(function(target, trigger){\n\ + \ function listener(event){\n\ + \ " <> preventDefaultStmt <> "\n\ + \ " <> stopPropagationStmt <> "\n\ + \ trigger();\n\ + \ }\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \})") preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" -unsafeConnectEvent :: Expr -> UnsafeJavaScript -> Event a -> Expr +unsafeConnectEvent :: JSExp -> UnsafeJavaScript -> Event a -> JSExp unsafeConnectEvent target ujs (Event eid) = Eval ujs `Apply` [target, Lam (TriggerEvent eid (Arg 0))] -attachHTML :: Expr -> HTML a -> JSM a -attachHTML rootEl contents = JSM \e -> do - e.hte_send $ PushStack rootEl +attachTo :: JSExp -> HTML a -> JSM a +attachTo rootEl contents = JSM \e -> do + e.ien_command $ PushStack rootEl (r, _) <- contents.unHTML Nothing e - e.hte_send PopStack + e.ien_command PopStack pure r -attachToBody :: HTML a -> JSM a -attachToBody = attachHTML $ Id "document" `Dot` "body" +attach :: HTML a -> JSM a +attach = attachTo $ Id "document" `Dot` "body" -saveStackTip :: HTML RefId -saveStackTip = HTML \s e -> +saveStackHead :: HTML RefId +saveStackHead = HTML \s e -> case s of Nothing -> do refId <- newRefId.unJSM e - e.hte_send $ AssignRef refId $ PeekStack 0 + e.ien_command $ AssignRef refId $ PeekStack 0 return (refId, Just refId) Just saved -> pure (saved, s) @@ -199,23 +202,120 @@ data Location = Location { -- of the URL. hash :: Text } deriving stock (Show, Eq, Generic) - deriving anyclass (FromValue, ToValue) + deriving anyclass (FromJSVal, ToJSVal) -- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event -popstateEvent :: Event Location -> Expr +popstateEvent :: Event Location -> JSExp popstateEvent (Event eventId) = - Eval - "(function(target, trigger){\n\ - \ function listener(){\n\ - \ trigger({\n\ - \ protocol: location.protocol,\n\ - \ hostname: location.hostname,\n\ - \ port: location.port,\n\ - \ pathname: location.pathname,\n\ - \ search: location.search,\n\ - \ hash: location.hash\n\ - \ });\n\ - \ }\n\ - \ target.addEventListener('popstate', listener);\n\ - \ return () => target.removeEventListener('popstate', listener);\n\ - \})" `Apply` [Id "window", Lam (TriggerEvent eventId (Arg 0))] + Eval script `Apply` [Id "window", Lam (TriggerEvent eventId (Arg 0))] + where + script = + "(function(target, trigger){\n\ + \ function listener(){\n\ + \ trigger({\n\ + \ protocol: location.protocol,\n\ + \ hostname: location.hostname,\n\ + \ port: location.port,\n\ + \ pathname: location.pathname,\n\ + \ search: location.search,\n\ + \ hash: location.hash\n\ + \ });\n\ + \ }\n\ + \ target.addEventListener('popstate', listener);\n\ + \ return () => target.removeEventListener('popstate', listener);\n\ + \})" + +dyn :: Dynamic (HTML ()) -> HTML () +dyn val = do + brackets <- liftJSM insertBrackets + scope <- liftJSM newScope + initialVal <- liftJSM $ readDyn val + let + update html = do + liftJSM $ clearBrackets brackets + html + exec h = + localScope scope $ customize (Ref brackets) h + liftJSM $ exec $ update initialVal + liftJSM $ subscribe val \newVal -> do + freeScope scope + exec $ update newVal + +-- | Auxilliary datatype used in 'simpleList' implementation +data ElemEnv a = ElemEnv { + brackets :: RefId, + state_var :: DynVar a, + elem_scope :: ScopeId +} + +-- | Display dynamic collection of widgets. NOTE: changes in `DynVar +-- a` do not automatically propagate into the larger state. See +-- `OverrideVar` and todomvc example to see one way to upstream +-- changes into the larger state. +simpleList :: + forall a. Dynamic [a] -> + (Int -> DynVar a -> HTML ()) -> + HTML () +simpleList listDyn h = liftJSM do + internalStateRef <- liftIO $ newIORef ([] :: [ElemEnv a]) + brackets <- insertBrackets + let + exec brackets' scope = + localScope scope . customize (Ref brackets') + exec1 brackets' = customize (Ref brackets') + + setup :: Int -> [a] -> [ElemEnv a] -> JSM [ElemEnv a] + setup idx new existing = case (existing, new) of + ([], []) -> return [] + -- New list is longer, append new elements + ([], x:xs) -> do + e <- newElem x + exec e.brackets e.elem_scope $ h idx e.state_var + fmap (e:) $ setup (idx + 1) xs [] + -- New list is shorter, delete the elements that no longer + -- present in the new list + (r:rs, []) -> do + finalizeElems True (r:rs) + return [] + -- Update existing elements along the way + (r:rs, y:ys) -> do + writeVar r.state_var y + fmap (r:) $ setup (idx + 1) ys rs + newElem :: a -> JSM (ElemEnv a) + newElem a = do + elem_scope <- newScope + localScope elem_scope do + state_var <- newVar a + brackets' <- insertBrackets + return ElemEnv {elem_scope, state_var, brackets = brackets'} + finalizeElems :: Bool -> [ElemEnv a] -> JSM () + finalizeElems remove = mapM_ \ee -> do + when remove $ detachBrackets ee.brackets + destroyScope ee.elem_scope + updateList :: [a] -> JSM () + updateList new = do + eenvs <- liftIO $ readIORef internalStateRef + newEenvs <- setup 0 new eenvs + liftIO $ writeIORef internalStateRef newEenvs + initialVal <- readDyn listDyn + exec1 brackets $ liftJSM $ updateList initialVal + subscribe listDyn $ exec1 brackets . liftJSM . updateList + +insertBrackets :: JSM RefId +insertBrackets = do + brackets <- newRefId + jsCmd $ AssignRef brackets InsertBrackets + pure brackets + +clearBrackets :: RefId -> JSM () +clearBrackets rid = jsCmd $ ClearBrackets $ Ref rid + +detachBrackets :: RefId -> JSM () +detachBrackets rid = jsCmd $ DetachBrackets $ Ref rid + +customize :: JSExp -> HTML a -> JSM a +customize elm action = JSM \e -> do + e.ien_command $ PushStack elm + (r, _) <- action.unHTML Nothing e + e.ien_command PopStack + pure r diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index 4f507eb..d6d2934 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -24,10 +24,11 @@ import Foreign.Marshal.Alloc (mallocBytes) import Foreign.Ptr import GHC.Exts import Unsafe.Coerce +import Data.Maybe newEvent :: JSM (Event a) newEvent = state \s -> - (Event (EventId s.next_id), s {next_id = s.next_id + 1}) + (Event (EventId s.ist_id_supply), s {ist_id_supply = s.ist_id_supply + 1}) mapEvent :: (a -> b) -> Event a -> JSM (Event b) mapEvent f ea = do @@ -42,15 +43,35 @@ mapMaybeEvent f ea = do return eb subscribeEvent :: forall a. Event a -> (a -> JSM ()) -> JSM () -subscribeEvent (Event eid) k = reactive_ g where - newSub scope = SubscriptionSimple scope (coerce eid) (k . unsafeCoerce) - g scope s = s {subscriptions = newSub scope : s.subscriptions} +subscribeEvent e k = reactive_ $ subscribeEventFn e k + +subscribeEventFn :: forall a. Event a -> (a -> JSM ()) -> ScopeId -> InternalState -> InternalState +subscribeEventFn (Event eid) k scope s = + s { + ist_subscriptions = Map.alter ins eid s.ist_subscriptions + } + where + ins Nothing = Just [newSub] + ins (Just xs) = Just $ newSub : xs + newSub = Subscription scope (k . unsafeCoerce) + +subscribeOnce :: forall a. Event a -> (a -> JSM ()) -> JSM () +subscribeOnce e k = do + scope <- newScope + localScope scope do + subscribeEvent e \pload -> do + k pload + destroyScope scope subscribe :: forall a. Dynamic a -> (a -> JSM ()) -> JSM () subscribe (ConstVal _) _ = return () -subscribe (FromVar (SourceVar srcid _)) k = reactive_ g where - newSub scope = SubscriptionSimple scope (coerce srcid) (k . unsafeCoerce) - g scope s = s {subscriptions = newSub scope : s.subscriptions} +subscribe (FromVar (SourceVar event _)) k = reactive_ g where + ins sub Nothing = Just [sub] + ins sub (Just xs) = Just $ sub : xs + newSub scope = Subscription scope (k . unsafeCoerce) + g scope s = s { + ist_subscriptions = Map.alter (ins (newSub scope)) event.unEvent s.ist_subscriptions + } subscribe (FromVar (OverrideVar _ var)) k = subscribe (FromVar var) k subscribe (FromVar (LensMap l var)) k = @@ -61,60 +82,50 @@ subscribe (SplatVal fv av) k = do subscribe fv $ f src subscribe av $ g src where + ins sub Nothing = Just [sub] + ins sub (Just xs) = Just $ sub : xs h scope s = (s', coerce event) where - s' = s - { subscriptions = newsub : s.subscriptions - , next_id = s.next_id + 1 - } - event = unsafeFromEventId $ EventId s.next_id - newsub = SubscriptionSimple scope event (k . unsafeCoerce) + s' = s { + ist_subscriptions = Map.alter (ins newsub) event.unEvent s.ist_subscriptions, + ist_id_supply = s.ist_id_supply + 1 + } + event = unsafeFromEventId $ EventId s.ist_id_supply + newsub = Subscription scope (k . unsafeCoerce) f src fv' = do - av' <- readVal av + av' <- readDyn av triggerEvent src $ fv' av' g src av' = do - fv' <- readVal fv + fv' <- readDyn fv triggerEvent src $ fv' av' subscribe (OverrideSub f d) k = f subscribe' k' where k' a _ = k a subscribe' c = subscribe d \a -> c a () -triggerEventOp :: Event a -> a -> InternalState -> InternalState -triggerEventOp event pload = - defer event $ gets (.subscriptions) >>= notify - where - eventEq :: forall a b. Event a -> Event b -> Bool - eventEq (Event a) (Event b) = a == b - - notify :: [Subscription Any] -> JSM () - notify [] = return () - notify (SubscriptionSimple {ss_event_id, ss_callback} : xs) - | ss_event_id `eventEq` event = ss_callback (unsafeCoerce pload) >> notify xs - | otherwise = notify xs - notify (SubscriptionAccum {sa_event_id, sa_callback, sa_accum_ref} : xs) - | sa_event_id `eventEq` event = notifyAcc sa_callback sa_accum_ref >> notify xs - | otherwise = notify xs - notifyAcc :: forall b. (Any -> b -> JSM b) -> IORef b -> JSM () - notifyAcc k ref = do - acc <- liftIO $ readIORef ref - acc' <- k (unsafeCoerce pload) acc - liftIO $ writeIORef ref acc' - defer :: Event a -> JSM () -> InternalState -> InternalState - defer k act s = s - {transaction_queue = Map.insert k.unEvent act s.transaction_queue} - triggerEvent :: Event a -> a -> JSM () -triggerEvent e a = modify $ triggerEventOp e a +triggerEvent e a = modify $ triggerEventFn e a {-# INLINE triggerEvent #-} +triggerEventFn :: Event a -> a -> InternalState -> InternalState +triggerEventFn event pload = + defer event $ gets look >>= mapM_ notify + where + look = fromMaybe [] . Map.lookup event.unEvent . (.ist_subscriptions) + notify s = s.sub_callback (unsafeCoerce pload) + + defer :: Event a -> JSM () -> InternalState -> InternalState + defer k act s = s { + ist_transaction_queue = Map.insert k.unEvent act s.ist_transaction_queue + } + reactive :: (ScopeId -> InternalState -> (InternalState, a)) -> JSM a -reactive f = JSM \e -> atomicModifyIORef' e.hte_state $ f e.hte_scope +reactive f = JSM \e -> atomicModifyIORef' e.ien_state $ f e.ien_scope {-# INLINE reactive #-} reactive_ :: (ScopeId -> InternalState -> InternalState) -> JSM () reactive_ f = reactive \scope s -> (f scope s, ()) {-# INLINE reactive_ #-} --- | Loop until transaction_queue is empty. +-- | Loop until ist_transaction_queue is empty. -- -- Makes possible to implement @Applicative Dynamic@ without invoking -- subscribers redundantly when multiple events are fired in the same @@ -134,98 +145,121 @@ trampoline act = loop0 act where forM_ mcont loop1 popQueue :: JSM (Maybe (JSM ())) popQueue = state \s -> - case Map.minViewWithKey s.transaction_queue of + case Map.minViewWithKey s.ist_transaction_queue of Nothing -> (Nothing, s) - Just ((_, r), newQueue) -> (Just r, s {transaction_queue = newQueue}) - -runTransition :: InternalEnv -> JSM () -> IO () -runTransition e c = - prompt e.hte_prompt_tag $ - ($ e) . unJSM . (<* syncPoint) . trampoline $ c - -syncPoint :: JSM () -syncPoint = JSM \e -> void $ e.hte_flush - -unsafeInsertHtml :: Text -> Expr -unsafeInsertHtml rawHtml = Eval - "(function(parent, rawHtml){\ - \var div = document.createElement('div');\ - \div.innerHTML = rawHtml;\ - \var iter = div.childNodes[0];\ - \for (; iter; iter = div.childNodes[0]) {\ - \ div.removeChild(iter);\ - \ if (parent instanceof Comment) {\ - \ parent.parentElement.insertBefore(iter, parent);\ - \ } else{\ - \ parent.appendChild(iter);\ - \ }\ - \}\ - \})" `Apply` [PeekStack 0, Str rawHtml] + Just ((_, r), newQueue) -> (Just r, s {ist_transaction_queue = newQueue}) + +runJSM :: InternalEnv -> JSM () -> IO () +runJSM e c = prompt e.ien_prompt_tag $ + unJSM (trampoline c >> jsFlush) e + +unsafeInsertHTML :: Text -> JSExp +unsafeInsertHTML rawHtml = + Eval script `Apply` [PeekStack 0, Str rawHtml] + where + script = + "(function(parent, rawHtml){\ + \var div = document.createElement('div');\ + \div.innerHTML = rawHtml;\ + \var iter = div.childNodes[0];\ + \for (; iter; iter = div.childNodes[0]) {\ + \ div.removeChild(iter);\ + \ if (parent instanceof Comment) {\ + \ parent.parentElement.insertBefore(iter, parent);\ + \ } else{\ + \ parent.appendChild(iter);\ + \ }\ + \}\ + \})" newScope :: JSM ScopeId -newScope = reactive newScopeOp +newScope = reactive newScopeFn {-# INLINE newScope #-} -newScopeOp :: ScopeId -> InternalState -> (InternalState, ScopeId) -newScopeOp p s = (s', scope) - where - s' = s {finalizers = fns, next_id = s.next_id + 1} - fns = ScopeFinalizer p scope : s.finalizers - scope = ScopeId s.next_id -{-# INLINE newScopeOp #-} +newScopeFn :: ScopeId -> InternalState -> (InternalState, ScopeId) +newScopeFn p s = (s', new) where + new = ScopeId s.ist_id_supply + ins = Map.insert new (Resources p [] []) + link = Map.adjust (\r -> r {rsr_linked = new : r.rsr_linked}) p + s' = s { + ist_id_supply = s.ist_id_supply + 1, + ist_resources = link $ ins s.ist_resources + } +{-# INLINE newScopeFn #-} + +localScope :: ScopeId -> JSM a -> JSM a +localScope s = local (\e -> e {ien_scope = s}) +{-# INLINE localScope #-} newRefId :: JSM RefId -newRefId = reactive newRefIdOp +newRefId = reactive newRefIdFn {-# INLINE newRefId #-} -newRefIdOp :: ScopeId -> InternalState -> (InternalState, RefId) -newRefIdOp e s = (s {next_id = s.next_id + 1}, RefId e s.next_id) -{-# INLINE newRefIdOp #-} +newRefIdFn :: ScopeId -> InternalState -> (InternalState, RefId) +newRefIdFn e s = (s {ist_id_supply = s.ist_id_supply + 1}, RefId e s.ist_id_supply) +{-# INLINE newRefIdFn #-} -freeScope :: Bool -> ScopeId -> JSM () -freeScope unlink s = - reactive (const (freeScopeOp unlink s)) >>= applyFin - where - applyFin [] = enqueueExpr $ FreeScope s - applyFin (ScopeFinalizer{sf_linked_scope}:xs) = freeScope True sf_linked_scope >> applyFin xs - applyFin (CustomFinalizer{cf_callback}:xs) = cf_callback >> applyFin xs +freeScope :: ScopeId -> JSM () +freeScope s = do + mres <- state $ swap . freeScopeFn s + forM_ mres \r -> forM_ r.rsr_linked destroyScope + forM_ mres \r -> sequence_ r.rsr_finalizers {-# INLINE freeScope #-} -freeScopeOp :: Bool -> ScopeId -> InternalState -> (InternalState, [Finalizer]) -freeScopeOp unlink scope s = - (s {subscriptions, finalizers}, scopeFns) +freeScopeFn :: ScopeId -> InternalState -> (InternalState, Maybe Resources) +freeScopeFn scope s = (s', resources) + where + subs = Map.map (List.filter filterSub) s.ist_subscriptions + filterSub sub = sub.sub_scope /= scope + (resources, rsr) = Map.alterF (,Nothing) scope s.ist_resources + s' = s {ist_subscriptions = subs, ist_resources = rsr} +{-# INLINE freeScopeFn #-} + +destroyScope :: ScopeId -> JSM () +destroyScope s = do + mres <- state $ swap . destroyScopeFn s + forM_ mres \r -> forM_ r.rsr_linked destroyScope + forM_ mres \r -> sequence_ r.rsr_finalizers +{-# INLINE destroyScope #-} + +destroyScopeFn :: ScopeId -> InternalState -> (InternalState, Maybe Resources) +destroyScopeFn scope s = (s', resources) where - chkSub s' = subscriptionScope s' /= scope - chkFin True ScopeFinalizer{sf_resource_scope, sf_linked_scope} = - sf_resource_scope /= scope && sf_linked_scope /= scope - chkFin True CustomFinalizer{cf_resource_scope} = cf_resource_scope /= scope - chkFin False f = finalizerScope f /= scope - (finalizers, scopeFns) = List.partition (chkFin unlink) s.finalizers - subscriptions = List.filter chkSub s.subscriptions -{-# INLINE freeScopeOp #-} + subs = Map.map (List.filter filterSub) s.ist_subscriptions + filterSub x = x.sub_scope /= scope + remove = Map.alterF (,Nothing) scope + unlink m = case resources of + Just r -> Map.adjust adj r.rsr_parent m + Nothing -> m + adj r = r {rsr_linked = List.filter (/=scope) r.rsr_linked} + (resources, rsr) = remove s.ist_resources + s' = s {ist_subscriptions = subs, ist_resources = unlink rsr} +{-# INLINE destroyScopeFn #-} installFinalizer :: JSM () -> JSM () -installFinalizer = reactive_ . installFinalizerOp +installFinalizer = reactive_ . installFinalizerFn {-# INLINE installFinalizer #-} -installFinalizerOp :: JSM () -> ScopeId -> InternalState -> InternalState -installFinalizerOp k scope s = - s {finalizers = CustomFinalizer scope k : s.finalizers} -{-# INLINE installFinalizerOp #-} +installFinalizerFn :: JSM () -> ScopeId -> InternalState -> InternalState +installFinalizerFn k scope s = s {ist_resources = rsr} + where + rsr = Map.adjust ins scope s.ist_resources + ins r = r {rsr_finalizers = k : r.rsr_finalizers} +{-# INLINE installFinalizerFn #-} emptyState :: InternalState -emptyState = InternalState [] [] Map.empty 0 +emptyState = InternalState Map.empty Map.empty Map.empty 0 --------------------------------------- -- OPERATIONS OVER DYNAMIC VARIABLES -- --------------------------------------- -readVal :: MonadIO m => Dynamic a -> m a -readVal (ConstVal a) = pure a -readVal (FromVar var) = readVar var -readVal (MapVal val f) = fmap f $ readVal val -readVal (SplatVal f a) = liftA2 ($) (readVal f) (readVal a) -readVal (OverrideSub _ a) = readVal a +readDyn :: MonadIO m => Dynamic a -> m a +readDyn (ConstVal a) = pure a +readDyn (FromVar var) = readVar var +readDyn (MapVal val f) = fmap f $ readDyn val +readDyn (SplatVal f a) = liftA2 ($) (readDyn f) (readDyn a) +readDyn (OverrideSub _ a) = readDyn a readVar :: MonadIO m => DynVar a -> m a readVar (SourceVar _ ref) = liftIO $ readIORef ref @@ -235,8 +269,8 @@ readVar (OverrideVar _ var) = readVar var newVar :: a -> JSM (DynVar a) newVar a = do ref <- liftIO $ newIORef a - let mkEv s = unsafeFromEventId $ EventId s.next_id - state \s -> (SourceVar (mkEv s) ref, s {next_id = s.next_id + 1}) + let mkEv s = unsafeFromEventId $ EventId s.ist_id_supply + state \s -> (SourceVar (mkEv s) ref, s {ist_id_supply = s.ist_id_supply + 1}) overrideVar :: (UpdateFn a -> UpdateFn a) -> DynVar a -> DynVar a overrideVar = OverrideVar @@ -262,7 +296,7 @@ writeVar :: DynVar s -> s -> JSM () writeVar var s = modifyVar_ var $ const s forDyn :: Dynamic a -> (a -> JSM ()) -> JSM () -forDyn dval action = readVal dval >>= action >> subscribe dval action +forDyn dval action = readDyn dval >>= action >> subscribe dval action forVar :: DynVar a -> (a -> JSM ()) -> JSM () forVar = forDyn . fromVar @@ -300,23 +334,26 @@ writeVarQuiet :: DynVar s -> s -> JSM () writeVarQuiet var = modifyVarQuiet_ var . const {-# INLINE writeVarQuiet #-} -enqueueExpr :: Expr -> JSM () -enqueueExpr cmd = JSM \e -> - e.hte_send cmd -{-# INLINE enqueueExpr #-} +jsCmd :: JSExp -> JSM () +jsCmd cmd = JSM \e -> + e.ien_command cmd +{-# INLINE jsCmd #-} + +jsEval :: JSExp -> JSM JSVal +jsEval cmd = JSM \e -> do + e.ien_command cmd + e.ien_flush +{-# INLINE jsEval #-} -evalExpr :: Expr -> JSM Expr -evalExpr cmd = JSM \e -> do - e.hte_send cmd - e.hte_flush -{-# INLINE evalExpr #-} +jsFlush :: JSM () +jsFlush = JSM \e -> void $ e.ien_flush -commandBuffer :: CStringLen -> (CStringLen -> IO ()) -> IO (Expr -> IO (), IO ()) +commandBuffer :: CStringLen -> (CStringLen -> IO ()) -> IO (JSExp -> IO (), IO ()) commandBuffer (buf, bufSize) consume = do ref <- newIORef 0 return (write ref, flush ref) where - write :: IORef Int -> Expr -> IO () + write :: IORef Int -> JSExp -> IO () write ref cmd = do off <- readIORef ref let b = runBuilder $ execPut $ Binary.put cmd @@ -360,24 +397,24 @@ commandBuffer (buf, bufSize) consume = do newInternalEnv :: Int -> (CStringLen -> IO ()) -> IO (InternalEnv, CStringLen) newInternalEnv bufSize consume = do buf <- mallocBytes bufSize - hte_state <- newIORef emptyState + ien_state <- newIORef emptyState (write, flush) <- commandBuffer (buf, bufSize) consume - hte_prompt_tag <- newPromptTag - hte_continuations <- newIORef Map.empty + ien_prompt_tag <- newPromptTag + ien_continuations <- newIORef Map.empty let bufResult = (castPtr buf, bufSize) pure ( InternalEnv { - hte_send = write, - hte_flush = do - tid <- atomicModifyIORef' hte_state \s -> - (s {next_id = s.next_id + 1}, ContId s.next_id) + ien_command = write, + ien_flush = do + tid <- atomicModifyIORef' ien_state \s -> + (s {ist_id_supply = s.ist_id_supply + 1}, ContId s.ist_id_supply) write $ Resume tid flush - control hte_prompt_tag \c -> - modifyIORef' hte_continuations $ Map.insert tid c, - hte_state, - hte_scope = ScopeId 0, - hte_prompt_tag, - hte_continuations + control ien_prompt_tag \c -> + modifyIORef' ien_continuations $ Map.insert tid c, + ien_state, + ien_scope = ScopeId 0, + ien_prompt_tag, + ien_continuations }, bufResult ) diff --git a/Clickable/Property.hs b/Clickable/Property.hs index a82ed89..312a462 100644 --- a/Clickable/Property.hs +++ b/Clickable/Property.hs @@ -13,11 +13,8 @@ import Clickable.Types import Data.Text --- TODO: Real-world usage has demonstrated that 'dynStyles' not --- sufficiently composable. For instance, if 'dynStyles' is used to --- set the CSS color for an element, essentially no other CSS property --- can be applied to this element, as they will be overwritten by --- 'dynStyles'. +-- TODO: 'dynStyles' lacks composability. It overwrites all CSS +-- properties, preventing other CSS styles from being applied. dynStyles :: Dynamic Text -> HTML () dynStyles = dynProp "style" {-# INLINE dynStyles #-} diff --git a/Clickable/Types.hs b/Clickable/Types.hs index 726a48f..ead9e25 100644 --- a/Clickable/Types.hs +++ b/Clickable/Types.hs @@ -13,13 +13,12 @@ {-# OPTIONS_GHC -Wall #-} module Clickable.Types where -import Clickable.Float +import Clickable.Binary import Control.Monad.Reader import Control.Monad.State.Strict import Data.Binary ( Binary ) import Data.Bool (bool) import Data.ByteString (ByteString) -import Data.ByteString.Builder ( Builder ) import Data.IORef import Data.Int import Data.Map (Map) @@ -44,31 +43,41 @@ newtype JSM a = JSM {unJSM :: InternalEnv -> IO a} ) via ReaderT InternalEnv IO instance MonadState InternalState JSM where - state f = JSM \e -> - atomicModifyIORef' e.hte_state (swap . f) + state f = JSM \e -> atomicModifyIORef' e.ien_state (swap . f) {-# INLINE state #-} - get = JSM \e -> readIORef e.hte_state + get = JSM \e -> readIORef e.ien_state {-# INLINE get #-} - put s = JSM \e -> writeIORef e.hte_state s + put s = JSM \e -> writeIORef e.ien_state s {-# INLINE put #-} class MonadJSM m where liftJSM :: JSM a -> m a data InternalEnv = InternalEnv { - hte_send :: Expr -> IO (), - hte_flush :: IO ValueExpr, - hte_state :: IORef InternalState, - hte_scope :: ScopeId, - hte_prompt_tag :: PromptTag (), - hte_continuations :: IORef (Map ContId (IO ValueExpr -> IO ())) + ien_command :: JSExp -> IO (), + ien_flush :: IO JSVal, + ien_state :: IORef InternalState, + ien_scope :: ScopeId, + ien_prompt_tag :: PromptTag (), + ien_continuations :: IORef (Map ContId (IO JSVal -> IO ())) } data InternalState = InternalState { - subscriptions :: [Subscription Any], - finalizers :: [Finalizer], - transaction_queue :: Map EventId (JSM ()), - next_id :: Word32 + ist_subscriptions :: Map EventId [Subscription Any], + ist_resources :: Map ScopeId Resources, + ist_transaction_queue :: Map EventId (JSM ()), + ist_id_supply :: Word32 +} + +data Subscription a = Subscription { + sub_scope :: ScopeId, + sub_callback :: a -> JSM () +} + +data Resources = Resources { + rsr_parent :: ScopeId, + rsr_linked :: [ScopeId], + rsr_finalizers :: [JSM ()] } newtype HTML a = HTML {unHTML :: Maybe RefId -> InternalEnv -> IO (a, Maybe RefId)} @@ -83,79 +92,84 @@ instance MonadJSM HTML where liftJSM (JSM a) = HTML \s e -> (,s) <$> a e {-# INLINE liftJSM #-} -data Expr where - Null :: Expr - Bool :: Word8 -> Expr - I8 :: Int8 -> Expr - I16 :: Int16 -> Expr - I32 :: Int32 -> Expr - I64 :: Int64 -> Expr - U8 :: Word8 -> Expr - U16 :: Word16 -> Expr - U32 :: Word32 -> Expr - U64 :: Word64 -> Expr - F32 :: Float32 -> Expr - F64 :: Float64 -> Expr - Str :: Text -> Expr - Arr :: [Expr] -> Expr - Obj :: [(Text, Expr)] -> Expr -- ^ JavaScript object - U8Arr :: ByteString -> Expr - - Dot :: Expr -> Text -> Expr - SetProp :: Expr -> Text -> Expr -> Expr - Ix :: Expr -> Word32 -> Expr - Id :: Text -> Expr - - Lam :: Expr -> Expr - Arg :: Word8 -> Expr - Apply :: Expr -> [Expr] -> Expr - Call :: Expr -> Text -> [Expr] -> Expr - - AssignRef :: RefId -> Expr -> Expr - FreeRef :: RefId -> Expr - Ref :: RefId -> Expr - FreeScope :: ScopeId -> Expr - - PeekStack :: Word8 -> Expr - PushStack :: Expr -> Expr - PopStack :: Expr - - PopIns :: Expr - ElementProp :: Expr -> Text -> Expr -> Expr - ElementAttr :: Expr -> Text -> Text -> Expr - ClassListAdd :: Expr -> Text -> Expr - ClassListRemove :: Expr -> Text -> Expr - InsertBrackets :: Expr - ClearBrackets :: Expr -> Expr - DropBrackets :: Expr -> Expr - - CreateElement :: Text -> Expr - CreateElementNS :: Text -> Text -> Expr - CreateTextNode :: Text -> Expr - UpdateTextNode :: Expr -> Text -> Expr - - Eval :: UnsafeJavaScript -> Expr - TriggerEvent :: EventId -> Expr -> Expr - Resume :: ContId -> Expr - - deriving stock Generic +data JSExp where + Null :: JSExp + Bool :: Word8 -> JSExp + I8 :: Int8 -> JSExp + I16 :: Int16 -> JSExp + I32 :: Int32 -> JSExp + I64 :: Int64 -> JSExp + U8 :: Word8 -> JSExp + U16 :: Word16 -> JSExp + U32 :: Word32 -> JSExp + U64 :: Word64 -> JSExp + F32 :: Float32 -> JSExp + F64 :: Float64 -> JSExp + Str :: Text -> JSExp + Arr :: [JSExp] -> JSExp + Obj :: [(Text, JSExp)] -> JSExp -- ^ JavaScript object + U8Arr :: ByteString -> JSExp + + Dot :: JSExp -> Text -> JSExp + SetProp :: JSExp -> Text -> JSExp -> JSExp + Ix :: JSExp -> Word32 -> JSExp + Id :: Text -> JSExp + + Lam :: JSExp -> JSExp + Arg :: Word8 -> JSExp + Apply :: JSExp -> [JSExp] -> JSExp + Call :: JSExp -> Text -> [JSExp] -> JSExp + + AssignRef :: RefId -> JSExp -> JSExp + FreeRef :: RefId -> JSExp + Ref :: RefId -> JSExp + FreeScope :: ScopeId -> JSExp + + PeekStack :: Word8 -> JSExp + PushStack :: JSExp -> JSExp + PopStack :: JSExp + + PopIns :: JSExp + ElementProp :: JSExp -> Text -> JSExp -> JSExp + ElementAttr :: JSExp -> Text -> Text -> JSExp + ClassListAdd :: JSExp -> Text -> JSExp + ClassListRemove :: JSExp -> Text -> JSExp + InsertBrackets :: JSExp + ClearBrackets :: JSExp -> JSExp + DetachBrackets :: JSExp -> JSExp + + CreateElement :: Text -> JSExp + CreateElementNS :: Text -> Text -> JSExp + CreateText :: Text -> JSExp + UpdateText :: JSExp -> Text -> JSExp + + Eval :: UnsafeJavaScript -> JSExp + TriggerEvent :: EventId -> JSExp -> JSExp + Resume :: ContId -> JSExp + + deriving stock (Generic, Show) deriving anyclass Binary data ClientMsg where StartMsg :: StartFlags -> ClientMsg - EventMsg :: EventId -> Expr -> ClientMsg - ResumeMsg :: ContId -> Expr -> ClientMsg + EventMsg :: EventId -> JSExp -> ClientMsg + ResumeMsg :: ContId -> JSExp -> ClientMsg deriving stock Generic deriving anyclass Binary -newtype StartFlags = StartFlags {unStartFlags :: Expr} +-- | JavaScript value, result of evaluating an 'JSExp'. Should only +-- contain constructors up to and including 'U8Arr'. I opted for type +-- alias rather than a datatype for easier conversion. +type JSVal = JSExp + +newtype StartFlags = StartFlags {unStartFlags :: JSVal} deriving newtype Binary newtype ScopeId = ScopeId {unScopeId :: Word32} - deriving newtype (Binary, Eq) + deriving newtype (Binary, Eq, Ord, Show) data RefId = RefId ScopeId Word32 - deriving stock (Generic) + deriving stock (Eq, Show, Generic) deriving anyclass (Binary) newtype EventId = EventId {unEventId :: Word32} @@ -207,247 +221,209 @@ fromVar :: DynVar a -> Dynamic a fromVar = FromVar {-# INLINE fromVar #-} -data Subscription a - = SubscriptionSimple { - ss_scope :: ScopeId, - ss_event_id :: Event a, - ss_callback :: a -> JSM () - } - | forall b. SubscriptionAccum { - sa_resource_scope :: ScopeId, - sa_event_id :: Event a, - sa_callback :: a -> b -> JSM b, - sa_accum_ref :: IORef b - } - -data Finalizer - = CustomFinalizer { - cf_resource_scope :: ScopeId, - cf_callback :: JSM () - } - | ScopeFinalizer { - sf_resource_scope :: ScopeId, - sf_linked_scope :: ScopeId - } +class ToJSVal a where + toJSVal :: a -> JSVal + default toJSVal :: (Generic a, GToJSVal (Rep a)) => a -> JSVal + toJSVal = gToJSVal . G.from -finalizerScope :: Finalizer -> ScopeId -finalizerScope CustomFinalizer{cf_resource_scope} = cf_resource_scope -finalizerScope ScopeFinalizer{sf_resource_scope} = sf_resource_scope +instance (Generic a, GToJSVal (Rep a)) => ToJSVal (Generically a) where + toJSVal = gToJSVal . G.from . (\(Generically x) -> x) -subscriptionScope :: Subscription a -> ScopeId -subscriptionScope SubscriptionSimple{ss_scope} = ss_scope -subscriptionScope SubscriptionAccum{sa_resource_scope} = sa_resource_scope +instance ToJSVal JSVal where toJSVal = Prelude.id --- | JavaScript value, result of evaluating an 'Expr'. Should only --- contain constructors up to and including 'U8Arr'. I chose to use --- type alias rather than a data type for easier conversion. -type ValueExpr = Expr +instance ToJSVal Bool where toJSVal = Bool . bool 0 1 -class ToValue a where - toValue :: a -> ValueExpr - default toValue :: (Generic a, GToValue (Rep a)) => a -> ValueExpr - toValue = gToValue . G.from +instance ToJSVal Int8 where toJSVal = I8 +instance ToJSVal Int16 where toJSVal = I16 +instance ToJSVal Int32 where toJSVal = I32 +instance ToJSVal Int64 where toJSVal = I64 -instance (Generic a, GToValue (Rep a)) => ToValue (Generically a) where - toValue = gToValue . G.from . (\(Generically x) -> x) +instance ToJSVal Word8 where toJSVal = U8 +instance ToJSVal Word16 where toJSVal = U16 +instance ToJSVal Word32 where toJSVal = U32 +instance ToJSVal Word64 where toJSVal = U64 -instance ToValue ValueExpr where toValue = Prelude.id +instance ToJSVal Float where toJSVal = F32 . Float32 +instance ToJSVal Double where toJSVal = F64 . Float64 -instance ToValue Bool where toValue = Bool . bool 0 1 +instance ToJSVal Int where toJSVal = I64 . fromIntegral +instance ToJSVal Word where toJSVal = U64 . fromIntegral -instance ToValue Int8 where toValue = I8 -instance ToValue Int16 where toValue = I16 -instance ToValue Int32 where toValue = I32 -instance ToValue Int64 where toValue = I64 +instance ToJSVal Char where + toJSVal c = Str $ Text.cons c Text.empty -instance ToValue Word8 where toValue = U8 -instance ToValue Word16 where toValue = U16 -instance ToValue Word32 where toValue = U32 -instance ToValue Word64 where toValue = U64 +instance ToJSVal Text where toJSVal = Str -instance ToValue Float where toValue = F32 . Float32 -instance ToValue Double where toValue = F64 . Float64 +instance ToJSVal ByteString where toJSVal = U8Arr -instance ToValue Int where toValue = I64 . fromIntegral -instance ToValue Word where toValue = U64 . fromIntegral +instance ToJSVal () where toJSVal _ = Null -instance ToValue Char where - toValue c = Str $ Text.cons c Text.empty +instance ToJSVal a => ToJSVal [a] where toJSVal = Arr . fmap toJSVal -instance ToValue Text where toValue = Str +instance ToJSVal a => ToJSVal (Maybe a) where toJSVal = maybe Null toJSVal -instance ToValue ByteString where toValue = U8Arr +instance (ToJSVal a, ToJSVal b) => ToJSVal (a, b) where + toJSVal (a, b) = toJSVal [toJSVal a, toJSVal b] -instance ToValue () where toValue _ = Null - -instance ToValue a => ToValue [a] where toValue = Arr . fmap toValue - -instance ToValue a => ToValue (Maybe a) where toValue = maybe Null toValue - -instance (ToValue a, ToValue b) => ToValue (a, b) where - toValue (a, b) = toValue [toValue a, toValue b] - -instance (ToValue a, ToValue b, ToValue c) => ToValue (a, b, c) where - toValue (a, b, c) = toValue [toValue a, toValue b, toValue c] +instance (ToJSVal a, ToJSVal b, ToJSVal c) => ToJSVal (a, b, c) where + toJSVal (a, b, c) = toJSVal [toJSVal a, toJSVal b, toJSVal c] -------------------------------------------------------------------------------- -class FromValue a where - fromValue :: ValueExpr -> Maybe a - default fromValue :: (Generic a, GFromValue (Rep a)) => ValueExpr -> Maybe a - fromValue = fmap G.to . gFromValue - -instance (Generic a, GFromValue (Rep a)) => FromValue (Generically a) where - fromValue = fmap (Generically . G.to) . gFromValue - -instance FromValue ValueExpr where fromValue = pure - -instance FromValue Bool where - fromValue (Bool 0) = Just False - fromValue (Bool _) = Just True - fromValue _ = Nothing - -instance FromValue Int8 where - fromValue (I8 j) = Just j - fromValue _ = Nothing - -instance FromValue Int16 where - fromValue (I16 j) = Just j - fromValue _ = Nothing - -instance FromValue Int32 where - fromValue = \case - I32 j -> Just j - F64 j -> Just $ floor j.unFloat64 - _ -> Nothing - -instance FromValue Int64 where - fromValue (I64 j) = Just j - fromValue _ = Nothing - -instance FromValue Word8 where - fromValue (U8 j) = Just j - fromValue _ = Nothing - -instance FromValue Word16 where - fromValue (U16 j) = Just j - fromValue _ = Nothing - -instance FromValue Word32 where - fromValue (U32 j) = Just j - fromValue _ = Nothing - -instance FromValue Word64 where - fromValue (U64 j) = Just j - fromValue _ = Nothing - -instance FromValue Float where - fromValue (F32 j) = Just j.unFloat32 - fromValue _ = Nothing - -instance FromValue Double where - fromValue = \case - I32 j -> Just $ fromIntegral j - F64 (Float64 j) -> Just j - _ -> Nothing - -instance FromValue Int where - fromValue (I8 j) = Just $ fromIntegral j - fromValue (I16 j) = Just $ fromIntegral j - fromValue (I32 j) = Just $ fromIntegral j - fromValue (I64 j) = Just $ fromIntegral j - fromValue (U8 j) = Just $ fromIntegral j - fromValue (U16 j) = Just $ fromIntegral j - fromValue (U32 j) = Just $ fromIntegral j - fromValue (U64 j) = Just $ fromIntegral j - fromValue _ = Nothing - -instance FromValue Word where - fromValue (I8 j) = Just $ fromIntegral j - fromValue (I16 j) = Just $ fromIntegral j - fromValue (I32 j) = Just $ fromIntegral j - fromValue (I64 j) = Just $ fromIntegral j - fromValue (U8 j) = Just $ fromIntegral j - fromValue (U16 j) = Just $ fromIntegral j - fromValue (U32 j) = Just $ fromIntegral j - fromValue (U64 j) = Just $ fromIntegral j - fromValue _ = Nothing - -instance FromValue Char where - fromValue = \case +class FromJSVal a where + fromJSVal :: JSVal -> Maybe a + default fromJSVal :: (Generic a, GFromJSVal (Rep a)) => JSVal -> Maybe a + fromJSVal = fmap G.to . gFromJSVal + +instance (Generic a, GFromJSVal (Rep a)) => FromJSVal (Generically a) where + fromJSVal = fmap (Generically . G.to) . gFromJSVal + +instance FromJSVal JSVal where fromJSVal = pure + +instance FromJSVal Bool where + fromJSVal (Bool 0) = Just False + fromJSVal (Bool _) = Just True + fromJSVal _ = Nothing + +instance FromJSVal Int8 where + fromJSVal (I8 j) = Just j + fromJSVal _ = Nothing + +instance FromJSVal Int16 where + fromJSVal (I16 j) = Just j + fromJSVal _ = Nothing + +instance FromJSVal Int32 where + fromJSVal (I32 j) = Just j + fromJSVal (F64 j) = Just $ floor j.unFloat64 + fromJSVal _ = Nothing + +instance FromJSVal Int64 where + fromJSVal (I64 j) = Just j + fromJSVal _ = Nothing + +instance FromJSVal Word8 where + fromJSVal (U8 j) = Just j + fromJSVal _ = Nothing + +instance FromJSVal Word16 where + fromJSVal (U16 j) = Just j + fromJSVal _ = Nothing + +instance FromJSVal Word32 where + fromJSVal (U32 j) = Just j + fromJSVal _ = Nothing + +instance FromJSVal Word64 where + fromJSVal (U64 j) = Just j + fromJSVal _ = Nothing + +instance FromJSVal Float where + fromJSVal (F32 j) = Just j.unFloat32 + fromJSVal _ = Nothing + +instance FromJSVal Double where + fromJSVal (I32 j) = Just $ fromIntegral j + fromJSVal (F64 (Float64 j)) = Just j + fromJSVal _ = Nothing + +instance FromJSVal Int where + fromJSVal (I8 j) = Just $ fromIntegral j + fromJSVal (I16 j) = Just $ fromIntegral j + fromJSVal (I32 j) = Just $ fromIntegral j + fromJSVal (I64 j) = Just $ fromIntegral j + fromJSVal (U8 j) = Just $ fromIntegral j + fromJSVal (U16 j) = Just $ fromIntegral j + fromJSVal (U32 j) = Just $ fromIntegral j + fromJSVal (U64 j) = Just $ fromIntegral j + fromJSVal _ = Nothing + +instance FromJSVal Word where + fromJSVal (I8 j) = Just $ fromIntegral j + fromJSVal (I16 j) = Just $ fromIntegral j + fromJSVal (I32 j) = Just $ fromIntegral j + fromJSVal (I64 j) = Just $ fromIntegral j + fromJSVal (U8 j) = Just $ fromIntegral j + fromJSVal (U16 j) = Just $ fromIntegral j + fromJSVal (U32 j) = Just $ fromIntegral j + fromJSVal (U64 j) = Just $ fromIntegral j + fromJSVal _ = Nothing + +instance FromJSVal Char where + fromJSVal = \case Str a | Just (c, _) <- Text.uncons a -> Just c - | otherwise -> Nothing + | otherwise -> Nothing _ -> Nothing -instance FromValue Text where - fromValue = \case Str a -> Just a; _ -> Nothing +instance FromJSVal Text where + fromJSVal = \case Str a -> Just a; _ -> Nothing -instance FromValue ByteString where - fromValue = \case U8Arr a -> Just a; _ -> Nothing +instance FromJSVal ByteString where + fromJSVal = \case U8Arr a -> Just a; _ -> Nothing -instance FromValue () where - fromValue = \case Null -> Just (); _ -> Nothing +instance FromJSVal () where + fromJSVal = \case Null -> Just (); _ -> Nothing -instance FromValue a => FromValue [a] where - fromValue = \case - Arr xs -> Just (mapMaybe fromValue xs) +instance FromJSVal a => FromJSVal [a] where + fromJSVal = \case + Arr xs -> Just (mapMaybe fromJSVal xs) _ -> Nothing -instance FromValue a => FromValue (Maybe a) where - fromValue = fmap Just . fromValue @a +instance FromJSVal a => FromJSVal (Maybe a) where + fromJSVal = fmap Just . fromJSVal @a -instance (FromValue a, FromValue b) => FromValue (a, b) where - fromValue j = fromValue j >>= \case - Just (a:b:_) -> (,) <$> fromValue a <*> fromValue b +instance (FromJSVal a, FromJSVal b) => FromJSVal (a, b) where + fromJSVal j = fromJSVal j >>= \case + Just (a:b:_) -> (,) <$> fromJSVal a <*> fromJSVal b _ -> Nothing -instance (FromValue a, FromValue b, FromValue c) => FromValue (a, b, c) where - fromValue j = fromValue j >>= \case - Just (a:b:c:_) -> (,,) <$> fromValue a <*> fromValue b <*> fromValue c +instance (FromJSVal a, FromJSVal b, FromJSVal c) => FromJSVal (a, b, c) where + fromJSVal j = fromJSVal j >>= \case + Just (a:b:c:_) -> (,,) <$> fromJSVal a <*> fromJSVal b <*> fromJSVal c _ -> Nothing -------------------------------------------------------------------------------- -class GFromValue (f :: Type -> Type) where - gFromValue :: ValueExpr -> Maybe (f a) +class GFromJSVal (f :: Type -> Type) where + gFromJSVal :: JSVal -> Maybe (f a) -instance GFromValue f => GFromValue (M1 m c f) where - gFromValue = fmap M1 . gFromValue @f +instance GFromJSVal f => GFromJSVal (M1 m c f) where + gFromJSVal = fmap M1 . gFromJSVal @f -instance GFromValue U1 where - gFromValue _ = Just U1 +instance GFromJSVal U1 where + gFromJSVal _ = Just U1 -instance GFromJSObject (x :*: y) => GFromValue (x :*: y) where - gFromValue (Obj kvs) = gFromJSObject kvs - gFromValue _ = Nothing +instance GFromJSObject (x :*: y) => GFromJSVal (x :*: y) where + gFromJSVal (Obj kvs) = gFromJSObject kvs + gFromJSVal _ = Nothing -instance GFromJSSum (x :+: y) => GFromValue (x :+: y) where - gFromValue (Arr [Str tag, v]) = gFromJSSum tag v - gFromValue _ = Nothing +instance GFromJSSum (x :+: y) => GFromJSVal (x :+: y) where + gFromJSVal (Arr [Str tag, v]) = gFromJSSum tag v + gFromJSVal _ = Nothing -instance {-# OVERLAPPING #-} FromValue a => GFromValue (S1 s (Rec0 a)) where - gFromValue = fmap (M1 . K1) . fromValue @a +instance {-# OVERLAPPING #-} FromJSVal a => GFromJSVal (S1 s (Rec0 a)) where + gFromJSVal = fmap (M1 . K1) . fromJSVal @a -------------------------------------------------------------------------------- -class GToValue (f :: Type -> Type) where - gToValue :: f x -> ValueExpr +class GToJSVal (f :: Type -> Type) where + gToJSVal :: f x -> JSVal -instance GToValue f => GToValue (M1 m c f) where - gToValue (M1 f) = gToValue f +instance GToJSVal f => GToJSVal (M1 m c f) where + gToJSVal (M1 f) = gToJSVal f -instance GToValue U1 where - gToValue _ = Null +instance GToJSVal U1 where + gToJSVal _ = Null -instance GToJSObject (x :*: y) => GToValue (x :*: y) where - gToValue (x :*: y) = Obj $ gToJSObject (x :*: y) +instance GToJSObject (x :*: y) => GToJSVal (x :*: y) where + gToJSVal (x :*: y) = Obj $ gToJSObject (x :*: y) -instance GToJSSum (x :+: y) => GToValue (x :+: y) where - gToValue = gToJSSum +instance GToJSSum (x :+: y) => GToJSVal (x :+: y) where + gToJSVal = gToJSSum -instance {-# OVERLAPPING #-} (ToValue a) => GToValue (S1 s (Rec0 a)) where - gToValue (M1 (K1 a)) = toValue a +instance {-# OVERLAPPING #-} (ToJSVal a) => GToJSVal (S1 s (Rec0 a)) where + gToJSVal (M1 (K1 a)) = toJSVal a -------------------------------------------------------------------------------- class GToJSObject (f :: Type -> Type) where - gToJSObject :: f x -> [(Text, ValueExpr)] + gToJSObject :: f x -> [(Text, JSVal)] instance (GToJSObject x, GToJSObject y) => GToJSObject (x :*: y) where gToJSObject (x :*: y) = gToJSObject x <> gToJSObject y @@ -455,14 +431,14 @@ instance (GToJSObject x, GToJSObject y) => GToJSObject (x :*: y) where instance (GToJSObject f) => GToJSObject (M1 m c f) where gToJSObject (M1 a) = gToJSObject a -instance {-# OVERLAPPING #-} (ToValue a, Selector s) => GToJSObject (S1 s (Rec0 a)) where - gToJSObject (M1 (K1 a)) = [(key, toValue a)] +instance {-# OVERLAPPING #-} (ToJSVal a, Selector s) => GToJSObject (S1 s (Rec0 a)) where + gToJSObject (M1 (K1 a)) = [(key, toJSVal a)] where key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) -------------------------------------------------------------------------------- class GFromJSObject (f :: Type -> Type) where - gFromJSObject :: [(Text, ValueExpr)] -> Maybe (f x) + gFromJSObject :: [(Text, JSVal)] -> Maybe (f x) instance (GFromJSObject x, GFromJSObject y) => GFromJSObject (x :*: y) where gFromJSObject kvs = liftA2 (:*:) (gFromJSObject kvs) (gFromJSObject kvs) @@ -470,14 +446,14 @@ instance (GFromJSObject x, GFromJSObject y) => GFromJSObject (x :*: y) where instance (GFromJSObject f) => GFromJSObject (M1 m c f) where gFromJSObject = fmap M1 . gFromJSObject -instance {-# OVERLAPPING #-} (FromValue a, Selector s) => GFromJSObject (S1 s (Rec0 a)) where - gFromJSObject kvs = List.lookup key kvs >>= fmap (M1 . K1) . fromValue +instance {-# OVERLAPPING #-} (FromJSVal a, Selector s) => GFromJSObject (S1 s (Rec0 a)) where + gFromJSObject kvs = List.lookup key kvs >>= fmap (M1 . K1) . fromJSVal where key = Text.pack $ selName (undefined :: M1 S s (Rec0 a) x) -------------------------------------------------------------------------------- class GFromJSSum (f :: Type -> Type) where - gFromJSSum :: Text -> ValueExpr -> Maybe (f x) + gFromJSSum :: Text -> JSVal -> Maybe (f x) instance (GFromJSSum x, GFromJSSum y) => GFromJSSum (x :+: y) where gFromJSSum tag v = case gFromJSSum @x tag v of @@ -486,12 +462,12 @@ instance (GFromJSSum x, GFromJSSum y) => GFromJSSum (x :+: y) where Just b -> Just $ R1 b Nothing -> Nothing -instance FromValue a => GFromValue (K1 R a) where - gFromValue v = fmap K1 $ fromValue @a v +instance FromJSVal a => GFromJSVal (K1 R a) where + gFromJSVal v = fmap K1 $ fromJSVal @a v -instance {-# OVERLAPPING #-} (GFromValue (f a), Constructor s) => GFromJSSum (C1 s (f a)) where +instance {-# OVERLAPPING #-} (GFromJSVal (f a), Constructor s) => GFromJSSum (C1 s (f a)) where gFromJSSum tag v = - if tag == key then fmap M1 $ gFromValue v else Nothing + if tag == key then fmap M1 $ gFromJSVal v else Nothing where key = Text.pack $ conName (undefined :: C1 s (f a) x) @@ -503,18 +479,18 @@ instance {-# OVERLAPPING #-} Constructor s => GFromJSSum (C1 s U1) where -------------------------------------------------------------------------------- class GToJSSum (f :: Type -> Type) where - gToJSSum :: f x -> ValueExpr + gToJSSum :: f x -> JSVal instance (GToJSSum x, GToJSSum y) => GToJSSum (x :+: y) where gToJSSum (L1 v) = gToJSSum v gToJSSum (R1 v) = gToJSSum v -instance ToValue a => GToValue (K1 R a) where - gToValue (K1 v) = toValue @a v +instance ToJSVal a => GToJSVal (K1 R a) where + gToJSVal (K1 v) = toJSVal @a v -instance {-# OVERLAPPING #-} (GToValue (f a), Constructor s) => GToJSSum (C1 s (f a)) where +instance {-# OVERLAPPING #-} (GToJSVal (f a), Constructor s) => GToJSSum (C1 s (f a)) where gToJSSum (M1 v) = - Arr [Str key, gToValue v] + Arr [Str key, gToJSVal v] where key = Text.pack $ conName (undefined :: C1 s (f a) x) @@ -548,8 +524,6 @@ control (PromptTag t) f = IO (control0# t g) data PromptTag a = PromptTag {unPromptTag :: PromptTag# a} -data SomeTag = forall a. SomeTag (PromptTag a) - newPromptTag :: forall a. IO (PromptTag a) newPromptTag = IO \s -> let !(# s', t #) = newPromptTag# @a s in (# s', PromptTag t #) diff --git a/Clickable/Wasm.hs b/Clickable/Wasm.hs index f1a4eda..d5303f3 100644 --- a/Clickable/Wasm.hs +++ b/Clickable/Wasm.hs @@ -34,7 +34,7 @@ foreign import ccall safe env :: InternalEnv {-# NOINLINE env #-} -continuations :: IORef (Map Word32 (IO ValueExpr -> IO ())) +continuations :: IORef (Map Word32 (IO JSVal -> IO ())) {-# NOINLINE continuations #-} buf :: CStringLen diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index b57b124..e823c03 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -37,15 +37,15 @@ import Network.WebSockets import System.IO data ServerConfig = ServerConfig { - cfg_html_template :: TemplateConfig -> Builder, + cfg_template :: TemplateConfig -> Builder, cfg_docroots :: [FilePath], - cfg_client :: ClientConnection -> StartFlags -> JSM (), - cfg_connection_lost :: ClientConnection -> IO (), + cfg_client :: DevServerConn -> StartFlags -> JSM (), + cfg_connection_lost :: DevServerConn -> IO (), cfg_middleware :: Middleware } data ServerInstance = ServerInstance { - sri_connection_state :: IORef (Map ConnectionId ClientConnection) + sri_dsc_websocket_state :: IORef (Map ConnectionId DevServerConn) } data TemplateConfig = TemplateConfig { @@ -53,12 +53,12 @@ data TemplateConfig = TemplateConfig { tpc_websocket_addr :: Builder } -data ClientConnection = ClientConnection { - connection :: Connection, - internal_env :: InternalEnv, +data DevServerConn = DevServerConn { + dsc_websocket :: Connection, + dsc_internal_env :: InternalEnv, -- | Writing to the Chan sends a command to the browser to execute - command_chan :: Chan (JSM ()), - connection_id :: ConnectionId + dsc_command_chan :: Chan (JSM ()), + dsc_connection_id :: ConnectionId } newtype ConnectionId = ConnectionId {unConnectionId :: Int} @@ -66,9 +66,9 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} newServer :: IO ServerInstance newServer = do - sri_connection_state <- newIORef Map.empty + sri_dsc_websocket_state <- newIORef Map.empty pure ServerInstance { - sri_connection_state + sri_dsc_websocket_state } waiApp :: ServerConfig -> ServerInstance -> Application @@ -86,7 +86,7 @@ waiApp cfg self req respond = route $ pathInfo req staticApp (defaultFileServerSettings docroot) {ss404Handler = Just (staticApp' docroots next)} - template = cfg.cfg_html_template TemplateConfig { + template = cfg.cfg_template TemplateConfig { tpc_jsrts = jsrts, tpc_websocket_addr = "/dev.sock" } @@ -98,19 +98,19 @@ fallbackApp _ respond = respond $ responseLBS status404 websocketApp :: ServerConfig -> ServerInstance -> ServerApp websocketApp cfg self p = - bracket acceptConn dropConn \connInfo -> - withPingThread connInfo.connection 30 (pure ()) $ loop connInfo + bracket acceptConn dropConn \devConn -> + withPingThread devConn.dsc_websocket 30 (pure ()) $ loop devConn where - acceptConn = mdo + acceptConn = do conn <- acceptRequest p newConn conn - dropConn (conn::ClientConnection) = do - modifyIORef' self.sri_connection_state $ Map.delete conn.connection_id + dropConn (conn::DevServerConn) = do + modifyIORef' self.sri_dsc_websocket_state $ Map.delete conn.dsc_connection_id cfg.cfg_connection_lost conn - loop (conn::ClientConnection) = do + loop (conn::DevServerConn) = do raceResult <- race - (try @ConnectionException (receiveData conn.connection)) - (readChan conn.command_chan) + (try @ConnectionException (receiveData conn.dsc_websocket)) + (readChan conn.dsc_command_chan) case raceResult of Left (Right (incomingBytes::ByteString)) -> do let jsMessage = Binary.decode . BSL.fromStrict $ incomingBytes @@ -122,34 +122,33 @@ websocketApp cfg self p = reader conn $ Left jsAction loop conn - reader :: ClientConnection -> Either (JSM ()) ClientMsg -> IO () + reader :: DevServerConn -> Either (JSM ()) ClientMsg -> IO () reader conn (Right (StartMsg flags)) = - void $ runTransition conn.internal_env + void $ runJSM conn.dsc_internal_env $ cfg.cfg_client conn flags reader conn (Right (ResumeMsg contId pload)) = - prompt conn.internal_env.hte_prompt_tag do - awatingThread <- atomicModifyIORef' conn.internal_env.hte_continuations $ + prompt conn.dsc_internal_env.ien_prompt_tag do + awatingThread <- atomicModifyIORef' conn.dsc_internal_env.ien_continuations $ swap . Map.alterF (,Nothing) contId forM_ awatingThread \cont -> cont $ pure pload reader conn (Right (EventMsg eid arg)) = - void $ runTransition conn.internal_env - $ modify (triggerEventOp (unsafeFromEventId eid) arg) + void $ runJSM conn.dsc_internal_env $ triggerEvent (unsafeFromEventId eid) arg reader conn (Left a) = - void $ runTransition conn.internal_env a + void $ runJSM conn.dsc_internal_env a - newConn connection = mdo - command_chan <- newChan - (internal_env, _) <- newInternalEnv (100 * 1024) \(ptr, len) -> do + newConn dsc_websocket = do + dsc_command_chan <- newChan + (dsc_internal_env, _) <- newInternalEnv (100 * 1024) \(ptr, len) -> do bs <- unsafePackCStringLen (castPtr ptr, len) - sendDataMessage connection $ Network.WebSockets.Binary $ BSL.fromStrict bs - atomicModifyIORef' self.sri_connection_state \m -> - let conn = ClientConnection { - internal_env, - connection, - command_chan, - connection_id = maybe 0 (succ . fst) $ Map.lookupMax m + sendDataMessage dsc_websocket $ Network.WebSockets.Binary $ BSL.fromStrict bs + atomicModifyIORef' self.sri_dsc_websocket_state \m -> + let conn = DevServerConn { + dsc_internal_env, + dsc_websocket, + dsc_command_chan, + dsc_connection_id = maybe 0 (succ . fst) $ Map.lookupMax m } - in (Map.insert conn.connection_id conn m, conn) + in (Map.insert conn.dsc_connection_id conn m, conn) tryPorts :: Warp.Settings -> Application -> IO () tryPorts set app = do @@ -167,7 +166,7 @@ tryPorts set app = do runDefault :: JSM () -> IO () runDefault client = runConfig ServerConfig { - cfg_html_template = defaultTemplate, + cfg_template = defaultTemplate, cfg_docroots = [], cfg_client = const $ const client, cfg_connection_lost = const $ pure (), diff --git a/clickable.cabal b/clickable.cabal index 3219fa6..c1329ae 100644 --- a/clickable.cabal +++ b/clickable.cabal @@ -18,7 +18,7 @@ executable clickable other-modules: Clickable Clickable.Element - Clickable.Float + Clickable.Binary Clickable.HTML Clickable.Internal Clickable.Property diff --git a/jsbits/proto.ts b/jsbits/proto.ts index 7633c81..9f0f088 100644 --- a/jsbits/proto.ts +++ b/jsbits/proto.ts @@ -77,12 +77,12 @@ export enum ExprTag { ClassListRemove, InsertBrackets, ClearBrackets, - DropBrackets, + DetachBrackets, CreateElement, CreateElementNS, - CreateTextNode, - UpdateTextNode, + CreateText, + UpdateText, Eval, TriggerEvent, @@ -131,12 +131,12 @@ export type Expr = | [ExprTag.ClassListRemove, Expr, string[]] | [ExprTag.InsertBrackets] | [ExprTag.ClearBrackets, Expr] - | [ExprTag.DropBrackets, Expr] + | [ExprTag.DetachBrackets, Expr] | [ExprTag.CreateElement, string] | [ExprTag.CreateElementNS, string, string] - | [ExprTag.CreateTextNode, string] - | [ExprTag.UpdateTextNode, Expr, string] + | [ExprTag.CreateText, string] + | [ExprTag.UpdateText, Expr, string] | [ExprTag.Eval, string] | [ExprTag.TriggerEvent, number, Expr] @@ -479,7 +479,7 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u utils.clearBrackets(node as any, false); return null; }; - case ExprTag.DropBrackets: { + case ExprTag.DetachBrackets: { const node = evalNext(self, args, prevRes); utils.clearBrackets(node as any, true); return null; @@ -493,11 +493,11 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u const ns = decodeString(self); return document.createElementNS(tagName, ns); }; - case ExprTag.CreateTextNode: { + case ExprTag.CreateText: { const content = decodeString(self); return document.createTextNode(content); }; - case ExprTag.UpdateTextNode: { + case ExprTag.UpdateText: { const node = evalNext(self, args, prevRes); const content = decodeString(self); (node as Text).textContent = content; @@ -680,7 +680,7 @@ export function lookaheadNext(mem: DataView, ptr: Ptr): Ptr { case ExprTag.ClearBrackets: { return lookaheadNext(mem, ptr); }; - case ExprTag.DropBrackets: { + case ExprTag.DetachBrackets: { return lookaheadNext(mem, ptr); }; case ExprTag.CreateElement: { @@ -690,10 +690,10 @@ export function lookaheadNext(mem: DataView, ptr: Ptr): Ptr { const newPtr0 = lookaheadString(mem, ptr); return lookaheadString(mem, newPtr0); }; - case ExprTag.CreateTextNode: { + case ExprTag.CreateText: { return lookaheadString(mem, ptr); }; - case ExprTag.UpdateTextNode: { + case ExprTag.UpdateText: { const newPtr0 = lookaheadNext(mem, ptr); return lookaheadString(mem, newPtr0); }; diff --git a/wasm.hs b/wasm.hs index 7b91ee5..e96122d 100644 --- a/wasm.hs +++ b/wasm.hs @@ -21,7 +21,7 @@ import Control.Monad.Reader test01 :: JSM () test01 = do - enqueueExpr $ PushStack $ Id "document" `Dot` "body" + jsCmd $ PushStack $ Id "document" `Dot` "body" counter <- newVar 0 el "div" do prop "className" (Str "container") @@ -42,9 +42,9 @@ test01 = do el "button" do text "Ask a Value" on @"click" do - t <- asks (.hte_prompt_tag) + t <- asks (.ien_prompt_tag) val <- liftIO $ control t \cont -> writeIORef ref cont - enqueueExpr $ Call (Id "console") "log" $ valueToExpr val + jsCmd $ Call (Id "console") "log" $ valueToExpr val el "button" do text "Fill the value" on @"click" do diff --git a/websocket.hs b/websocket.hs index cd7911d..0776963 100644 --- a/websocket.hs +++ b/websocket.hs @@ -41,9 +41,9 @@ test01 = do el "button" do text "Ask a Value" on @"click" do - t <- asks (.hte_prompt_tag) + t <- asks (.ien_prompt_tag) val <- liftIO $ control t \cont -> writeIORef ref cont - enqueueExpr $ Call (Id "console") "log" [val] + jsCmd $ Call (Id "console") "log" [val] el "button" do text "Fill the value" on @"click" do From 8a5f7470152a310c929c1c4caa6697798134ce50 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 19 Nov 2024 18:43:42 +0400 Subject: [PATCH 60/64] Fix a bug in encodeValue --- Clickable.hs | 1 + Clickable/DOM.hs | 288 +++++++++++++++++++++++++++++++++++++++++ Clickable/HTML.hs | 104 +-------------- Clickable/Types.hs | 7 + Clickable/WebSocket.hs | 13 +- clickable.cabal | 1 + jsbits/index.js | 3 + jsbits/misc.ts | 27 ++++ jsbits/proto.ts | 69 +++++----- jsbits/wasm.ts | 21 +-- jsbits/websocket.ts | 16 +-- 11 files changed, 394 insertions(+), 156 deletions(-) create mode 100644 Clickable/DOM.hs create mode 100644 jsbits/misc.ts diff --git a/Clickable.hs b/Clickable.hs index 0e080a5..c680fe8 100644 --- a/Clickable.hs +++ b/Clickable.hs @@ -3,6 +3,7 @@ Native GHC -} module Clickable (module Exports) where import Clickable.HTML as Exports +import Clickable.DOM as Exports import Clickable.Element as Exports import Clickable.Property as Exports import Clickable.Internal as Exports diff --git a/Clickable/DOM.hs b/Clickable/DOM.hs new file mode 100644 index 0000000..c88ca7c --- /dev/null +++ b/Clickable/DOM.hs @@ -0,0 +1,288 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE DataKinds #-} +{-# OPTIONS_GHC -Wall #-} +module Clickable.DOM where + +import Data.Text (Text) +import GHC.Generics (Generic) +import Clickable.Types +import Data.Kind +import Data.Int +import Clickable.Internal +import Unsafe.Coerce + + +data ListenerOptions = ListenerOptions { + prevent_default :: Bool, + stop_propagation :: Bool +} deriving (Generic, Show, Eq) + +defaultListenerOptions :: ListenerOptions +defaultListenerOptions = ListenerOptions { + prevent_default = False, + stop_propagation = False +} + +addEventListener :: FromJSVal a => (Event a -> JSExp) -> (a -> JSM ()) -> JSM () +addEventListener addScript k = + reactive add >>= jsCmd where + add scope s = (s''', cmd) where + k' = localScope scope . k + eventId = EventId s.ist_id_supply + (s', unsub) = newRefIdFn scope s {ist_id_supply = s.ist_id_supply + 1} + s'' = subscribeEventFn (unsafeFromEventId eventId) + (mapM_ k' . fromJSVal . unsafeCoerce) scope s' + s''' = installFinalizerFn (jsCmd $ Apply (Ref unsub) []) scope s'' + cmd = AssignRef unsub $ addScript $ Event eventId + +class EventName eventName where + type EventListenerCb eventName :: Type + connectEventName :: EventListenerCb eventName -> JSM () + +instance EventName "click" where + type EventListenerCb "click" = JSM () + connectEventName k = addEventListener + (genericEvent defaultListenerOptions "click" (PeekStack 0)) (const k) + +instance EventName "mousedown" where + type EventListenerCb "mousedown" = JSM () + connectEventName k = addEventListener + (genericEvent defaultListenerOptions "mousedown" (PeekStack 0)) (const k) + +instance EventName "mouseup" where + type EventListenerCb "mouseup" = JSM () + connectEventName k = addEventListener + (genericEvent defaultListenerOptions "mouseup" (PeekStack 0)) (const k) + +instance EventName "mouseenter" where + type EventListenerCb "mouseenter" = JSM () + connectEventName k = addEventListener + (genericEvent defaultListenerOptions "mouseenter" (PeekStack 0)) (const k) + +instance EventName "mouseleave" where + type EventListenerCb "mouseleave" = JSM () + connectEventName k = addEventListener + (genericEvent defaultListenerOptions "mouseleave" (PeekStack 0)) (const k) + +instance EventName "dblclick" where + type EventListenerCb "dblclick" = JSM () + connectEventName k = addEventListener + (genericEvent defaultListenerOptions "dblclick" (PeekStack 0)) (const k) + +instance EventName "submit" where + type EventListenerCb "submit" = JSM () + connectEventName k = + addEventListener (genericEvent opt "submit" (PeekStack 0)) (const k) + where + opt = ListenerOptions { + prevent_default = True, + stop_propagation = True + } + +instance EventName "input" where + type EventListenerCb "input" = Text -> JSM () + connectEventName = addEventListener (inputEvent "input") + +instance EventName "keydown" where + type EventListenerCb "keydown" = Int32 -> JSM () + connectEventName = addEventListener (keyboardEvent "keydown") + +instance EventName "keyup" where + type EventListenerCb "keyup" = Int32 -> JSM () + connectEventName = addEventListener (keyboardEvent "keyup") + +instance EventName "focus" where + type EventListenerCb "focus" = JSM () + connectEventName k = addEventListener + (genericEvent defaultListenerOptions "focus" (PeekStack 0)) (const k) + +instance EventName "blur" where + type EventListenerCb "blur" = JSM () + connectEventName k = addEventListener + (genericEvent defaultListenerOptions "blur" (PeekStack 0)) (const k) + +instance EventName "input/blur" where + type EventListenerCb "input/blur" = Text -> JSM () + connectEventName = addEventListener (inputEvent "blur") + +instance EventName "input/focus" where + type EventListenerCb "input/focus" = Text -> JSM () + connectEventName = addEventListener (inputEvent "focus") + +instance EventName "checkbox/change" where + type EventListenerCb "checkbox/change" = Bool -> JSM () + connectEventName = addEventListener checkboxChangeEvent + +instance EventName "select/change" where + type EventListenerCb "select/change" = Text -> JSM () + connectEventName = addEventListener selectChangeEvent + +instance EventName "mousewheel" where + type EventListenerCb "mousewheel" = MouseWheel -> JSM () + connectEventName = addEventListener mouseWheelEvent + +on :: forall eventName. EventName eventName => EventListenerCb eventName -> HTML () +on k = liftJSM $ connectEventName @eventName k + +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event +genericEvent :: ListenerOptions -> Text -> JSExp -> Event () -> JSExp +genericEvent opt eventName target (Event eventId) = + Eval script `Apply` [target, Lam (TriggerEvent eventId Null)] + where + script = + "(function(target, trigger){\n\ + \ function listener(event){\n\ + \ " <> preventDefaultStmt <> "\n\ + \ " <> stopPropagationStmt <> "\n\ + \ trigger();\n\ + \ }\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \})" + preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" + stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event +inputEvent :: Text -> Event Text -> JSExp +inputEvent eventName (Event eventId) = + Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] + where + script = + "(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger(event.target.value);\n\ + \ }\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \})" + +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event +-- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event +keyboardEvent :: Text -> Event Int32 -> JSExp +keyboardEvent eventName (Event eventId) = + Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] + where + script = + "(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger(event.keyCode);\n\ + \ }\n\ + \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ + \})" + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event +checkboxChangeEvent :: Event Bool -> JSExp +checkboxChangeEvent (Event eventId) = + Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] + where + script = + "(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger(event.target.checked);\n\ + \ }\n\ + \ target.addEventListener('change', listener);\n\ + \ return () => target.removeEventListener('change', listener);\n\ + \})" + +-- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event +selectChangeEvent :: Event Text -> JSExp +selectChangeEvent (Event eventId) = + Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] + where + script = + "(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger(event.target.value);\n\ + \ }\n\ + \ target.addEventListener('change', listener);\n\ + \ return () => target.removeEventListener('change', listener);\n\ + \})" + +-- | Collection of deltaX, deltaY and deltaZ properties from WheelEvent +-- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent +data MouseWheel = MouseWheel { + mw_delta_x :: Int32, + mw_delta_y :: Int32, + mw_delta_z :: Int32, + mw_alt_key :: Bool, + mw_ctrl_key :: Bool, + mw_meta_key :: Bool, + mw_shift_key :: Bool +} deriving stock (Eq, Show, Generic) + deriving anyclass (FromJSVal, ToJSVal) + +-- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent +mouseWheelEvent :: Event MouseWheel -> JSExp +mouseWheelEvent (Event eventId) = + Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] + where + script = + "(function(target, trigger){\n\ + \ function listener(event){\n\ + \ trigger({\n\ + \ mw_delta_x: event.deltaX,\n\ + \ mw_delta_y: event.deltaY,\n\ + \ mw_delta_z: event.deltaZ,\n\ + \ mw_alt_key: event.altKey,\n\ + \ mw_ctrl_key: event.ctrlKey,\n\ + \ mw_meta_key: event.metaKey,\n\ + \ mw_shift_key: event.shiftKey\n\ + \ });\n\ + \ }\n\ + \ target.addEventListener('mousewheel', listener);\n\ + \ return () => target.removeEventListener('mousewheel', listener);\n\ + \})" + +data Location = Location { + -- | A string containing the protocol scheme of the URL, including + -- the final ':' + loc_protocol :: Text, + -- | A string containing the domain of the URL. + loc_hostname :: Text, + -- | A string containing the port number of the URL. + loc_port :: Text, + -- | A string containing an initial '/' followed by the path of the + -- URL, not including the query string or fragment. + loc_pathname :: Text, + -- | String containing a '?' followed by the parameters or + -- "querystring" of the URL + loc_search :: Text, + -- | String containing a '#' followed by the fragment identifier + -- of the URL. + loc_hash :: Text +} deriving stock (Show, Eq, Generic) + deriving anyclass (FromJSVal, ToJSVal) + +-- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event +popstateEvent :: Event Location -> JSExp +popstateEvent (Event eventId) = + Eval script `Apply` [Id "window", Lam (TriggerEvent eventId (Arg 0))] + where + script = + "(function(target, trigger){\n\ + \ function listener(){\n\ + \ trigger({\n\ + \ loc_protocol: location.protocol,\n\ + \ loc_hostname: location.hostname,\n\ + \ loc_port: location.port,\n\ + \ loc_pathname: location.pathname,\n\ + \ loc_search: location.search,\n\ + \ loc_hash: location.hash\n\ + \ });\n\ + \ }\n\ + \ target.addEventListener('popstate', listener);\n\ + \ return () => target.removeEventListener('popstate', listener);\n\ + \})" diff --git a/Clickable/HTML.hs b/Clickable/HTML.hs index c7a4923..456bd62 100644 --- a/Clickable/HTML.hs +++ b/Clickable/HTML.hs @@ -13,13 +13,10 @@ module Clickable.HTML where import Clickable.Internal import Clickable.Types -import Data.Kind (Type) -import Data.Text (Text) -import GHC.Generics (Generic) -import Unsafe.Coerce (unsafeCoerce) +import Control.Monad import Control.Monad.Trans import Data.IORef -import Control.Monad +import Data.Text (Text) el :: Text -> HTML a -> HTML a el tagName child = HTML \s e -> do @@ -104,62 +101,6 @@ toggleClass className dynEnable = HTML \s e -> do pure ((), s') {-# INLINE toggleClass #-} -addEventListener :: FromJSVal a => (Event a -> JSExp) -> (a -> JSM ()) -> JSM () -addEventListener addScript k = - reactive add >>= jsCmd where - add scope s = (s''', cmd) where - k' = localScope scope . k - eventId = EventId s.ist_id_supply - (s', unsub) = newRefIdFn scope s {ist_id_supply = s.ist_id_supply + 1} - s'' = subscribeEventFn (unsafeFromEventId eventId) - (mapM_ k' . fromJSVal . unsafeCoerce) scope s' - s''' = installFinalizerFn (jsCmd $ Apply (Ref unsub) []) scope s'' - cmd = AssignRef unsub $ addScript $ Event eventId - -class IsEventName eventName where - type EventListenerCb eventName :: Type - connectEventName :: EventListenerCb eventName -> JSM () - -on :: forall eventName. IsEventName eventName => EventListenerCb eventName -> HTML () -on k = liftJSM $ connectEventName @eventName k - -instance IsEventName "click" where - type EventListenerCb "click" = JSM () - connectEventName k = addEventListener - (genericEvent defaultEventListenerOptions "click" (PeekStack 0)) (const k) - -data EventListenerOptions = EventListenerOptions { - prevent_default :: Bool, - stop_propagation :: Bool -} deriving stock (Generic, Show, Eq) - -defaultEventListenerOptions :: EventListenerOptions -defaultEventListenerOptions = EventListenerOptions { - prevent_default = False, - stop_propagation = False -} - -genericEvent :: EventListenerOptions -> Text -> JSExp -> Event () -> JSExp -genericEvent opt eventName target (Event eid) = - Eval script `Apply` [target, Lam (TriggerEvent eid Null)] - where - script = - ("(function(target, trigger){\n\ - \ function listener(event){\n\ - \ " <> preventDefaultStmt <> "\n\ - \ " <> stopPropagationStmt <> "\n\ - \ trigger();\n\ - \ }\n\ - \ target.addEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \ return () => target.removeEventListener('" <> UnsafeJavaScript eventName <> "', listener);\n\ - \})") - preventDefaultStmt = if opt.prevent_default then "event.preventDefault();" else "" - stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" - -unsafeConnectEvent :: JSExp -> UnsafeJavaScript -> Event a -> JSExp -unsafeConnectEvent target ujs (Event eid) = - Eval ujs `Apply` [target, Lam (TriggerEvent eid (Arg 0))] - attachTo :: JSExp -> HTML a -> JSM a attachTo rootEl contents = JSM \e -> do e.ien_command $ PushStack rootEl @@ -184,47 +125,6 @@ blank :: Applicative m => m () blank = pure () {-# INLINE blank #-} -data Location = Location { - -- | A string containing the protocol scheme of the URL, including - -- the final ':' - protocol :: Text, - -- | A string containing the domain of the URL. - hostname :: Text, - -- | A string containing the port number of the URL. - port :: Text, - -- | A string containing an initial '/' followed by the path of the - -- URL, not including the query string or fragment. - pathname :: Text, - -- | String containing a '?' followed by the parameters or - -- "querystring" of the URL - search :: Text, - -- | String containing a '#' followed by the fragment identifier - -- of the URL. - hash :: Text -} deriving stock (Show, Eq, Generic) - deriving anyclass (FromJSVal, ToJSVal) - --- https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event -popstateEvent :: Event Location -> JSExp -popstateEvent (Event eventId) = - Eval script `Apply` [Id "window", Lam (TriggerEvent eventId (Arg 0))] - where - script = - "(function(target, trigger){\n\ - \ function listener(){\n\ - \ trigger({\n\ - \ protocol: location.protocol,\n\ - \ hostname: location.hostname,\n\ - \ port: location.port,\n\ - \ pathname: location.pathname,\n\ - \ search: location.search,\n\ - \ hash: location.hash\n\ - \ });\n\ - \ }\n\ - \ target.addEventListener('popstate', listener);\n\ - \ return () => target.removeEventListener('popstate', listener);\n\ - \})" - dyn :: Dynamic (HTML ()) -> HTML () dyn val = do brackets <- liftJSM insertBrackets diff --git a/Clickable/Types.hs b/Clickable/Types.hs index ead9e25..0627490 100644 --- a/Clickable/Types.hs +++ b/Clickable/Types.hs @@ -92,6 +92,13 @@ instance MonadJSM HTML where liftJSM (JSM a) = HTML \s e -> (,s) <$> a e {-# INLINE liftJSM #-} +instance a ~ () => IsString (HTML a) where + fromString t = HTML \s e -> do + e.ien_command $ PushStack $ CreateText $ Text.pack t + e.ien_command PopIns + return ((), s) + {-# INLINE fromString #-} + data JSExp where Null :: JSExp Bool :: Word8 -> JSExp diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index e823c03..0d607d3 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -53,6 +53,12 @@ data TemplateConfig = TemplateConfig { tpc_websocket_addr :: Builder } +defaultTemplateConfig :: TemplateConfig +defaultTemplateConfig = TemplateConfig { + tpc_jsrts = jsrts, + tpc_websocket_addr = "/dev.sock" +} + data DevServerConn = DevServerConn { dsc_websocket :: Connection, dsc_internal_env :: InternalEnv, @@ -86,10 +92,7 @@ waiApp cfg self req respond = route $ pathInfo req staticApp (defaultFileServerSettings docroot) {ss404Handler = Just (staticApp' docroots next)} - template = cfg.cfg_template TemplateConfig { - tpc_jsrts = jsrts, - tpc_websocket_addr = "/dev.sock" - } + template = cfg.cfg_template defaultTemplateConfig fallbackApp :: Application fallbackApp _ respond = respond $ responseLBS status404 @@ -198,4 +201,4 @@ defaultTemplate cfg = -- yarn run webpack --mode production && cat dist-newstyle/index.bundle.js | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' jsrts :: Builder jsrts = - "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeValue(e,t),encodeValue(e,n)}))}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DropBrackets=38]=\"DropBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateTextNode=41]=\"CreateTextNode\",e[e.UpdateTextNode=42]=\"UpdateTextNode\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.YieldResult=45]=\"YieldResult\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null){const n=new WebSocket(e),r={refs:new Map,stack:null};function s(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.EventMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))}function i(e,t){const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.ResumeMsg,e,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))}n.onopen=e=>{const r={mem,begin:0,end:outBuf.byteLength};proto.ni(r,[proto.JC.StartMsg,t]),n.send(new Uint8Array(outBuf).subarray(0,r.begin))},n.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({triggerEvent:s,resumeCont:i,persistent:r,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},n.onerror=e=>{console.error(\"WebSocket error:\",e)},n.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(3e4,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null){const n=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]),r={refs:new Map,stack:null};function s(e,t){const n=new DataView(inst.exports.memory.buffer),s={triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)},resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},persistent:r,mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:n.wasiImport,env:{clickable_eval_buffer:s}}))).then((e=>{inst=e,n.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}window.clickable={runWebsocket,runWasm}})();" + "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeString(e,t),encodeValue(e,n)}))}function encodeString(e,t){const n=new Uint8Array(e.mem.buffer).subarray(e.begin+8),r=(new TextEncoder).encodeInto(t,n);e.mem.setBigUint64(e.begin,BigInt(r.written),!1),e.begin+=8+r.written}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DetachBrackets=38]=\"DetachBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateText=41]=\"CreateText\",e[e.UpdateText=42]=\"UpdateText\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.Resume=45]=\"Resume\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null,n){const r=new WebSocket(e),s={refs:(null==n?void 0:n.refs)||new Map,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.EventMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},resumeCont:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.ResumeMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))}};r.onopen=e=>{const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.StartMsg,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},r.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({context:s,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},r.onerror=e=>{console.error(\"WebSocket error:\",e)},r.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(5e3,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null,n){const r={refs:(null==n?void 0:n.refs)||new Map,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(){},resumeCont:function(){}},s=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]);function i(e,t){const n=new DataView(inst.exports.memory.buffer),s={context:Object.assign(Object.assign({},r),{resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)}}),mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:s.wasiImport,env:{clickable_eval_buffer:i}}))).then((e=>{inst=e,s.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}function evalUint8Array(e,t){const n={context:{refs:(null==t?void 0:t.refs)||new Map,stack:(null==t?void 0:t.stack)||null,triggerEvent:(null==t?void 0:t.triggerEvent)||function(){},resumeCont:(null==t?void 0:t.resumeCont)||function(){}},mem:new DataView(e.buffer),isMutableMem:!1,begin:0,end:e.byteLength};return proto.iQ(n)}function evalBase64(e,t){return evalUint8Array(Uint8Array.from(atob(e),(function(e){return e.charCodeAt(0)})),t)}window.clickable={runWebsocket,runWasm,evalUint8Array,evalBase64}})();" diff --git a/clickable.cabal b/clickable.cabal index c1329ae..d517300 100644 --- a/clickable.cabal +++ b/clickable.cabal @@ -19,6 +19,7 @@ executable clickable Clickable Clickable.Element Clickable.Binary + Clickable.DOM Clickable.HTML Clickable.Internal Clickable.Property diff --git a/jsbits/index.js b/jsbits/index.js index 53508ec..0fbe7b0 100644 --- a/jsbits/index.js +++ b/jsbits/index.js @@ -1,7 +1,10 @@ import * as websocket from './websocket'; import * as wasm from './wasm'; +import * as misc from './misc'; window.clickable = { runWebsocket: websocket.runWebsocket, runWasm: wasm.runWasm, + evalUint8Array: misc.evalUint8Array, + evalBase64: misc.evalBase64, }; diff --git a/jsbits/misc.ts b/jsbits/misc.ts new file mode 100644 index 0000000..1dbf998 --- /dev/null +++ b/jsbits/misc.ts @@ -0,0 +1,27 @@ +import { EvalState, EvalContext } from "./proto"; +import * as proto from "./proto"; + + +export function evalUint8Array(command: Uint8Array, options?: Partial): unknown { + const context: EvalContext = { + refs: options?.refs || new Map(), + stack: options?.stack || null, + triggerEvent: options?.triggerEvent || function() {}, + resumeCont: options?.resumeCont || function() {}, + }; + const mem = new DataView(command.buffer); + + const intp: EvalState = { + context, + mem, + isMutableMem: false, + begin: 0, + end: command.byteLength, + }; + return proto.evalMem(intp); +} + +export function evalBase64(command: string, options?: Partial): unknown { + const u8array = Uint8Array.from(atob(command), function(c) { return c.charCodeAt(0); }); + return evalUint8Array(u8array, options); +} diff --git a/jsbits/proto.ts b/jsbits/proto.ts index 9f0f088..215a2af 100644 --- a/jsbits/proto.ts +++ b/jsbits/proto.ts @@ -149,27 +149,28 @@ export type RefId = number; export type EventId = number; export type EvalState = { - readonly triggerEvent: (eventId: EventId, arg: unknown) => void; - readonly resumeCont: (contId: number, res: unknown) => void; - readonly persistent: PersistentState; + readonly context: EvalContext; readonly mem: DataView; readonly isMutableMem: boolean; begin: Ptr; readonly end: Ptr; }; -export type PersistentState = { +export type EvalContext = { + readonly triggerEvent: (eventId: EventId, arg: unknown) => void; + readonly resumeCont: (contId: number, res: unknown) => void; readonly refs: Map>; stack: List; }; /** Evaluate sequence of `Expr` encoded as `Data.Binary.Binary` * instance inside the memory given in `self.mem` */ -export function evalMem(self: EvalState): void { +export function evalMem(self: EvalState): unknown { let res = null; for (; self.begin < self.end;) { res = evalNext(self, null, res); } + return res; } /** Evaluate next single `Expr` relative to `self.begin` pointer */ @@ -367,13 +368,13 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u const refId = self.mem.getUint32(self.begin + 4, false); self.begin += 8; const val = evalNext(self, args, prevRes); - if (self.persistent.refs.has(scopeId)) { - const scopeMap = self.persistent.refs.get(scopeId)!; + if (self.context.refs.has(scopeId)) { + const scopeMap = self.context.refs.get(scopeId)!; scopeMap.set(refId, val); } else { const scopeMap = new Map(); scopeMap.set(refId, val); - self.persistent.refs.set(scopeId, scopeMap); + self.context.refs.set(scopeId, scopeMap); } return val; }; @@ -381,11 +382,11 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u const scopeId = self.mem.getUint32(self.begin, false); const refId = self.mem.getUint32(self.begin + 4, false); self.begin += 8; - const scopeMap = self.persistent.refs.get(scopeId); + const scopeMap = self.context.refs.get(scopeId); if (!scopeMap) return null; scopeMap.delete(refId); if (scopeMap.size == 0) { - self.persistent.refs.delete(scopeId); + self.context.refs.delete(scopeId); } return null; }; @@ -393,19 +394,19 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u const scopeId = self.mem.getUint32(self.begin, false); const refId = self.mem.getUint32(self.begin + 4, false); self.begin += 8; - return self.persistent.refs.get(scopeId)?.get(refId); + return self.context.refs.get(scopeId)?.get(refId); }; case ExprTag.FreeScope: { const scopeId = self.mem.getUint32(self.begin, false); self.begin += 4; - self.persistent.refs.delete(scopeId); + self.context.refs.delete(scopeId); return null; }; case ExprTag.PeekStack: { const stackIx = self.mem.getInt8(self.begin); self.begin += 1; - let iter = self.persistent.stack; + let iter = self.context.stack; let i = 0; while (iter) { if (i == stackIx) { @@ -418,28 +419,28 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u }; case ExprTag.PushStack: { const val = evalNext(self, args, prevRes); - self.persistent.stack = Cons(val, self.persistent.stack); + self.context.stack = Cons(val, self.context.stack); return val; }; case ExprTag.PopStack: { - if (!self.persistent.stack) { + if (!self.context.stack) { throw new Error("PopStack: empty stack"); } - const res = self.persistent.stack[VAL]; - self.persistent.stack = self.persistent.stack[NEXT]; + const res = self.context.stack[VAL]; + self.context.stack = self.context.stack[NEXT]; return res; }; case ExprTag.PopIns: { - if (!self.persistent.stack) { + if (!self.context.stack) { throw new Error("PopIns: empty stack"); } - const tip = self.persistent.stack[VAL] as Node; - self.persistent.stack = self.persistent.stack[NEXT]; - if (!self.persistent.stack) { + const tip = self.context.stack[VAL] as Node; + self.context.stack = self.context.stack[NEXT]; + if (!self.context.stack) { throw new Error("PopIns: empty stack"); } - const parent = self.persistent.stack[VAL] as Element; + const parent = self.context.stack[VAL] as Element; utils.insert(parent, tip); return tip; }; @@ -468,10 +469,10 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u return el.classList.remove(className); }; case ExprTag.InsertBrackets: { - if (!self.persistent.stack) { + if (!self.context.stack) { throw new Error("InsertBrackets: empty stack"); } - const el = self.persistent.stack[VAL] as any; + const el = self.context.stack[VAL] as any; return utils.insertBrackets(el); }; case ExprTag.ClearBrackets: { @@ -511,13 +512,13 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u const eventId = self.mem.getUint32(self.begin, false); self.begin += 4; const pload = evalNext(self, args, prevRes); - self.triggerEvent(eventId, pload); + self.context.triggerEvent(eventId, pload); return null; }; case ExprTag.Resume: { const contId = self.mem.getUint32(self.begin, false); self.begin += 4; - self.resumeCont(contId, prevRes); + self.context.resumeCont(contId, prevRes); return null; }; } @@ -743,10 +744,8 @@ export function encodeValue(self: EncoderState, val: unknown): void { } if (typeof(val) === 'string') { self.mem.setUint8(self.begin, ExprTag.Str); - const destRange = new Uint8Array(self.mem.buffer).subarray(self.begin + 9); - const encResult = new TextEncoder().encodeInto(val, destRange) - self.mem.setBigUint64(self.begin + 1, BigInt(encResult.written), false); - self.begin += 9 + encResult.written; + self.begin++; + encodeString(self, val); return; } if (typeof(val) === 'bigint') { @@ -781,12 +780,20 @@ export function encodeValue(self: EncoderState, val: unknown): void { self.begin += 9; entries.forEach(([k, v]) => { - encodeValue(self, k); + encodeString(self, k); encodeValue(self, v); }); return; } +function encodeString(self: EncoderState, s: string): void { + const destRange = new Uint8Array(self.mem.buffer).subarray(self.begin + 8); + const encResult = new TextEncoder().encodeInto(s, destRange) + self.mem.setBigUint64(self.begin, BigInt(encResult.written), false); + self.begin += 8 + encResult.written; + return; +} + export enum ClientMsgTag { StartMsg, EventMsg, diff --git a/jsbits/wasm.ts b/jsbits/wasm.ts index b1bf8ab..f852de4 100644 --- a/jsbits/wasm.ts +++ b/jsbits/wasm.ts @@ -1,24 +1,27 @@ import { WASI, File, OpenFile } from '@bjorn3/browser_wasi_shim'; -import { ClientMsgTag, EventId, EvalState, PersistentState, Ptr } from "./proto"; +import { ClientMsgTag, EventId, EvalState, Ptr, EvalContext } from "./proto"; import * as proto from "./proto"; let inst: WebAssembly.Instance; -export function runWasm(wasmUri: string, startFlags: unknown = null) { +export function runWasm(wasmUri: string, startFlags: unknown = null, options?: Partial) { + const context: EvalContext = { + refs: options?.refs || new Map(), + stack: options?.stack || null, + triggerEvent: function() {}, + resumeCont: function() {}, + }; + const wasi = new WASI([], [], [ new OpenFile(new File([])), // stdin new OpenFile(new File([])), // stdout new OpenFile(new File([])), // stderr ]); - const persistent: PersistentState = { - refs: new Map(), - stack: null, - }; - function clickable_eval_buffer(ptr: Ptr, len: number): void { // @ts-ignore const mem = new DataView(inst.exports.memory.buffer); + const context1 = {...context, resumeCont, triggerEvent} function triggerEvent(eventId: EventId, arg: unknown) { const encoderState = {mem, begin: ptr, end: ptr + len}; @@ -35,9 +38,7 @@ export function runWasm(wasmUri: string, startFlags: unknown = null) { }; const intp: EvalState = { - triggerEvent, - resumeCont, - persistent, + context: context1, mem, isMutableMem: true, begin: ptr, diff --git a/jsbits/websocket.ts b/jsbits/websocket.ts index bf2251c..799c04c 100644 --- a/jsbits/websocket.ts +++ b/jsbits/websocket.ts @@ -1,14 +1,16 @@ -import { ClientMsgTag, EventId, PersistentState } from "./proto"; +import { ClientMsgTag, EvalContext, EventId } from "./proto"; import * as proto from "./proto"; const outBuf = new ArrayBuffer(100 * 1024); const mem = new DataView(outBuf); -export function runWebsocket(devSocketUri: string, startFlags: unknown = null) { +export function runWebsocket(devSocketUri: string, startFlags: unknown = null, options?: Partial) { const websocket = new WebSocket(devSocketUri); - const persistent: PersistentState = { - refs: new Map(), - stack: null, + const context: EvalContext = { + refs: options?.refs || new Map(), + stack: options?.stack || null, + triggerEvent, + resumeCont, }; function triggerEvent(eventId: EventId, arg: unknown) { @@ -33,9 +35,7 @@ export function runWebsocket(devSocketUri: string, startFlags: unknown = null) { websocket.onmessage = (event) => { convertBlobToUint8Array(event.data).then(buf => { proto.evalMem({ - triggerEvent, - resumeCont, - persistent, + context, mem: new DataView(buf), isMutableMem: false, begin: 0, From fa87752d4a8c74b0332f17d81b6b8c738ae2d931 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 21 Nov 2024 15:40:51 +0400 Subject: [PATCH 61/64] MoveScope --- Clickable/DOM.hs | 4 +- Clickable/HTML.hs | 144 ++++++++++++++++++-------------------- Clickable/Internal.hs | 83 +++++++++++++--------- Clickable/Types.hs | 29 ++++---- Clickable/WebSocket.hs | 12 ++-- jsbits/misc.ts | 2 +- jsbits/proto.ts | 155 +++++++++++++++++++++++------------------ jsbits/wasm.ts | 2 +- jsbits/websocket.ts | 2 +- 9 files changed, 228 insertions(+), 205 deletions(-) diff --git a/Clickable/DOM.hs b/Clickable/DOM.hs index c88ca7c..7f87e4d 100644 --- a/Clickable/DOM.hs +++ b/Clickable/DOM.hs @@ -32,7 +32,7 @@ defaultListenerOptions = ListenerOptions { } addEventListener :: FromJSVal a => (Event a -> JSExp) -> (a -> JSM ()) -> JSM () -addEventListener addScript k = +addEventListener script k = reactive add >>= jsCmd where add scope s = (s''', cmd) where k' = localScope scope . k @@ -41,7 +41,7 @@ addEventListener addScript k = s'' = subscribeEventFn (unsafeFromEventId eventId) (mapM_ k' . fromJSVal . unsafeCoerce) scope s' s''' = installFinalizerFn (jsCmd $ Apply (Ref unsub) []) scope s'' - cmd = AssignRef unsub $ addScript $ Event eventId + cmd = AssignRef scope unsub $ script $ Event eventId class EventName eventName where type EventListenerCb eventName :: Type diff --git a/Clickable/HTML.hs b/Clickable/HTML.hs index 456bd62..f81d937 100644 --- a/Clickable/HTML.hs +++ b/Clickable/HTML.hs @@ -2,18 +2,12 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE OverloadedRecordDot #-} -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DerivingVia #-} {-# LANGUAGE BlockArguments #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE AllowAmbiguousTypes #-} -{-# LANGUAGE DataKinds #-} {-# OPTIONS_GHC -Wall #-} module Clickable.HTML where import Clickable.Internal import Clickable.Types -import Control.Monad import Control.Monad.Trans import Data.IORef import Data.Text (Text) @@ -46,7 +40,7 @@ dynText contentDyn = HTML \s e -> do c <- readDyn contentDyn refId <- newRefId.unJSM e e.ien_command $ PushStack $ CreateText c - e.ien_command $ AssignRef refId (PeekStack 0) + e.ien_command $ AssignRef e.ien_scope refId (PeekStack 0) e.ien_command PopIns let k nval = JSM \e' -> e'.ien_command $ UpdateText (Ref refId) nval @@ -116,7 +110,7 @@ saveStackHead = HTML \s e -> case s of Nothing -> do refId <- newRefId.unJSM e - e.ien_command $ AssignRef refId $ PeekStack 0 + e.ien_command $ AssignRef e.ien_scope refId $ PeekStack 0 return (refId, Just refId) Just saved -> pure (saved, s) @@ -127,24 +121,23 @@ blank = pure () dyn :: Dynamic (HTML ()) -> HTML () dyn val = do - brackets <- liftJSM insertBrackets scope <- liftJSM newScope - initialVal <- liftJSM $ readDyn val - let - update html = do - liftJSM $ clearBrackets brackets - html - exec h = - localScope scope $ customize (Ref brackets) h - liftJSM $ exec $ update initialVal + place <- liftJSM insertPlaceholder + initial <- liftJSM $ readDyn val + liftJSM $ update scope place initial liftJSM $ subscribe val \newVal -> do freeScope scope - exec $ update newVal + update scope place newVal + where + update scope place content = + localScope scope do + clearPlaceholder place + execHTML (Ref place) content -- | Auxilliary datatype used in 'simpleList' implementation -data ElemEnv a = ElemEnv { - brackets :: RefId, - state_var :: DynVar a, +data InternalElem a = InternalElem { + placeholder :: RefId, + elem_state :: DynVar a, elem_scope :: ScopeId } @@ -152,69 +145,64 @@ data ElemEnv a = ElemEnv { -- a` do not automatically propagate into the larger state. See -- `OverrideVar` and todomvc example to see one way to upstream -- changes into the larger state. -simpleList :: - forall a. Dynamic [a] -> - (Int -> DynVar a -> HTML ()) -> +simpleList :: forall a. + Dynamic [a] -> + (DynVar a -> HTML ()) -> HTML () -simpleList listDyn h = liftJSM do - internalStateRef <- liftIO $ newIORef ([] :: [ElemEnv a]) - brackets <- insertBrackets - let - exec brackets' scope = - localScope scope . customize (Ref brackets') - exec1 brackets' = customize (Ref brackets') - - setup :: Int -> [a] -> [ElemEnv a] -> JSM [ElemEnv a] - setup idx new existing = case (existing, new) of - ([], []) -> return [] +simpleList listDyn h = do + ref <- liftIO $ newIORef ([] :: [InternalElem a]) + place <- liftJSM insertPlaceholder + initial <- readDyn listDyn + liftJSM $ execHTML (Ref place) $ liftJSM $ updateList ref initial + liftJSM $ subscribe listDyn $ execHTML (Ref place) . liftJSM . updateList ref + where + synchronize :: [a] -> [InternalElem a] -> JSM [InternalElem a] + synchronize [] [] = return [] + synchronize (x:xs) [] = do -- New list is longer, append new elements - ([], x:xs) -> do - e <- newElem x - exec e.brackets e.elem_scope $ h idx e.state_var - fmap (e:) $ setup (idx + 1) xs [] + ie <- newElem x + localScope ie.elem_scope $ execHTML (Ref ie.placeholder) $ h ie.elem_state + fmap (ie:) $ synchronize xs [] + synchronize [] (r:rs) = do -- New list is shorter, delete the elements that no longer -- present in the new list - (r:rs, []) -> do - finalizeElems True (r:rs) - return [] + mapM_ dropElem (r:rs) + pure [] + synchronize (y:ys) (r:rs) = do -- Update existing elements along the way - (r:rs, y:ys) -> do - writeVar r.state_var y - fmap (r:) $ setup (idx + 1) ys rs - newElem :: a -> JSM (ElemEnv a) + writeVar r.elem_state y + fmap (r:) $ synchronize ys rs + newElem :: a -> JSM (InternalElem a) newElem a = do - elem_scope <- newScope - localScope elem_scope do - state_var <- newVar a - brackets' <- insertBrackets - return ElemEnv {elem_scope, state_var, brackets = brackets'} - finalizeElems :: Bool -> [ElemEnv a] -> JSM () - finalizeElems remove = mapM_ \ee -> do - when remove $ detachBrackets ee.brackets - destroyScope ee.elem_scope - updateList :: [a] -> JSM () - updateList new = do - eenvs <- liftIO $ readIORef internalStateRef - newEenvs <- setup 0 new eenvs - liftIO $ writeIORef internalStateRef newEenvs - initialVal <- readDyn listDyn - exec1 brackets $ liftJSM $ updateList initialVal - subscribe listDyn $ exec1 brackets . liftJSM . updateList - -insertBrackets :: JSM RefId -insertBrackets = do - brackets <- newRefId - jsCmd $ AssignRef brackets InsertBrackets - pure brackets - -clearBrackets :: RefId -> JSM () -clearBrackets rid = jsCmd $ ClearBrackets $ Ref rid - -detachBrackets :: RefId -> JSM () -detachBrackets rid = jsCmd $ DetachBrackets $ Ref rid - -customize :: JSExp -> HTML a -> JSM a -customize elm action = JSM \e -> do + scope <- newScope + localScope scope do + elem_state <- newVar a + place' <- insertPlaceholder + pure InternalElem {elem_scope = scope, elem_state, placeholder = place'} + dropElem :: InternalElem a -> JSM () + dropElem ie = do + destroyScope ie.elem_scope + detachPlaceholder ie.placeholder + updateList :: IORef [InternalElem a] -> [a] -> JSM () + updateList ref new = do + ies <- liftIO $ readIORef ref + ies' <- synchronize new ies + liftIO $ writeIORef ref ies' + +insertPlaceholder :: JSM RefId +insertPlaceholder = JSM \e -> do + ref <- newRefId.unJSM e + e.ien_command $ AssignRef e.ien_scope ref InsertPlaceholder + pure ref + +clearPlaceholder :: RefId -> JSM () +clearPlaceholder rid = jsCmd $ ClearPlaceholder $ Ref rid + +detachPlaceholder :: RefId -> JSM () +detachPlaceholder rid = jsCmd $ DetachPlaceholder $ Ref rid + +execHTML :: JSExp -> HTML a -> JSM a +execHTML elm action = JSM \e -> do e.ien_command $ PushStack elm (r, _) <- action.unHTML Nothing e e.ien_command PopStack diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index d6d2934..c7cbecb 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -196,48 +196,65 @@ newRefId = reactive newRefIdFn {-# INLINE newRefId #-} newRefIdFn :: ScopeId -> InternalState -> (InternalState, RefId) -newRefIdFn e s = (s {ist_id_supply = s.ist_id_supply + 1}, RefId e s.ist_id_supply) +newRefIdFn _e s = (s {ist_id_supply = s.ist_id_supply + 1}, RefId s.ist_id_supply) {-# INLINE newRefIdFn #-} freeScope :: ScopeId -> JSM () -freeScope s = do - mres <- state $ swap . freeScopeFn s - forM_ mres \r -> forM_ r.rsr_linked destroyScope - forM_ mres \r -> sequence_ r.rsr_finalizers -{-# INLINE freeScope #-} - -freeScopeFn :: ScopeId -> InternalState -> (InternalState, Maybe Resources) -freeScopeFn scope s = (s', resources) +freeScope scope = do + mres <- state updateState + forM_ mres \res -> do + forM_ (res.rsr_linked) destroyScope + sequence_ (res.rsr_finalizers) + jsCmd $ FreeScope scope where - subs = Map.map (List.filter filterSub) s.ist_subscriptions - filterSub sub = sub.sub_scope /= scope - (resources, rsr) = Map.alterF (,Nothing) scope s.ist_resources - s' = s {ist_subscriptions = subs, ist_resources = rsr} -{-# INLINE freeScopeFn #-} + updateState :: InternalState -> (Maybe Resources, InternalState) + updateState s = (res, s') + where + subs = Map.map (filter (not . isTargetScope)) s.ist_subscriptions + isTargetScope sub = sub.sub_scope == scope + (res, rsr) = Map.alterF (, Nothing) scope s.ist_resources + s' = s {ist_subscriptions = subs, ist_resources = rsr} destroyScope :: ScopeId -> JSM () -destroyScope s = do - mres <- state $ swap . destroyScopeFn s - forM_ mres \r -> forM_ r.rsr_linked destroyScope - forM_ mres \r -> sequence_ r.rsr_finalizers -{-# INLINE destroyScope #-} - -destroyScopeFn :: ScopeId -> InternalState -> (InternalState, Maybe Resources) -destroyScopeFn scope s = (s', resources) +destroyScope scope = do + mres <- state updateState + forM_ mres \res -> do + forM_ (res.rsr_linked) destroyScope + sequence_ (res.rsr_finalizers) + jsCmd $ FreeScope scope where - subs = Map.map (List.filter filterSub) s.ist_subscriptions - filterSub x = x.sub_scope /= scope - remove = Map.alterF (,Nothing) scope - unlink m = case resources of - Just r -> Map.adjust adj r.rsr_parent m - Nothing -> m - adj r = r {rsr_linked = List.filter (/=scope) r.rsr_linked} - (resources, rsr) = remove s.ist_resources - s' = s {ist_subscriptions = subs, ist_resources = unlink rsr} -{-# INLINE destroyScopeFn #-} + updateState :: InternalState -> (Maybe Resources, InternalState) + updateState s = (res, s') + where + subs = Map.map (filter (not . isTargetScope)) s.ist_subscriptions + isTargetScope sub = sub.sub_scope == scope + remove = Map.alterF (,Nothing) scope + unlink m = case res of + Just r -> Map.adjust adj r.rsr_parent m + Nothing -> m + adj r = r {rsr_linked = List.filter (/=scope) r.rsr_linked} + (res, rsr) = remove s.ist_resources + s' = s {ist_subscriptions = subs, ist_resources = unlink rsr} + +moveScope :: ScopeId -> ScopeId -> JSM () +moveScope src dest = do + modify updateState + jsCmd $ MoveScope src dest + where + updateState :: InternalState -> InternalState + updateState s + | Just srcRes <- Map.lookup src s.ist_resources = + s {ist_resources = Map.adjust (updateRes srcRes) dest s.ist_resources} + | otherwise = s + where + updateRes :: Resources -> Resources -> Resources + updateRes src' dest' = dest' { + rsr_linked = src'.rsr_linked <> dest'.rsr_linked, + rsr_finalizers = src'.rsr_finalizers <> dest'.rsr_finalizers + } installFinalizer :: JSM () -> JSM () -installFinalizer = reactive_ . installFinalizerFn +installFinalizer f = reactive_ $ installFinalizerFn f {-# INLINE installFinalizer #-} installFinalizerFn :: JSM () -> ScopeId -> InternalState -> InternalState diff --git a/Clickable/Types.hs b/Clickable/Types.hs index 0627490..4b868b5 100644 --- a/Clickable/Types.hs +++ b/Clickable/Types.hs @@ -127,10 +127,10 @@ data JSExp where Apply :: JSExp -> [JSExp] -> JSExp Call :: JSExp -> Text -> [JSExp] -> JSExp - AssignRef :: RefId -> JSExp -> JSExp - FreeRef :: RefId -> JSExp + AssignRef :: ScopeId -> RefId -> JSExp -> JSExp Ref :: RefId -> JSExp FreeScope :: ScopeId -> JSExp + MoveScope :: ScopeId -> ScopeId -> JSExp PeekStack :: Word8 -> JSExp PushStack :: JSExp -> JSExp @@ -141,9 +141,9 @@ data JSExp where ElementAttr :: JSExp -> Text -> Text -> JSExp ClassListAdd :: JSExp -> Text -> JSExp ClassListRemove :: JSExp -> Text -> JSExp - InsertBrackets :: JSExp - ClearBrackets :: JSExp -> JSExp - DetachBrackets :: JSExp -> JSExp + InsertPlaceholder :: JSExp + ClearPlaceholder :: JSExp -> JSExp + DetachPlaceholder :: JSExp -> JSExp CreateElement :: Text -> JSExp CreateElementNS :: Text -> Text -> JSExp @@ -175,9 +175,8 @@ newtype StartFlags = StartFlags {unStartFlags :: JSVal} newtype ScopeId = ScopeId {unScopeId :: Word32} deriving newtype (Binary, Eq, Ord, Show) -data RefId = RefId ScopeId Word32 - deriving stock (Eq, Show, Generic) - deriving anyclass (Binary) +newtype RefId = RefId {unRefId :: Word32} + deriving newtype (Binary, Eq, Ord, Show) newtype EventId = EventId {unEventId :: Word32} deriving newtype (Show, Ord, Eq, Binary) @@ -520,13 +519,15 @@ prompt (PromptTag t) (IO m) = IO (prompt# t m) control :: forall a b. PromptTag a -> ((IO b -> IO a) -> IO a) -> IO b control (PromptTag t) f = IO (control0# t g) where - g :: ((State# RealWorld -> (# State# RealWorld, b #)) - -> State# RealWorld -> (# State# RealWorld, a #)) - -> State# RealWorld -> (# State# RealWorld, a #) + g :: + ((State# RealWorld -> (# State# RealWorld, b #)) -> + State# RealWorld -> (# State# RealWorld, a #)) -> + State# RealWorld -> (# State# RealWorld, a #) g h = let IO m = f (k h) in m - k :: ((State# RealWorld -> (# State# RealWorld, b #)) - -> State# RealWorld -> (# State# RealWorld, a #)) - -> IO b -> IO a + k :: + ((State# RealWorld -> (# State# RealWorld, b #)) -> + State# RealWorld -> (# State# RealWorld, a #)) -> + IO b -> IO a k l (IO n) = IO (l n) data PromptTag a = PromptTag {unPromptTag :: PromptTag# a} diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index 0d607d3..c22f2e8 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -45,7 +45,7 @@ data ServerConfig = ServerConfig { } data ServerInstance = ServerInstance { - sri_dsc_websocket_state :: IORef (Map ConnectionId DevServerConn) + sri_websocket_state :: IORef (Map ConnectionId DevServerConn) } data TemplateConfig = TemplateConfig { @@ -72,9 +72,9 @@ newtype ConnectionId = ConnectionId {unConnectionId :: Int} newServer :: IO ServerInstance newServer = do - sri_dsc_websocket_state <- newIORef Map.empty + sri_websocket_state <- newIORef Map.empty pure ServerInstance { - sri_dsc_websocket_state + sri_websocket_state } waiApp :: ServerConfig -> ServerInstance -> Application @@ -108,7 +108,7 @@ websocketApp cfg self p = conn <- acceptRequest p newConn conn dropConn (conn::DevServerConn) = do - modifyIORef' self.sri_dsc_websocket_state $ Map.delete conn.dsc_connection_id + modifyIORef' self.sri_websocket_state $ Map.delete conn.dsc_connection_id cfg.cfg_connection_lost conn loop (conn::DevServerConn) = do raceResult <- race @@ -144,7 +144,7 @@ websocketApp cfg self p = (dsc_internal_env, _) <- newInternalEnv (100 * 1024) \(ptr, len) -> do bs <- unsafePackCStringLen (castPtr ptr, len) sendDataMessage dsc_websocket $ Network.WebSockets.Binary $ BSL.fromStrict bs - atomicModifyIORef' self.sri_dsc_websocket_state \m -> + atomicModifyIORef' self.sri_websocket_state \m -> let conn = DevServerConn { dsc_internal_env, dsc_websocket, @@ -201,4 +201,4 @@ defaultTemplate cfg = -- yarn run webpack --mode production && cat dist-newstyle/index.bundle.js | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' jsrts :: Builder jsrts = - "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeString(e,t),encodeValue(e,n)}))}function encodeString(e,t){const n=new Uint8Array(e.mem.buffer).subarray(e.begin+8),r=(new TextEncoder).encodeInto(t,n);e.mem.setBigUint64(e.begin,BigInt(r.written),!1),e.begin+=8+r.written}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.FreeRef=25]=\"FreeRef\",e[e.Ref=26]=\"Ref\",e[e.FreeScope=27]=\"FreeScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertBrackets=36]=\"InsertBrackets\",e[e.ClearBrackets=37]=\"ClearBrackets\",e[e.DetachBrackets=38]=\"DetachBrackets\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateText=41]=\"CreateText\",e[e.UpdateText=42]=\"UpdateText\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.Resume=45]=\"Resume\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"ContentBrackets {{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertBrackets=function(e){const n=document.createComment(\"ContentBrackets {{\"),r=document.createComment(\"}}\");return t(e,n),t(e,r),r},e.clearBrackets=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}))}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null,n){const r=new WebSocket(e),s={refs:(null==n?void 0:n.refs)||new Map,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.EventMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},resumeCont:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.ResumeMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))}};r.onopen=e=>{const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.StartMsg,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},r.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({context:s,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},r.onerror=e=>{console.error(\"WebSocket error:\",e)},r.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(5e3,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null,n){const r={refs:(null==n?void 0:n.refs)||new Map,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(){},resumeCont:function(){}},s=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]);function i(e,t){const n=new DataView(inst.exports.memory.buffer),s={context:Object.assign(Object.assign({},r),{resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)}}),mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:s.wasiImport,env:{clickable_eval_buffer:i}}))).then((e=>{inst=e,s.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}function evalUint8Array(e,t){const n={context:{refs:(null==t?void 0:t.refs)||new Map,stack:(null==t?void 0:t.stack)||null,triggerEvent:(null==t?void 0:t.triggerEvent)||function(){},resumeCont:(null==t?void 0:t.resumeCont)||function(){}},mem:new DataView(e.buffer),isMutableMem:!1,begin:0,end:e.byteLength};return proto.iQ(n)}function evalBase64(e,t){return evalUint8Array(Uint8Array.from(atob(e),(function(e){return e.charCodeAt(0)})),t)}window.clickable={runWebsocket,runWasm,evalUint8Array,evalBase64}})();" + "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,PG:()=>RefStore,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeString(e,t),encodeValue(e,n)}))}function encodeString(e,t){const n=new Uint8Array(e.mem.buffer).subarray(e.begin+8),r=(new TextEncoder).encodeInto(t,n);e.mem.setBigUint64(e.begin,BigInt(r.written),!1),e.begin+=8+r.written}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.Ref=25]=\"Ref\",e[e.FreeScope=26]=\"FreeScope\",e[e.MoveScope=27]=\"MoveScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertPlaceholder=36]=\"InsertPlaceholder\",e[e.ClearPlaceholder=37]=\"ClearPlaceholder\",e[e.DetachPlaceholder=38]=\"DetachPlaceholder\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateText=41]=\"CreateText\",e[e.UpdateText=42]=\"UpdateText\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.Resume=45]=\"Resume\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"Placeholder {{{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertPlaceholder=function(e){const n=document.createComment(\"Placeholder {{{\"),r=document.createComment(\"}}}\");return t(e,n),t(e,r),r},e.clearPlaceholder=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}));class RefStore{constructor(e=new Map,t=new Map){this.scopes=e,this.refs=t}assignRef(e,t,n){const r=this.scopes.get(e),s=r||new Set;r||this.scopes.set(e,s),s.add(t),this.refs.set(t,n)}moveScope(e,t){const n=this.scopes.get(e),r=this.scopes.get(t);n&&r&&(n.forEach((e=>r.add(e))),this.scopes.delete(e))}freeScope(e){const t=this.scopes.get(e);t&&(t.forEach((e=>this.refs.delete(e))),this.scopes.delete(e))}}}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null,n){const r=new WebSocket(e),s={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.EventMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},resumeCont:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.ResumeMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))}};r.onopen=e=>{const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.StartMsg,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},r.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({context:s,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},r.onerror=e=>{console.error(\"WebSocket error:\",e)},r.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(5e3,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null,n){const r={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(){},resumeCont:function(){}},s=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]);function i(e,t){const n=new DataView(inst.exports.memory.buffer),s={context:Object.assign(Object.assign({},r),{resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)}}),mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:s.wasiImport,env:{clickable_eval_buffer:i}}))).then((e=>{inst=e,s.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}function evalUint8Array(e,t){const n={context:{refs:(null==t?void 0:t.refs)||new proto.PG,stack:(null==t?void 0:t.stack)||null,triggerEvent:(null==t?void 0:t.triggerEvent)||function(){},resumeCont:(null==t?void 0:t.resumeCont)||function(){}},mem:new DataView(e.buffer),isMutableMem:!1,begin:0,end:e.byteLength};return proto.iQ(n)}function evalBase64(e,t){return evalUint8Array(Uint8Array.from(atob(e),(function(e){return e.charCodeAt(0)})),t)}window.clickable={runWebsocket,runWasm,evalUint8Array,evalBase64}})();" diff --git a/jsbits/misc.ts b/jsbits/misc.ts index 1dbf998..d9d5033 100644 --- a/jsbits/misc.ts +++ b/jsbits/misc.ts @@ -4,7 +4,7 @@ import * as proto from "./proto"; export function evalUint8Array(command: Uint8Array, options?: Partial): unknown { const context: EvalContext = { - refs: options?.refs || new Map(), + refs: options?.refs || new proto.RefStore(), stack: options?.stack || null, triggerEvent: options?.triggerEvent || function() {}, resumeCont: options?.resumeCont || function() {}, diff --git a/jsbits/proto.ts b/jsbits/proto.ts index 215a2af..80f8cbf 100644 --- a/jsbits/proto.ts +++ b/jsbits/proto.ts @@ -62,9 +62,9 @@ export enum ExprTag { Call, AssignRef, - FreeRef, Ref, FreeScope, + MoveScope, PeekStack, PushStack, @@ -75,9 +75,9 @@ export enum ExprTag { ElementAttr, ClassListAdd, ClassListRemove, - InsertBrackets, - ClearBrackets, - DetachBrackets, + InsertPlaceholder, + ClearPlaceholder, + DetachPlaceholder, CreateElement, CreateElementNS, @@ -116,9 +116,9 @@ export type Expr = | [ExprTag.Call, Expr, string, [Expr]] | [ExprTag.AssignRef, number, number, Expr] - | [ExprTag.FreeRef, number, number] - | [ExprTag.Ref, number, number] + | [ExprTag.Ref, number] | [ExprTag.FreeScope, number] + | [ExprTag.MoveScope, number, number] | [ExprTag.PeekStack, number] | [ExprTag.PushStack, Expr] @@ -129,9 +129,9 @@ export type Expr = | [ExprTag.ElementAttr, string, string] | [ExprTag.ClassListAdd, Expr, string[]] | [ExprTag.ClassListRemove, Expr, string[]] - | [ExprTag.InsertBrackets] - | [ExprTag.ClearBrackets, Expr] - | [ExprTag.DetachBrackets, Expr] + | [ExprTag.InsertPlaceholder] + | [ExprTag.ClearPlaceholder, Expr] + | [ExprTag.DetachPlaceholder, Expr] | [ExprTag.CreateElement, string] | [ExprTag.CreateElementNS, string, string] @@ -159,7 +159,7 @@ export type EvalState = { export type EvalContext = { readonly triggerEvent: (eventId: EventId, arg: unknown) => void; readonly resumeCont: (contId: number, res: unknown) => void; - readonly refs: Map>; + readonly refs: RefStore; stack: List; }; @@ -364,42 +364,29 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u }; case ExprTag.AssignRef: { - const scopeId = self.mem.getUint32(self.begin, false); - const refId = self.mem.getUint32(self.begin + 4, false); + const scope = self.mem.getUint32(self.begin, false); + const ref = self.mem.getUint32(self.begin + 4, false); self.begin += 8; const val = evalNext(self, args, prevRes); - if (self.context.refs.has(scopeId)) { - const scopeMap = self.context.refs.get(scopeId)!; - scopeMap.set(refId, val); - } else { - const scopeMap = new Map(); - scopeMap.set(refId, val); - self.context.refs.set(scopeId, scopeMap); - } + self.context.refs.assignRef(scope, ref, val); return val; }; - case ExprTag.FreeRef: { - const scopeId = self.mem.getUint32(self.begin, false); - const refId = self.mem.getUint32(self.begin + 4, false); - self.begin += 8; - const scopeMap = self.context.refs.get(scopeId); - if (!scopeMap) return null; - scopeMap.delete(refId); - if (scopeMap.size == 0) { - self.context.refs.delete(scopeId); - } - return null; - }; case ExprTag.Ref: { - const scopeId = self.mem.getUint32(self.begin, false); - const refId = self.mem.getUint32(self.begin + 4, false); - self.begin += 8; - return self.context.refs.get(scopeId)?.get(refId); + const ref = self.mem.getUint32(self.begin, false); + self.begin += 4; + return self.context.refs.refs.get(ref); }; case ExprTag.FreeScope: { - const scopeId = self.mem.getUint32(self.begin, false); + const scope = self.mem.getUint32(self.begin, false); self.begin += 4; - self.context.refs.delete(scopeId); + self.context.refs.freeScope(scope); + return null; + }; + case ExprTag.MoveScope: { + const src = self.mem.getUint32(self.begin, false); + const dest = self.mem.getUint32(self.begin + 4, false); + self.begin += 8; + self.context.refs.moveScope(src, dest); return null; }; @@ -468,21 +455,21 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u const className = decodeString(self); return el.classList.remove(className); }; - case ExprTag.InsertBrackets: { + case ExprTag.InsertPlaceholder: { if (!self.context.stack) { - throw new Error("InsertBrackets: empty stack"); + throw new Error("InsertPlaceholder: empty stack"); } const el = self.context.stack[VAL] as any; - return utils.insertBrackets(el); + return utils.insertPlaceholder(el); }; - case ExprTag.ClearBrackets: { + case ExprTag.ClearPlaceholder: { const node = evalNext(self, args, prevRes); - utils.clearBrackets(node as any, false); + utils.clearPlaceholder(node as any, false); return null; }; - case ExprTag.DetachBrackets: { + case ExprTag.DetachPlaceholder: { const node = evalNext(self, args, prevRes); - utils.clearBrackets(node as any, true); + utils.clearPlaceholder(node as any, true); return null; }; case ExprTag.CreateElement: { @@ -634,15 +621,15 @@ export function lookaheadNext(mem: DataView, ptr: Ptr): Ptr { case ExprTag.AssignRef: { return ptr + 8; }; - case ExprTag.FreeRef: { - return ptr + 8; - }; case ExprTag.Ref: { - return ptr + 8; + return ptr + 4; }; case ExprTag.FreeScope: { return ptr + 4; }; + case ExprTag.MoveScope: { + return ptr + 8; + }; case ExprTag.PeekStack: { return ptr + 1; @@ -675,13 +662,13 @@ export function lookaheadNext(mem: DataView, ptr: Ptr): Ptr { const newPtr0 = lookaheadNext(mem, ptr); return lookaheadString(mem, newPtr0); }; - case ExprTag.InsertBrackets: { + case ExprTag.InsertPlaceholder: { return ptr; }; - case ExprTag.ClearBrackets: { + case ExprTag.ClearPlaceholder: { return lookaheadNext(mem, ptr); }; - case ExprTag.DetachBrackets: { + case ExprTag.DetachPlaceholder: { return lookaheadNext(mem, ptr); }; case ExprTag.CreateElement: { @@ -873,31 +860,31 @@ namespace utils { element.removeEventListener(eventName, listener); } - export function insertBrackets(builder: Element|Comment): Comment { - const begin = document.createComment('ContentBrackets {{'); - const end = document.createComment('}}'); + export function insertPlaceholder(builder: Element|Comment): Comment { + const begin = document.createComment('Placeholder {{{'); + const end = document.createComment('}}}'); insert(builder, begin); insert(builder, end); return end; } - export function clearBrackets(bracket: Comment|Element, detach: boolean): void { - if (bracket instanceof Comment) { + export function clearPlaceholder(placeholder: Comment|Element, detach: boolean): void { + if (placeholder instanceof Comment) { let nestedCounter = 0; for (;;){ - if (!bracket.previousSibling || - (nestedCounter == 0 && isOpenBracket(bracket.previousSibling)) + if (!placeholder.previousSibling || + (nestedCounter == 0 && isOpenPlaceholder(placeholder.previousSibling)) ) break; - if (isClosingBracket(bracket.previousSibling)) nestedCounter++; - else if (isOpenBracket(bracket.previousSibling)) nestedCounter--; - bracket.previousSibling!.parentNode!.removeChild(bracket.previousSibling!); + if (isClosingPlaceholder(placeholder.previousSibling)) nestedCounter++; + else if (isOpenPlaceholder(placeholder.previousSibling)) nestedCounter--; + placeholder.previousSibling!.parentNode!.removeChild(placeholder.previousSibling!); } if (detach) { - bracket.previousSibling!.parentNode!.removeChild(bracket.previousSibling!); - bracket.parentNode!.removeChild(bracket); + placeholder.previousSibling!.parentNode!.removeChild(placeholder.previousSibling!); + placeholder.parentNode!.removeChild(placeholder); } } else { - bracket.innerHTML = ''; + placeholder.innerHTML = ''; } } @@ -908,17 +895,47 @@ namespace utils { return builder; } - function isOpenBracket(node: Node): boolean { - if (node instanceof Comment && node.textContent == 'ContentBrackets {{') { + function isOpenPlaceholder(node: Node): boolean { + if (node instanceof Comment && node.textContent == 'Placeholder {{{') { return true; } return false; } - function isClosingBracket(node: Node): boolean { - if (node instanceof Comment && node.textContent == '}}') { + function isClosingPlaceholder(node: Node): boolean { + if (node instanceof Comment && node.textContent == '}}}') { return true; } return false; } }; + +export class RefStore { + constructor( + public scopes = new Map>, + public refs = new Map, + ) {} + + assignRef(scope: ScopeId, refId: RefId, value: unknown) { + const refs0 = this.scopes.get(scope); + const refs1 = refs0 || new Set(); + if (!refs0) this.scopes.set(scope, refs1); + refs1.add(refId); + this.refs.set(refId, value); + } + + moveScope(src: ScopeId, dest: ScopeId) { + const srcRefs = this.scopes.get(src); + const destRefs = this.scopes.get(dest); + if (!srcRefs || !destRefs) return; + srcRefs.forEach(s => destRefs.add(s)); + this.scopes.delete(src); + } + + freeScope(scope: ScopeId) { + const refs = this.scopes.get(scope); + if (!refs) return; + refs.forEach(s => this.refs.delete(s)); + this.scopes.delete(scope); + } +} diff --git a/jsbits/wasm.ts b/jsbits/wasm.ts index f852de4..442c528 100644 --- a/jsbits/wasm.ts +++ b/jsbits/wasm.ts @@ -6,7 +6,7 @@ let inst: WebAssembly.Instance; export function runWasm(wasmUri: string, startFlags: unknown = null, options?: Partial) { const context: EvalContext = { - refs: options?.refs || new Map(), + refs: options?.refs || new proto.RefStore(), stack: options?.stack || null, triggerEvent: function() {}, resumeCont: function() {}, diff --git a/jsbits/websocket.ts b/jsbits/websocket.ts index 799c04c..2dd10ba 100644 --- a/jsbits/websocket.ts +++ b/jsbits/websocket.ts @@ -7,7 +7,7 @@ const mem = new DataView(outBuf); export function runWebsocket(devSocketUri: string, startFlags: unknown = null, options?: Partial) { const websocket = new WebSocket(devSocketUri); const context: EvalContext = { - refs: options?.refs || new Map(), + refs: options?.refs || new proto.RefStore(), stack: options?.stack || null, triggerEvent, resumeCont, From 4a454a3c0bf8e22555333f375397419f8f3fbf48 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Sat, 7 Dec 2024 22:51:49 +0400 Subject: [PATCH 62/64] TodoMVC --- .gitignore | 3 +- 9.6.5.nix | 2 +- Clickable/DOM.hs | 8 +- Clickable/HTML.hs | 21 +- Clickable/Internal.hs | 98 +++--- Clickable/Types.hs | 24 +- Clickable/{Wasm.hs => WASM.hs} | 54 +-- Clickable/WebSocket.hs | 49 +-- clickable.cabal | 23 +- examples/todomvc/App.hs | 36 ++ examples/todomvc/TodoItem.hs | 93 ++++++ examples/todomvc/TodoList.hs | 581 +++++++++++++++++++++++++++++++++ examples/todomvc/Utils.hs | 23 ++ examples/todomvc/wasm.hs | 10 + hie.yaml | 2 +- jsbits/proto.ts | 10 +- jsbits/wasm.ts | 81 ++++- package.json | 12 +- wasm.hs | 59 ---- websocket.hs | 63 ---- yarn.lock | 365 +++++++++++---------- 21 files changed, 1169 insertions(+), 448 deletions(-) rename Clickable/{Wasm.hs => WASM.hs} (56%) create mode 100644 examples/todomvc/App.hs create mode 100644 examples/todomvc/TodoItem.hs create mode 100644 examples/todomvc/TodoList.hs create mode 100644 examples/todomvc/Utils.hs create mode 100644 examples/todomvc/wasm.hs delete mode 100644 wasm.hs delete mode 100644 websocket.hs diff --git a/.gitignore b/.gitignore index 47c63dd..e1297b6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ bin/** shell.nix doc dist-newstyle -node_modules \ No newline at end of file +node_modules +build diff --git a/9.6.5.nix b/9.6.5.nix index 340b5e3..59c60c2 100644 --- a/9.6.5.nix +++ b/9.6.5.nix @@ -3,7 +3,7 @@ let nixpkgs = builtins.fetchTarball { url = "https://github.com/NixOS/nixpkgs/archive/refs/tags/24.05.tar.gz"; }; - ghc-wasm-meta = "gitlab:ghc/ghc-wasm-meta?host=gitlab.haskell.org&ref=108e4693cd147777e8d93683e58c8a5e1da74c96"; + ghc-wasm-meta = "gitlab:ghc/ghc-wasm-meta?host=gitlab.haskell.org&ref=455a759195e71c572e73b56d868e544176d32897"; }; pkgs = import sources.nixpkgs {}; diff --git a/Clickable/DOM.hs b/Clickable/DOM.hs index 7f87e4d..d07c7db 100644 --- a/Clickable/DOM.hs +++ b/Clickable/DOM.hs @@ -11,12 +11,12 @@ {-# OPTIONS_GHC -Wall #-} module Clickable.DOM where -import Data.Text (Text) -import GHC.Generics (Generic) +import Clickable.Internal import Clickable.Types -import Data.Kind import Data.Int -import Clickable.Internal +import Data.Kind +import Data.Text (Text) +import GHC.Generics (Generic) import Unsafe.Coerce diff --git a/Clickable/HTML.hs b/Clickable/HTML.hs index f81d937..1b2900e 100644 --- a/Clickable/HTML.hs +++ b/Clickable/HTML.hs @@ -95,15 +95,15 @@ toggleClass className dynEnable = HTML \s e -> do pure ((), s') {-# INLINE toggleClass #-} -attachTo :: JSExp -> HTML a -> JSM a -attachTo rootEl contents = JSM \e -> do - e.ien_command $ PushStack rootEl - (r, _) <- contents.unHTML Nothing e +execHTML :: JSExp -> HTML a -> JSM a +execHTML elm action = JSM \e -> do + e.ien_command $ PushStack elm + (r, _) <- action.unHTML Nothing e e.ien_command PopStack pure r -attach :: HTML a -> JSM a -attach = attachTo $ Id "document" `Dot` "body" +execHTMLBody :: HTML a -> JSM a +execHTMLBody = execHTML $ Id "document" `Dot` "body" saveStackHead :: HTML RefId saveStackHead = HTML \s e -> @@ -181,8 +181,8 @@ simpleList listDyn h = do pure InternalElem {elem_scope = scope, elem_state, placeholder = place'} dropElem :: InternalElem a -> JSM () dropElem ie = do - destroyScope ie.elem_scope detachPlaceholder ie.placeholder + destroyScope ie.elem_scope updateList :: IORef [InternalElem a] -> [a] -> JSM () updateList ref new = do ies <- liftIO $ readIORef ref @@ -200,10 +200,3 @@ clearPlaceholder rid = jsCmd $ ClearPlaceholder $ Ref rid detachPlaceholder :: RefId -> JSM () detachPlaceholder rid = jsCmd $ DetachPlaceholder $ Ref rid - -execHTML :: JSExp -> HTML a -> JSM a -execHTML elm action = JSM \e -> do - e.ien_command $ PushStack elm - (r, _) <- action.unHTML Nothing e - e.ien_command PopStack - pure r diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index c7cbecb..d5e827a 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -13,18 +13,21 @@ import Control.Monad.State.Strict import Data.Binary qualified as Binary import Data.Binary.Put (execPut) import Data.ByteString.Builder.Extra (runBuilder, Next (..), BufferWriter) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) import Data.Functor.Const import Data.IORef import Data.List qualified as List import Data.Map qualified as Map +import Data.Maybe import Data.Text (Text) import Data.Tuple (swap) import Foreign.C.String (CStringLen) +import Foreign.Marshal (copyBytes) import Foreign.Marshal.Alloc (mallocBytes) import Foreign.Ptr import GHC.Exts +import GHC.Stack import Unsafe.Coerce -import Data.Maybe newEvent :: JSM (Event a) newEvent = state \s -> @@ -359,11 +362,30 @@ jsCmd cmd = JSM \e -> jsEval :: JSExp -> JSM JSVal jsEval cmd = JSM \e -> do e.ien_command cmd - e.ien_flush + eid <- atomicModifyIORef' e.ien_state nextId + control e.ien_prompt_tag \c -> do + let jsc :: IO JSVal -> JSM () + jsc a = JSM \_ -> c a + sub = Subscription e.ien_scope (unsafeCoerce jsc) + modifyIORef' e.ien_state \s -> s { + ist_subscriptions = Map.insert eid [sub] s.ist_subscriptions + } + e.ien_command $ Resume eid Out + e.ien_flush + where + nextId s = (s {ist_id_supply = s.ist_id_supply + 1}, EventId s.ist_id_supply) {-# INLINE jsEval #-} jsFlush :: JSM () jsFlush = JSM \e -> void $ e.ien_flush +{-# INLINE jsFlush #-} + +jsUnsafe :: (HasCallStack, FromJSVal a) => UnsafeJavaScript -> JSM a +jsUnsafe ujs = do + j <- jsEval (Eval ujs) + case fromJSVal j of + Just a -> pure a + Nothing -> error "jsUnsafe: fromJSVal failed" commandBuffer :: CStringLen -> (CStringLen -> IO ()) -> IO (JSExp -> IO (), IO ()) commandBuffer (buf, bufSize) consume = do @@ -380,31 +402,17 @@ commandBuffer (buf, bufSize) consume = do writeCommand :: BufferWriter -> Int -> IO Int writeCommand bufWrite off = do (written, next) <- bufWrite (buf `plusPtr` off) (bufSize - off) - let off' = off + written - case next of - Done -> pure off' - More minSize _moreWrite - | off == 0 -> - error $ "Buffer too small, encountered command that requires at \ - \least " <> show minSize <> " bytes" - | otherwise -> do - consume (castPtr buf, off) - writeRemains bufWrite 0 - Chunk chunk moreWrite -> do - off1 <- writeRemains (runBuilder $ execPut $ Binary.put chunk) off - writeRemains moreWrite off1 - - writeRemains :: BufferWriter -> Int -> IO Int - writeRemains bufWrite off = do - (written, next) <- bufWrite (buf `plusPtr` off) (bufSize - off) - let off' = off + written - case next of - Done -> pure off' - More _minSize _moreWrite -> - error $ "Buffer too small, inscrease the buffer size" - Chunk chunk moreWrite -> do - off1 <- writeRemains (runBuilder $ execPut $ Binary.put chunk) off - writeRemains moreWrite off1 + writeNext next $ off + written + + writeNext :: Next -> Int -> IO Int + writeNext Done off = pure off + writeNext (More minSize _) _off = + error $ "Buffer too small, encountered command that requires at \ + \least " <> show minSize <> " bytes" + writeNext (Chunk chunk more) off = + unsafeUseAsCStringLen chunk \(zs, len) -> do + copyBytes (buf `plusPtr` off) zs len + writeCommand more (off + len) flush :: IORef Int -> IO () flush ref = do @@ -414,24 +422,18 @@ commandBuffer (buf, bufSize) consume = do newInternalEnv :: Int -> (CStringLen -> IO ()) -> IO (InternalEnv, CStringLen) newInternalEnv bufSize consume = do buf <- mallocBytes bufSize - ien_state <- newIORef emptyState - (write, flush) <- commandBuffer (buf, bufSize) consume - ien_prompt_tag <- newPromptTag - ien_continuations <- newIORef Map.empty - let bufResult = (castPtr buf, bufSize) - pure ( - InternalEnv { - ien_command = write, - ien_flush = do - tid <- atomicModifyIORef' ien_state \s -> - (s {ist_id_supply = s.ist_id_supply + 1}, ContId s.ist_id_supply) - write $ Resume tid - flush - control ien_prompt_tag \c -> - modifyIORef' ien_continuations $ Map.insert tid c, - ien_state, - ien_scope = ScopeId 0, - ien_prompt_tag, - ien_continuations - }, bufResult - ) + let strLen = (castPtr buf, bufSize) + ienv <- mkEnv buf + pure (ienv, strLen) + where + mkEnv buf = do + ien_prompt_tag <- newPromptTag + ien_state <- newIORef emptyState + (write, flush) <- commandBuffer (buf, bufSize) consume + pure InternalEnv { + ien_command = write, + ien_flush = flush, + ien_state, + ien_scope = ScopeId 0, + ien_prompt_tag + } diff --git a/Clickable/Types.hs b/Clickable/Types.hs index 4b868b5..1c8dd22 100644 --- a/Clickable/Types.hs +++ b/Clickable/Types.hs @@ -32,6 +32,7 @@ import GHC.Generics qualified as G import GHC.List qualified as List import GHC.Types import GHC.Generics +import Control.Monad.Fix newtype JSM a = JSM {unJSM :: InternalEnv -> IO a} deriving ( @@ -39,7 +40,8 @@ newtype JSM a = JSM {unJSM :: InternalEnv -> IO a} Applicative, Monad, MonadIO, - MonadReader InternalEnv + MonadReader InternalEnv, + MonadFix ) via ReaderT InternalEnv IO instance MonadState InternalState JSM where @@ -55,11 +57,10 @@ class MonadJSM m where data InternalEnv = InternalEnv { ien_command :: JSExp -> IO (), - ien_flush :: IO JSVal, + ien_flush :: IO (), ien_state :: IORef InternalState, ien_scope :: ScopeId, - ien_prompt_tag :: PromptTag (), - ien_continuations :: IORef (Map ContId (IO JSVal -> IO ())) + ien_prompt_tag :: PromptTag () } data InternalState = InternalState { @@ -85,7 +86,8 @@ newtype HTML a = HTML {unHTML :: Maybe RefId -> InternalEnv -> IO (a, Maybe RefI Functor, Applicative, Monad, - MonadIO + MonadIO, + MonadFix ) via StateT (Maybe RefId) JSM instance MonadJSM HTML where @@ -152,7 +154,8 @@ data JSExp where Eval :: UnsafeJavaScript -> JSExp TriggerEvent :: EventId -> JSExp -> JSExp - Resume :: ContId -> JSExp + Resume :: EventId -> JSExp -> JSExp + Out :: JSExp deriving stock (Generic, Show) deriving anyclass Binary @@ -160,8 +163,8 @@ data JSExp where data ClientMsg where StartMsg :: StartFlags -> ClientMsg EventMsg :: EventId -> JSExp -> ClientMsg - ResumeMsg :: ContId -> JSExp -> ClientMsg - deriving stock Generic + ResumeMsg :: EventId -> JSExp -> ClientMsg + deriving stock (Generic, Show) deriving anyclass Binary -- | JavaScript value, result of evaluating an 'JSExp'. Should only @@ -170,7 +173,7 @@ data ClientMsg where type JSVal = JSExp newtype StartFlags = StartFlags {unStartFlags :: JSVal} - deriving newtype Binary + deriving newtype (Binary, Show) newtype ScopeId = ScopeId {unScopeId :: Word32} deriving newtype (Binary, Eq, Ord, Show) @@ -181,9 +184,6 @@ newtype RefId = RefId {unRefId :: Word32} newtype EventId = EventId {unEventId :: Word32} deriving newtype (Show, Ord, Eq, Binary) -newtype ContId = ContId {unContId :: Word32} - deriving newtype (Show, Ord, Eq, Binary) - newtype UnsafeJavaScript = UnsafeJavaScript {unUnsafeJavaScript :: Text} deriving newtype (IsString, Show, Semigroup, Monoid, Binary) diff --git a/Clickable/Wasm.hs b/Clickable/WASM.hs similarity index 56% rename from Clickable/Wasm.hs rename to Clickable/WASM.hs index d5303f3..700011b 100644 --- a/Clickable/Wasm.hs +++ b/Clickable/WASM.hs @@ -1,6 +1,5 @@ {-# LANGUAGE GHC2024 #-} {-# LANGUAGE StrictData #-} -{-# LANGUAGE CPP #-} {-# LANGUAGE BlockArguments #-} {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE LambdaCase #-} @@ -9,24 +8,27 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE UnboxedTuples #-} {-# OPTIONS_GHC -Wno-unused-do-bind #-} -module Clickable.Wasm where +{-# OPTIONS_GHC -Wall #-} +module Clickable.WASM where import Clickable.Internal import Clickable.Types -import Control.Monad import Data.Binary (Binary) +import Data.Binary qualified as Binary import Data.ByteString (ByteString) -import Data.IORef +import Data.ByteString.Lazy qualified as BSL +import Data.ByteString.Unsafe qualified as BSU import Data.Word +import Foreign.C.String (CStringLen) import Foreign.Ptr import System.IO.Unsafe (unsafePerformIO) -import qualified Data.Binary as Binary -import qualified Data.ByteString.Lazy as BSL -import qualified Data.ByteString.Unsafe as BSU -import qualified Data.Map as Map -import Data.Tuple (swap) -import Data.Map (Map) -import Foreign.C.String (CStringLen) +import GHC.Exts +import Data.Map qualified as Map +import Data.Maybe (fromMaybe) +import Data.IORef +import Control.Monad +import Unsafe.Coerce +import System.IO foreign import ccall safe "clickable_eval_buffer" clickable_eval_buffer :: Ptr Word8 -> Int -> IO () @@ -34,34 +36,34 @@ foreign import ccall safe env :: InternalEnv {-# NOINLINE env #-} -continuations :: IORef (Map Word32 (IO JSVal -> IO ())) -{-# NOINLINE continuations #-} - buf :: CStringLen {-# NOINLINE buf #-} -(env, continuations, buf) = unsafePerformIO $ +(env, buf) = unsafePerformIO $ newInternalEnv (100 * 1024) \(ptr, len) -> clickable_eval_buffer (castPtr ptr) len -mkWasmApp :: JSM () -> Ptr Word8 -> IO (Ptr Word8) -mkWasmApp app p | p == nullPtr = do - runTransition env app +mkWasmApp :: (StartFlags -> JSM ()) -> Ptr Word8 -> IO (Ptr Word8) +mkWasmApp _app p | p == nullPtr = do + hSetBuffering stdout LineBuffering + hSetBuffering stderr LineBuffering return $ castPtr $ fst buf mkWasmApp app inmsg = do msg <- loadMessage inmsg $ snd buf case msg of - Just (StartMsg _flags) -> - runTransition env app + Just (StartMsg flags) -> + runJSM env $ app flags Just (EventMsg eventId pload) -> - runTransition env $ - triggerEvent (unsafeFromEventId eventId) pload + runJSM env $ triggerEvent (unsafeFromEventId eventId) pload Just (ResumeMsg contId pload) -> do - awatingThread <- atomicModifyIORef' continuations $ - swap . Map.alterF (,Nothing) contId - forM_ awatingThread \cont -> cont $ pure pload + cont <- atomicModifyIORef' env.ien_state $ lookupCont $ coerce contId + forM_ cont \c -> runJSM env $ c.sub_callback $ unsafeCoerce $ ((pure pload) :: IO JSVal) _ -> error "mkWasmApp: Failed to parse incomming command" - return $ castPtr $ fst buf + pure $ castPtr $ fst buf + where + lookupCont :: EventId -> InternalState -> (InternalState, [Subscription Any]) + lookupCont eventId s = (s {ist_subscriptions = subs}, fromMaybe [] cont) where + (cont, subs) = Map.alterF (,Nothing) eventId $ s.ist_subscriptions loadMessage :: Binary msg => Ptr a -> Int -> IO (Maybe msg) loadMessage p len diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index c22f2e8..b5e16c5 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -16,7 +16,6 @@ import Control.Concurrent import Control.Concurrent.Async (race) import Control.Exception import Control.Monad -import Control.Monad.State.Strict (modify) import Data.Binary qualified as Binary import Data.Binary.Builder ( Builder ) import Data.ByteString (ByteString) @@ -25,7 +24,6 @@ import Data.ByteString.Unsafe (unsafePackCStringLen) import Data.IORef import Data.Map (Map) import Data.Map qualified as Map -import Data.Tuple import Foreign.Ptr import GHC.IO.Exception import Network.HTTP.Types @@ -35,13 +33,16 @@ import Network.Wai.Handler.Warp qualified as Warp import Network.Wai.Handler.WebSockets import Network.WebSockets import System.IO +import GHC.Exts +import Data.Maybe +import Unsafe.Coerce data ServerConfig = ServerConfig { cfg_template :: TemplateConfig -> Builder, cfg_docroots :: [FilePath], cfg_client :: DevServerConn -> StartFlags -> JSM (), - cfg_connection_lost :: DevServerConn -> IO (), - cfg_middleware :: Middleware + cfg_middleware :: Middleware, + cfg_warp :: Warp.Settings } data ServerInstance = ServerInstance { @@ -64,9 +65,13 @@ data DevServerConn = DevServerConn { dsc_internal_env :: InternalEnv, -- | Writing to the Chan sends a command to the browser to execute dsc_command_chan :: Chan (JSM ()), - dsc_connection_id :: ConnectionId + dsc_connection_id :: ConnectionId, + dsc_resources :: IORef (Map ReleaseKey (IO ())) } +newtype ReleaseKey = ReleaseKey {unReleaseKey :: Int} + deriving newtype (Ord, Show, Eq, Num, Enum) + newtype ConnectionId = ConnectionId {unConnectionId :: Int} deriving newtype (Ord, Show, Eq, Num, Enum) @@ -109,7 +114,8 @@ websocketApp cfg self p = newConn conn dropConn (conn::DevServerConn) = do modifyIORef' self.sri_websocket_state $ Map.delete conn.dsc_connection_id - cfg.cfg_connection_lost conn + resources <- atomicModifyIORef' conn.dsc_resources (Map.empty,) + sequence_ resources loop (conn::DevServerConn) = do raceResult <- race (try @ConnectionException (receiveData conn.dsc_websocket)) @@ -129,11 +135,9 @@ websocketApp cfg self p = reader conn (Right (StartMsg flags)) = void $ runJSM conn.dsc_internal_env $ cfg.cfg_client conn flags - reader conn (Right (ResumeMsg contId pload)) = - prompt conn.dsc_internal_env.ien_prompt_tag do - awatingThread <- atomicModifyIORef' conn.dsc_internal_env.ien_continuations $ - swap . Map.alterF (,Nothing) contId - forM_ awatingThread \cont -> cont $ pure pload + reader conn (Right (ResumeMsg contId pload)) = do + cont <- atomicModifyIORef' conn.dsc_internal_env.ien_state $ lookupCont $ coerce contId + forM_ cont \c -> runJSM conn.dsc_internal_env $ c.sub_callback $ unsafeCoerce $ ((pure pload) :: IO JSVal) reader conn (Right (EventMsg eid arg)) = void $ runJSM conn.dsc_internal_env $ triggerEvent (unsafeFromEventId eid) arg reader conn (Left a) = @@ -141,18 +145,24 @@ websocketApp cfg self p = newConn dsc_websocket = do dsc_command_chan <- newChan - (dsc_internal_env, _) <- newInternalEnv (100 * 1024) \(ptr, len) -> do + (dsc_internal_env, _) <- newInternalEnv (10000 * 1024) \(ptr, len) -> do bs <- unsafePackCStringLen (castPtr ptr, len) sendDataMessage dsc_websocket $ Network.WebSockets.Binary $ BSL.fromStrict bs + dsc_resources <- newIORef Map.empty atomicModifyIORef' self.sri_websocket_state \m -> let conn = DevServerConn { dsc_internal_env, dsc_websocket, dsc_command_chan, - dsc_connection_id = maybe 0 (succ . fst) $ Map.lookupMax m + dsc_connection_id = maybe 0 (succ . fst) $ Map.lookupMax m, + dsc_resources } in (Map.insert conn.dsc_connection_id conn m, conn) + lookupCont :: EventId -> InternalState -> (InternalState, [Subscription Any]) + lookupCont eventId s = (s {ist_subscriptions = subs}, fromMaybe [] cont) where + (cont, subs) = Map.alterF (,Nothing) eventId $ s.ist_subscriptions + tryPorts :: Warp.Settings -> Application -> IO () tryPorts set app = do hPutStrLn stderr $ "Development Server is running at http://localhost:" <> @@ -172,17 +182,14 @@ runDefault client = runConfig cfg_template = defaultTemplate, cfg_docroots = [], cfg_client = const $ const client, - cfg_connection_lost = const $ pure (), - cfg_middleware = Prelude.id + cfg_middleware = Prelude.id, + cfg_warp = Warp.defaultSettings } runConfig :: ServerConfig -> IO () -runConfig = runConfig' Warp.defaultSettings - -runConfig' :: Warp.Settings -> ServerConfig -> IO () -runConfig' set cfg = do +runConfig cfg = do self <- newServer - tryPorts set $ cfg.cfg_middleware $ waiApp cfg self + tryPorts cfg.cfg_warp $ cfg.cfg_middleware $ waiApp cfg self defaultTemplate :: TemplateConfig -> Builder defaultTemplate cfg = @@ -201,4 +208,4 @@ defaultTemplate cfg = -- yarn run webpack --mode production && cat dist-newstyle/index.bundle.js | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' jsrts :: Builder jsrts = - "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,PG:()=>RefStore,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeString(e,t),encodeValue(e,n)}))}function encodeString(e,t){const n=new Uint8Array(e.mem.buffer).subarray(e.begin+8),r=(new TextEncoder).encodeInto(t,n);e.mem.setBigUint64(e.begin,BigInt(r.written),!1),e.begin+=8+r.written}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.Ref=25]=\"Ref\",e[e.FreeScope=26]=\"FreeScope\",e[e.MoveScope=27]=\"MoveScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertPlaceholder=36]=\"InsertPlaceholder\",e[e.ClearPlaceholder=37]=\"ClearPlaceholder\",e[e.DetachPlaceholder=38]=\"DetachPlaceholder\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateText=41]=\"CreateText\",e[e.UpdateText=42]=\"UpdateText\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.Resume=45]=\"Resume\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"Placeholder {{{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertPlaceholder=function(e){const n=document.createComment(\"Placeholder {{{\"),r=document.createComment(\"}}}\");return t(e,n),t(e,r),r},e.clearPlaceholder=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}));class RefStore{constructor(e=new Map,t=new Map){this.scopes=e,this.refs=t}assignRef(e,t,n){const r=this.scopes.get(e),s=r||new Set;r||this.scopes.set(e,s),s.add(t),this.refs.set(t,n)}moveScope(e,t){const n=this.scopes.get(e),r=this.scopes.get(t);n&&r&&(n.forEach((e=>r.add(e))),this.scopes.delete(e))}freeScope(e){const t=this.scopes.get(e);t&&(t.forEach((e=>this.refs.delete(e))),this.scopes.delete(e))}}}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null,n){const r=new WebSocket(e),s={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.EventMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},resumeCont:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.ResumeMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))}};r.onopen=e=>{const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.StartMsg,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},r.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({context:s,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},r.onerror=e=>{console.error(\"WebSocket error:\",e)},r.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(5e3,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null,n){const r={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(){},resumeCont:function(){}},s=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]);function i(e,t){const n=new DataView(inst.exports.memory.buffer),s={context:Object.assign(Object.assign({},r),{resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)}}),mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:s.wasiImport,env:{clickable_eval_buffer:i}}))).then((e=>{inst=e,s.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}function evalUint8Array(e,t){const n={context:{refs:(null==t?void 0:t.refs)||new proto.PG,stack:(null==t?void 0:t.stack)||null,triggerEvent:(null==t?void 0:t.triggerEvent)||function(){},resumeCont:(null==t?void 0:t.resumeCont)||function(){}},mem:new DataView(e.buffer),isMutableMem:!1,begin:0,end:e.byteLength};return proto.iQ(n)}function evalBase64(e,t){return evalUint8Array(Uint8Array.from(atob(e),(function(e){return e.charCodeAt(0)})),t)}window.clickable={runWebsocket,runWasm,evalUint8Array,evalBase64}})();" + "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,PG:()=>RefStore,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeString(e,t),encodeValue(e,n)}))}function encodeString(e,t){const n=new Uint8Array(e.mem.buffer).subarray(e.begin+8),r=(new TextEncoder).encodeInto(t,n);e.mem.setBigUint64(e.begin,BigInt(r.written),!1),e.begin+=8+r.written}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.Ref=25]=\"Ref\",e[e.FreeScope=26]=\"FreeScope\",e[e.MoveScope=27]=\"MoveScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertPlaceholder=36]=\"InsertPlaceholder\",e[e.ClearPlaceholder=37]=\"ClearPlaceholder\",e[e.DetachPlaceholder=38]=\"DetachPlaceholder\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateText=41]=\"CreateText\",e[e.UpdateText=42]=\"UpdateText\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.Resume=45]=\"Resume\",e[e.Out=46]=\"Out\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"Placeholder {{{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertPlaceholder=function(e){const n=document.createComment(\"Placeholder {{{\"),r=document.createComment(\"}}}\");return t(e,n),t(e,r),r},e.clearPlaceholder=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}));class RefStore{constructor(e=new Map,t=new Map){this.scopes=e,this.refs=t}assignRef(e,t,n){const r=this.scopes.get(e),s=r||new Set;r||this.scopes.set(e,s),s.add(t),this.refs.set(t,n)}moveScope(e,t){const n=this.scopes.get(e),r=this.scopes.get(t);n&&r&&(n.forEach((e=>r.add(e))),this.scopes.delete(e))}freeScope(e){const t=this.scopes.get(e);t&&(t.forEach((e=>this.refs.delete(e))),this.scopes.delete(e))}}}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null,n){const r=new WebSocket(e),s={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.EventMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},resumeCont:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.ResumeMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))}};r.onopen=e=>{const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.StartMsg,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},r.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({context:s,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},r.onerror=e=>{console.error(\"WebSocket error:\",e)},r.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(5e3,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null,n){const r={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(){},resumeCont:function(){}},s=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]);function i(e,t){const n=new DataView(inst.exports.memory.buffer),s={context:Object.assign(Object.assign({},r),{resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)}}),mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:s.wasiImport,env:{clickable_eval_buffer:i}}))).then((e=>{inst=e,s.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}function evalUint8Array(e,t){const n={context:{refs:(null==t?void 0:t.refs)||new proto.PG,stack:(null==t?void 0:t.stack)||null,triggerEvent:(null==t?void 0:t.triggerEvent)||function(){},resumeCont:(null==t?void 0:t.resumeCont)||function(){}},mem:new DataView(e.buffer),isMutableMem:!1,begin:0,end:e.byteLength};return proto.iQ(n)}function evalBase64(e,t){return evalUint8Array(Uint8Array.from(atob(e),(function(e){return e.charCodeAt(0)})),t)}window.clickable={runWebsocket,runWasm,evalUint8Array,evalBase64}})();" diff --git a/clickable.cabal b/clickable.cabal index d517300..abc1b95 100644 --- a/clickable.cabal +++ b/clickable.cabal @@ -16,15 +16,20 @@ executable clickable main-is: websocket.hs hs-source-dirs: ./ other-modules: - Clickable - Clickable.Element - Clickable.Binary - Clickable.DOM - Clickable.HTML - Clickable.Internal - Clickable.Property - Clickable.Types - Clickable.WebSocket + Clickable + Clickable.Element + Clickable.Binary + Clickable.DOM + Clickable.HTML + Clickable.Internal + Clickable.Property + Clickable.Types + if !arch(wasm32) + other-modules: + Clickable.WebSocket + if arch(javascript) + other-modules: + Clickable.WASM -- other-extensions: build-depends: async, diff --git a/examples/todomvc/App.hs b/examples/todomvc/App.hs new file mode 100644 index 0000000..b610a25 --- /dev/null +++ b/examples/todomvc/App.hs @@ -0,0 +1,36 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# OPTIONS_GHC -Wall #-} +module App where + +import Data.Maybe +import Clickable + +import TodoList qualified as TodoList +import Utils +import TodoItem (TodoItemState(TodoItemState)) + +app :: StartFlags -> JSM () +app _ = do + items <- fromMaybe [] <$> readLocalStorage "todo-items" + stateVar <- TodoList.new items + installFinalizer do + s <- readVar stateVar + saveLocalStorage "todo-items" s.items + execHTMLBody do + el "style" $ text TodoList.styles + TodoList.view TodoList.TodoListConfig {self = stateVar} + liftJSM $ addEventListener popstateEvent \loc -> do + let f = fromMaybe TodoList.All $ TodoList.parseFilter loc.loc_hash + modifyVar_ stateVar \s -> s {TodoList.filter = f} + + +app1 :: StartFlags -> JSM () +app1 _ = do + items :: [TodoItemState] <- fromMaybe [] <$> readLocalStorage "todo-items" + execHTMLBody do + h1_ "sdfsdfsdfsd" diff --git a/examples/todomvc/TodoItem.hs b/examples/todomvc/TodoItem.hs new file mode 100644 index 0000000..1a85c24 --- /dev/null +++ b/examples/todomvc/TodoItem.hs @@ -0,0 +1,93 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE RecursiveDo #-} +{-# OPTIONS_GHC -Wall #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE GADTs #-} +module TodoItem where + +import Clickable +import Data.Maybe +import Data.Text (Text) +import GHC.Int +import GHC.Generics + +import Utils + +data TodoItemConfig = TodoItemConfig { + self :: DynVar TodoItemState, + is_hidden_dyn :: Dynamic Bool, + ask_delete_item :: JSM () +} + +data TodoItemState = TodoItemState { + title :: Text, + completed :: Bool, + editing :: Maybe Text +} deriving stock (Show, Eq, Generic) + deriving anyclass (FromJSVal, ToJSVal) + +data TodoItemAction a where + CancelAction :: TodoItemAction () + CommitAction :: TodoItemAction () + InputAction :: Text -> TodoItemAction () + DoubleClickAction :: RefId -> TodoItemAction () + CheckedAction :: Bool -> TodoItemAction () + KeydownAction :: Int32 -> TodoItemAction () + +emptyState :: TodoItemState +emptyState = TodoItemState "" False Nothing + +eval :: TodoItemConfig -> TodoItemAction a -> JSM a +eval cfg CancelAction = + modifyVar_ cfg.self \s -> s{editing=Nothing} +eval cfg CommitAction = do + state <- readVar cfg.self + case state.editing of + Just "" -> + cfg.ask_delete_item + Just t -> + modifyVar_ cfg.self \s -> s {editing=Nothing, title = t} + Nothing -> + pure () +eval cfg (InputAction newVal) = + modifyVar_ cfg.self \s -> s{editing = Just newVal} +eval cfg (DoubleClickAction inpElm) = do + modifyVar_ cfg.self \s -> s {editing = Just s.title} + assignFocus inpElm +eval cfg (CheckedAction isChecked) = + modifyVar_ cfg.self \s -> s{completed = isChecked} +eval cfg (KeydownAction key) = case key of + 13 {- Enter -} -> eval cfg CommitAction + 27 {- Escape -} -> eval cfg CancelAction + _ -> return () + +view :: TodoItemConfig -> HTML () +view cfg = li_ mdo + let completedDyn = (.completed) <$> fromVar cfg.self + editingDyn = isJust . (.editing) <$> fromVar cfg.self + valueDyn = fromMaybe "" . (.editing) <$> fromVar cfg.self + toggleClass "completed" completedDyn + toggleClass "editing" editingDyn + toggleClass "hidden" cfg.is_hidden_dyn + div_ [class_ "view"] do + on @"dblclick" $ eval cfg $ DoubleClickAction inp + input_ [class_ "toggle", type_ "checkbox"] do + dynChecked $ (.completed) <$> fromVar cfg.self + on @"checkbox/change" $ eval cfg . CheckedAction + label_ $ dynText $ (.title) <$> fromVar cfg.self + button_ [class_ "destroy"] do + on @"click" cfg.ask_delete_item + inp <- input_ [class_ "edit", type_ "text"] do + dynValue valueDyn + on @"input" $ eval cfg . InputAction + on @"keydown" $ eval cfg . KeydownAction + on @"blur" $ eval cfg CommitAction + saveStackHead + return () diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs new file mode 100644 index 0000000..ddc54fe --- /dev/null +++ b/examples/todomvc/TodoList.hs @@ -0,0 +1,581 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE RecursiveDo #-} +{-# OPTIONS_GHC -Wall #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE GADTs #-} +module TodoList where + +import Clickable +import Control.Monad +import Data.List qualified as List +import Data.Text (Text) +import Data.Text qualified as Text +import GHC.Int + +import TodoItem qualified as TodoItem + + +data TodoListConfig = TodoListConfig { + self :: DynVar TodoListState +} + +data TodoListState = TodoListState { + title :: Text, + items :: [TodoItem.TodoItemState], + filter :: Filter +} deriving (Show, Eq) + +data Filter = All | Active | Completed + deriving (Show, Eq) + +new :: [TodoItem.TodoItemState] -> JSM (DynVar TodoListState) +new items = + newVar TodoListState { + title = "", + items = items, + filter = All + } + +view :: TodoListConfig -> HTML () +view cfg = do + div_ do + section_ [class_ "todoapp"] do + headerWidget + mainWidget + footerWidget + footerInfoWidget + where + headerWidget = header_ [class_ "header"] do + h1_ (text "todos") + input_ [class_ "new-todo", placeholder_ "What needs to be done?", autofocus_ True] do + dynValue $ (.title) <$> fromVar cfg.self + on @"input" $ eval cfg . InputAction + on @"keydown" $ eval cfg . KeydownAction + mainWidget = section_ [class_ "main"] do + toggleClass "hidden" hiddenDyn + input_ [id_ "toggle-all", class_ "toggle-all", type_ "checkbox"] do + on @"checkbox/change" $ eval cfg . ToggleAllAction + label_ do + attribute "for" "toggle-all" + text "Mark all as completed" + ul_ [class_ "todo-list"] do + simpleList itemsDyn \todoRef -> + TodoItem.view TodoItem.TodoItemConfig { + self = lensMap (_2) $ overrideVar (todoItemUpdated cfg) todoRef, + is_hidden_dyn = liftA2 isHidden (fromVar cfg.self) (fromVar todoRef), + ask_delete_item = eval cfg . DeleteItemAction . fst =<< readVar todoRef + } + footerWidget = footer_ [class_ "footer"] do + toggleClass "hidden" hiddenDyn + span_ [class_ "todo-count"] do + strong_ $ dynText $ Text.pack . show <$> itemsLeftDyn + dynText $ pluralize " item left" " items left" <$> itemsLeftDyn + ul_ [class_ "filters"] do + forM_ [All, Active, Completed] filterWidget + button_ [class_ "clear-completed"] do + on @"click" $ eval cfg ClearCompletedAction + text "Clear completed" + footerInfoWidget = footer_ [class_ "info"] do + p_ "Double-click to edit a todo" + p_ do + text "Created by " + a_ [href_ "https://github.com/lagunoff"] "Vlad Lagunov" + p_ do + text "Part of " + a_ [href_ "http://todomvc.com"] "TodoMVC" + filterWidget :: Filter -> HTML () + filterWidget flt = li_ do + a_ [href_ (printFilter flt)] do + toggleClass "selected" $ filterSelectedDyn flt + text $ Text.pack $ show flt + hiddenDyn = + Prelude.null . (.items) <$> fromVar cfg.self + itemsLeftDyn = + countItemsLeft <$> fromVar cfg.self + filterSelectedDyn flt = + (==flt) . (.filter) <$> fromVar cfg.self + itemsDyn :: Dynamic [(Int, TodoItem.TodoItemState)] + itemsDyn = (\s -> zip [0..] s.items) <$> fromVar cfg.self + countItemsLeft TodoListState{items} = + foldl (\acc TodoItem.TodoItemState{completed} -> + if not completed then acc + 1 else acc) 0 items + isHidden :: TodoListState -> (Int, TodoItem.TodoItemState) -> Bool + isHidden listState (_, itemState) = + case (listState.filter, itemState.completed) of + (Active, True) -> True + (Completed, False) -> True + _ -> False + +data TodoListAction a where + ToggleAllAction :: Bool -> TodoListAction () + InputAction :: Text -> TodoListAction () + CommitAction :: TodoListAction () + KeydownAction :: Int32 -> TodoListAction () + DeleteItemAction :: Int -> TodoListAction () + ClearCompletedAction :: TodoListAction () + +eval :: TodoListConfig -> TodoListAction a -> JSM a +eval cfg (ToggleAllAction isChecked) = + modifyVar_ cfg.self \s -> s { + items = fmap (\i -> i {TodoItem.completed = isChecked}) s.items + } +eval cfg (InputAction newVal) = + modifyVar_ cfg.self \s -> s {title = newVal} +eval cfg CommitAction = do + title <- Text.strip . (.title) <$> readVar cfg.self + case title of + "" -> return () + t -> modifyVar_ cfg.self \s -> s { + items = s.items <> [newTodo t], + title = "" + } + where + newTodo t = TodoItem.emptyState {TodoItem.title = t} +eval cfg (KeydownAction key) = case key of + 13 {- Enter -} -> eval cfg CommitAction + _ -> return () +eval cfg (DeleteItemAction itemIx) = + modifyVar_ cfg.self \s -> s {items = deleteIx itemIx s.items} + where + deleteIx :: Int -> [a] -> [a] + deleteIx _ [] = [] + deleteIx i (a:as) | i == 0 = as | otherwise = a : deleteIx (i-1) as +eval cfg ClearCompletedAction = + modifyVar_ cfg.self \s -> s + {items = (List.filter (not . TodoItem.completed)) s.items} + +-- | Synchronize TodoItem state with the larger state of TodoList +-- widget. +todoItemUpdated :: + TodoListConfig -> + UpdateFn (Int, TodoItem.TodoItemState) -> + UpdateFn (Int, TodoItem.TodoItemState) +todoItemUpdated cfg next f = do + -- Update the local TodoItemState + ((s, s'), result) <- next g + -- Filter out irrelevant updates + let needPropagateUpdate = (snd s).completed /= (snd s').completed + -- Update the same item in the larger TodoListState + if needPropagateUpdate + then modifyVar cfg.self $ h s' + else modifyVarQuiet cfg.self $ h s' + pure result + where + g s = let (s', a) = f s in (s', ((s, s'), a)) + h (i, e) s = (s {items = updateIx i e s.items}, ()) + + updateIx :: Int -> a -> [a] -> [a] + updateIx 0 a (_:xs) = a : xs + updateIx n a (x:xs) = x : updateIx (pred n) a xs + updateIx _ _ [] = [] + +pluralize :: Text -> Text -> Int -> Text +pluralize singular _plural 0 = singular +pluralize _singular plural _ = plural + +parseFilter :: Text -> Maybe Filter +parseFilter "#/" = Just All +parseFilter "#/active" = Just Active +parseFilter "#/completed" = Just Completed +parseFilter _ = Nothing + +printFilter :: Filter -> Text +printFilter All = "#/" +printFilter Active = "#/active" +printFilter Completed = "#/completed" + +-- TODO: rewrite without lenses +_2 :: Lens' (a, b) b +_2 f a = fmap (setter a) (f (getter a)) + where + setter (a', _) c = (a', c) + getter (_, b) = b + +styles :: Text +styles = "\ + \body {\ + \ margin: 0;\ + \ padding: 0 ;\ + \}\ + \\ + \button {\ + \ margin: 0;\ + \ padding: 0;\ + \ border: 0;\ + \ background: none;\ + \ font-size: 100%;\ + \ vertical-align: baseline;\ + \ font-family: inherit;\ + \ font-weight: inherit;\ + \ color: inherit;\ + \ -webkit-appearance: none;\ + \ appearance: none;\ + \ -webkit-font-smoothing: antialiased;\ + \ -moz-osx-font-smoothing: grayscale;\ + \}\ + \\ + \body {\ + \ font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;\ + \ line-height: 1.4em;\ + \ background: #f5f5f5;\ + \ color: #4d4d4d;\ + \ min-width: 230px;\ + \ max-width: 550px;\ + \ margin: 0 auto;\ + \ -webkit-font-smoothing: antialiased;\ + \ -moz-osx-font-smoothing: grayscale;\ + \ font-weight: 300;\ + \}\ + \\ + \:focus {\ + \ outline: 0;\ + \}\ + \\ + \.hidden {\ + \ display: none;\ + \}\ + \\ + \.todoapp {\ + \ background: #fff;\ + \ margin: 130px 0 40px 0;\ + \ position: relative;\ + \ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),\ + \ 0 25px 50px 0 rgba(0, 0, 0, 0.1);\ + \}\ + \\ + \.todoapp input::-webkit-input-placeholder {\ + \ font-style: italic;\ + \ font-weight: 300;\ + \ color: #e6e6e6;\ + \}\ + \\ + \.todoapp input::-moz-placeholder {\ + \ font-style: italic;\ + \ font-weight: 300;\ + \ color: #e6e6e6;\ + \}\ + \\ + \.todoapp input::input-placeholder {\ + \ font-style: italic;\ + \ font-weight: 300;\ + \ color: #e6e6e6;\ + \}\ + \\ + \.todoapp h1 {\ + \ position: absolute;\ + \ top: -155px;\ + \ width: 100%;\ + \ font-size: 100px;\ + \ font-weight: 100;\ + \ text-align: center;\ + \ color: rgba(175, 47, 47, 0.15);\ + \ -webkit-text-rendering: optimizeLegibility;\ + \ -moz-text-rendering: optimizeLegibility;\ + \ text-rendering: optimizeLegibility;\ + \}\ + \\ + \.new-todo,\ + \.edit {\ + \ position: relative;\ + \ margin: 0;\ + \ width: 100%;\ + \ font-size: 24px;\ + \ font-family: inherit;\ + \ font-weight: inherit;\ + \ line-height: 1.4em;\ + \ border: 0;\ + \ color: inherit;\ + \ padding: 6px;\ + \ border: 1px solid #999;\ + \ box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);\ + \ box-sizing: border-box;\ + \ -webkit-font-smoothing: antialiased;\ + \ -moz-osx-font-smoothing: grayscale;\ + \}\ + \\ + \.new-todo {\ + \ padding: 16px 16px 16px 60px;\ + \ border: none;\ + \ background: rgba(0, 0, 0, 0.003);\ + \ box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);\ + \}\ + \\ + \.main {\ + \ position: relative;\ + \ z-index: 2;\ + \ border-top: 1px solid #e6e6e6;\ + \}\ + \\ + \.toggle-all {\ + \ width: 1px;\ + \ height: 1px;\ + \ border: none; /* Mobile Safari */\ + \ opacity: 0;\ + \ position: absolute;\ + \ right: 100%;\ + \ bottom: 100%;\ + \}\ + \\ + \.toggle-all + label {\ + \ width: 60px;\ + \ height: 34px;\ + \ font-size: 0;\ + \ position: absolute;\ + \ top: -52px;\ + \ left: -13px;\ + \ -webkit-transform: rotate(90deg);\ + \ transform: rotate(90deg);\ + \}\ + \\ + \.toggle-all + label:before {\ + \ content: '❯';\ + \ font-size: 22px;\ + \ color: #e6e6e6;\ + \ padding: 10px 27px 10px 27px;\ + \}\ + \\ + \.toggle-all:checked + label:before {\ + \ color: #737373;\ + \}\ + \\ + \.todo-list {\ + \ margin: 0;\ + \ padding: 0;\ + \ list-style: none;\ + \}\ + \\ + \.todo-list li {\ + \ position: relative;\ + \ font-size: 24px;\ + \ border-bottom: 1px solid #ededed;\ + \}\ + \\ + \.todo-list li:last-child {\ + \ border-bottom: none;\ + \}\ + \\ + \.todo-list li.editing {\ + \ border-bottom: none;\ + \ padding: 0;\ + \}\ + \\ + \.todo-list li.editing .edit {\ + \ display: block;\ + \ width: calc(100% - 43px);\ + \ padding: 12px 16px;\ + \ margin: 0 0 0 43px;\ + \}\ + \\ + \.todo-list li.editing .view {\ + \ display: none;\ + \}\ + \\ + \.todo-list li .toggle {\ + \ text-align: center;\ + \ width: 40px;\ + \ /* auto, since non-WebKit browsers doesn't support input styling */\ + \ height: auto;\ + \ position: absolute;\ + \ top: 0;\ + \ bottom: 0;\ + \ margin: auto 0;\ + \ border: none; /* Mobile Safari */\ + \ -webkit-appearance: none;\ + \ appearance: none;\ + \}\ + \\ + \.todo-list li .toggle {\ + \ opacity: 0;\ + \}\ + \\ + \.todo-list li .toggle + label {\ + \ /*\ + \ Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433\ + \ IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/\ + \ */\ + \ background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');\ + \ background-repeat: no-repeat;\ + \ background-position: center left;\ + \}\ + \\ + \.todo-list li .toggle:checked + label {\ + \ background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');\ + \}\ + \\ + \.todo-list li label {\ + \ word-break: break-all;\ + \ padding: 15px 15px 15px 60px;\ + \ display: block;\ + \ line-height: 1.2;\ + \ transition: color 0.4s;\ + \}\ + \\ + \.todo-list li.completed label {\ + \ color: #d9d9d9;\ + \ text-decoration: line-through;\ + \}\ + \\ + \.todo-list li .destroy {\ + \ display: none;\ + \ position: absolute;\ + \ top: 0;\ + \ right: 10px;\ + \ bottom: 0;\ + \ width: 40px;\ + \ height: 40px;\ + \ margin: auto 0;\ + \ font-size: 30px;\ + \ color: #cc9a9a;\ + \ margin-bottom: 11px;\ + \ transition: color 0.2s ease-out;\ + \}\ + \\ + \.todo-list li .destroy:hover {\ + \ color: #af5b5e;\ + \}\ + \\ + \.todo-list li .destroy:after {\ + \ content: '×';\ + \}\ + \\ + \.todo-list li:hover .destroy {\ + \ display: block;\ + \}\ + \\ + \.todo-list li .edit {\ + \ display: none;\ + \}\ + \\ + \.todo-list li.editing:last-child {\ + \ margin-bottom: -1px;\ + \}\ + \\ + \.footer {\ + \ color: #777;\ + \ padding: 10px 15px;\ + \ height: 20px;\ + \ text-align: center;\ + \ border-top: 1px solid #e6e6e6;\ + \}\ + \\ + \.footer:before {\ + \ content: '';\ + \ position: absolute;\ + \ right: 0;\ + \ bottom: 0;\ + \ left: 0;\ + \ height: 50px;\ + \ overflow: hidden;\ + \ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),\ + \ 0 8px 0 -3px #f6f6f6,\ + \ 0 9px 1px -3px rgba(0, 0, 0, 0.2),\ + \ 0 16px 0 -6px #f6f6f6,\ + \ 0 17px 2px -6px rgba(0, 0, 0, 0.2);\ + \}\ + \\ + \.todo-count {\ + \ float: left;\ + \ text-align: left;\ + \}\ + \\ + \.todo-count strong {\ + \ font-weight: 300;\ + \}\ + \\ + \.filters {\ + \ margin: 0;\ + \ padding: 0;\ + \ list-style: none;\ + \ position: absolute;\ + \ right: 0;\ + \ left: 0;\ + \}\ + \\ + \.filters li {\ + \ display: inline;\ + \}\ + \\ + \.filters li a {\ + \ color: inherit;\ + \ margin: 3px;\ + \ padding: 3px 7px;\ + \ text-decoration: none;\ + \ border: 1px solid transparent;\ + \ border-radius: 3px;\ + \}\ + \\ + \.filters li a:hover {\ + \ border-color: rgba(175, 47, 47, 0.1);\ + \}\ + \\ + \.filters li a.selected {\ + \ border-color: rgba(175, 47, 47, 0.2);\ + \}\ + \\ + \.clear-completed,\ + \html .clear-completed:active {\ + \ float: right;\ + \ position: relative;\ + \ line-height: 20px;\ + \ text-decoration: none;\ + \ cursor: pointer;\ + \}\ + \\ + \.clear-completed:hover {\ + \ text-decoration: underline;\ + \}\ + \\ + \.info {\ + \ margin: 65px auto 0;\ + \ color: #bfbfbf;\ + \ font-size: 10px;\ + \ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\ + \ text-align: center;\ + \}\ + \\ + \.info p {\ + \ line-height: 1;\ + \}\ + \\ + \.info a {\ + \ color: inherit;\ + \ text-decoration: none;\ + \ font-weight: 400;\ + \}\ + \\ + \.info a:hover {\ + \ text-decoration: underline;\ + \}\ + \\ + \/*\ + \ Hack to remove background from Mobile Safari.\ + \ Can't use it globally since it destroys checkboxes in Firefox\ + \*/\ + \@media screen and (-webkit-min-device-pixel-ratio:0) {\ + \ .toggle-all,\ + \ .todo-list li .toggle {\ + \ background: none;\ + \ }\ + \\ + \ .todo-list li .toggle {\ + \ height: 40px;\ + \ }\ + \}\ + \\ + \@media (max-width: 430px) {\ + \ .footer {\ + \ height: 50px;\ + \ }\ + \\ + \ .filters {\ + \ bottom: 10px;\ + \ }\ + \}" diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs new file mode 100644 index 0000000..308af2d --- /dev/null +++ b/examples/todomvc/Utils.hs @@ -0,0 +1,23 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE OverloadedStrings #-} +{-# OPTIONS_GHC -Wall #-} +module Utils where + +import Data.Text (Text) +import Clickable + +readLocalStorage :: FromJSVal v => Text -> JSM (Maybe v) +readLocalStorage key = do + let jsonParse e = Call (Id "JSON") "parse" [e] + val <- jsEval $ jsonParse $ Call (Id "localStorage") "getItem" [Str key] + return $ fromJSVal val + +saveLocalStorage :: ToJSVal v => Text -> v -> JSM () +saveLocalStorage key val = do + let stringify s = Call (Id "JSON") "stringify" [toJSVal s] + jsCmd $ Call (Id "localStorage") "setItem" [Str key, stringify val] + +assignFocus :: RefId -> JSM () +assignFocus elm = jsCmd $ Call (Ref elm) "focus" [] diff --git a/examples/todomvc/wasm.hs b/examples/todomvc/wasm.hs new file mode 100644 index 0000000..d208273 --- /dev/null +++ b/examples/todomvc/wasm.hs @@ -0,0 +1,10 @@ +import Clickable.WASM +import GHC.Ptr +import GHC.Word +import App + +main :: IO () +main = return () + +foreign export ccall wasm_app :: Ptr Word8 -> IO (Ptr Word8) +wasm_app = mkWasmApp app diff --git a/hie.yaml b/hie.yaml index 8245581..ddfc1ba 100644 --- a/hie.yaml +++ b/hie.yaml @@ -1,3 +1,3 @@ cradle: direct: - arguments: [] + arguments: [-i./examples/todomvc] diff --git a/jsbits/proto.ts b/jsbits/proto.ts index 80f8cbf..13dc0ab 100644 --- a/jsbits/proto.ts +++ b/jsbits/proto.ts @@ -87,6 +87,7 @@ export enum ExprTag { Eval, TriggerEvent, Resume, + Out, } /** Encode `Expr` type as a union of disjoint n-tuples, keep in @@ -140,7 +141,8 @@ export type Expr = | [ExprTag.Eval, string] | [ExprTag.TriggerEvent, number, Expr] - | [ExprTag.Resume, number] + | [ExprTag.Resume, number, Expr] + | [ExprTag.Out] ; export type Ptr = number; @@ -505,9 +507,13 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u case ExprTag.Resume: { const contId = self.mem.getUint32(self.begin, false); self.begin += 4; - self.context.resumeCont(contId, prevRes); + const pload = evalNext(self, args, prevRes); + self.context.resumeCont(contId, pload); return null; }; + case ExprTag.Out: { + return prevRes; + }; } } diff --git a/jsbits/wasm.ts b/jsbits/wasm.ts index 442c528..6b4ca59 100644 --- a/jsbits/wasm.ts +++ b/jsbits/wasm.ts @@ -11,19 +11,28 @@ export function runWasm(wasmUri: string, startFlags: unknown = null, options?: P triggerEvent: function() {}, resumeCont: function() {}, }; + // const stdout = new OpenFile(new File([])); + // const stderr = new OpenFile(new File([])); + const stdout = new OpenFileDebug(new File([]), consoleLineBuffering(console.log)); + const stderr = new OpenFileDebug(new File([]), consoleLineBuffering(console.log)); + // @ts-ignore + window['stdout'] = stdout; + // @ts-ignore + window['stderr'] = stderr; const wasi = new WASI([], [], [ new OpenFile(new File([])), // stdin - new OpenFile(new File([])), // stdout - new OpenFile(new File([])), // stderr + stdout as any, + stderr as any, ]); function clickable_eval_buffer(ptr: Ptr, len: number): void { // @ts-ignore - const mem = new DataView(inst.exports.memory.buffer); const context1 = {...context, resumeCont, triggerEvent} function triggerEvent(eventId: EventId, arg: unknown) { + // @ts-ignore + const mem = new DataView(inst.exports.memory.buffer); const encoderState = {mem, begin: ptr, end: ptr + len}; proto.encodeClientMessage(encoderState, [ClientMsgTag.EventMsg, eventId, arg]); // @ts-ignore @@ -31,12 +40,16 @@ export function runWasm(wasmUri: string, startFlags: unknown = null, options?: P }; function resumeCont(contId: number, res: unknown) { + // @ts-ignore + const mem = new DataView(inst.exports.memory.buffer); const encoderState = {mem, begin: ptr, end: ptr + len}; proto.encodeClientMessage(encoderState, [ClientMsgTag.ResumeMsg, contId, res]); // @ts-ignore inst.exports.wasm_app(ptr); }; + // @ts-ignore + const mem = new DataView(inst.exports.memory.buffer); const intp: EvalState = { context: context1, mem, @@ -48,11 +61,18 @@ export function runWasm(wasmUri: string, startFlags: unknown = null, options?: P proto.evalMem(intp); } + function console_log(ptr: Ptr, len: number): void { + // @ts-ignore + const strView = new Uint8Array(inst.exports.memory.buffer).subarray(ptr, ptr + len); + return console.log(new TextDecoder('utf8').decode(strView)); + } + WebAssembly.compileStreaming(fetch(wasmUri)) .then(wasm => WebAssembly.instantiate(wasm, { wasi_snapshot_preview1: wasi.wasiImport, env: { clickable_eval_buffer, + console_log, }, })) .then(inst1 => { @@ -62,6 +82,59 @@ export function runWasm(wasmUri: string, startFlags: unknown = null, options?: P // @ts-ignore inst1.exports.hs_init(); // @ts-ignore - inst1.exports.wasm_app(0); + const buf: number = inst1.exports.wasm_app(0); + // @ts-ignore + const mem = new DataView(inst1.exports.memory.buffer); + const encoderState = {mem, begin: buf, end: buf + (1024 * 100)}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.StartMsg, startFlags]); + // @ts-ignore + inst1.exports.wasm_app(buf); }); }; + +export class OpenFileDebug extends OpenFile { + public printDebug: (s: Uint8Array) => void; + + constructor(file: File, printDebug: (s: Uint8Array) => void) { + super(file); + this.printDebug = printDebug; + } + + fd_write(data: Uint8Array): { + ret: number; + nwritten: number; + } { + this.printDebug(data); + return super.fd_write(data); + } + + fd_pwrite(data: Uint8Array, offset: bigint): { + ret: number; + nwritten: number; + } { + this.printDebug(data.subarray(Number(offset))); + return super.fd_pwrite(data, offset); + } +} + +// Split given chunks of memory into lines and pass decoded strings +// into the given logger function, buffer unfinished lines if neccessary +function consoleLineBuffering(logger: (s: string) => void): (u8: Uint8Array) => void { + let buffer: Uint8Array[] = []; + return (u8: Uint8Array) => { + const go = (bytes: Uint8Array) => { + if (bytes.byteLength == 0) return; + const newLineIndex = bytes.findIndex(b => b == '\n'.charCodeAt(0)); + if (newLineIndex >= 0) { + const olderBits = buffer.map(u8s => new TextDecoder('utf8').decode(u8s)).join(''); + buffer = []; + const lastBits = new TextDecoder('utf8').decode(bytes.subarray(0, newLineIndex)); + logger(olderBits + lastBits); + go(bytes.subarray(newLineIndex + 1)); + } else { + buffer.push(bytes.slice()); + } + }; + go(u8); + }; +} diff --git a/package.json b/package.json index 5a362d5..13b391b 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "dependencies": { - "@bjorn3/browser_wasi_shim": "^0.3.0", - "ts-loader": "^9.5.1", - "tslib": "^2.7.0", - "typescript": "^5.6.2", - "webpack": "^5.95.0", - "webpack-cli": "^5.1.4" + "@bjorn3/browser_wasi_shim": "0.3.0", + "ts-loader": "*", + "tslib": "*", + "typescript": "*", + "webpack": "*", + "webpack-cli": "*" } } diff --git a/wasm.hs b/wasm.hs deleted file mode 100644 index e96122d..0000000 --- a/wasm.hs +++ /dev/null @@ -1,59 +0,0 @@ -{-# OPTIONS_GHC -Wno-unused-local-binds #-} -{-# LANGUAGE BlockArguments #-} -{-# LANGUAGE RecursiveDo #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE OverloadedRecordDot #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE StrictData #-} -{-# OPTIONS_GHC -Wno-unused-do-bind #-} -{-# LANGUAGE DataKinds #-} -module Main where - -import Clickable.HTML -import Clickable.Internal -import Clickable.Types -import qualified Data.Text as Text -import Clickable.Wasm -import Data.Word -import Foreign (Ptr) -import Data.IORef -import Control.Monad.Reader - -test01 :: JSM () -test01 = do - jsCmd $ PushStack $ Id "document" `Dot` "body" - counter <- newVar 0 - el "div" do - prop "className" (Str "container") - text "Lorem Ipsum" - el "h1" $ text "Fox jumps over a lazy dog" - el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" - el "button" do - text "Click Here" - on @"click" $ modifyVar_ counter succ - el "button" do - text "-" - on @"click" $ modifyVar_ counter pred - el "br" $ pure () - el "span" do - dynText $ fmap (Text.pack . show) $ fromVar counter - ref <- liftIO $ newIORef $ const $ pure () - el "div" do - el "button" do - text "Ask a Value" - on @"click" do - t <- asks (.ien_prompt_tag) - val <- liftIO $ control t \cont -> writeIORef ref cont - jsCmd $ Call (Id "console") "log" $ valueToExpr val - el "button" do - text "Fill the value" - on @"click" do - cont <- liftIO $ readIORef ref - liftIO $ cont $ pure $ Vobj [("this", Vstr "is"), ("some", Vstr "value")] - -main :: IO () -main = pure () - -foreign export ccall wasm_app :: Ptr Word8 -> IO (Ptr Word8) -wasm_app :: Ptr Word8 -> IO (Ptr Word8) -wasm_app = mkWasmApp test01 diff --git a/websocket.hs b/websocket.hs deleted file mode 100644 index 0776963..0000000 --- a/websocket.hs +++ /dev/null @@ -1,63 +0,0 @@ -{-# LANGUAGE GHC2021 #-} -{-# LANGUAGE BlockArguments #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE OverloadedRecordDot #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE RecursiveDo #-} -module Main where - -import Clickable.Html -import Clickable.Internal -import Clickable.Types -import Clickable.WebSocket -import Control.Monad.IO.Class -import Control.Monad.Reader -import Data.IORef -import Network.Wai.Handler.Warp (run) -import Unsafe.Coerce (unsafeCoerce) -import qualified Data.Text as Text - -test01 :: JSM () -test01 = do - counter <- newVar @Int 0 - attachToBody do - el "div" do - prop "className" (Str "container") - text "Lorem Ipsum" - el "h1" $ text "Fox jumps over a lazy dog" - el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" - el "button" do - text "Click Here" - on @"click" $ modifyVar_ counter succ - el "button" do - text "-" - on @"click" $ modifyVar_ counter pred - el "br" $ pure () - el "span" do - dynText $ fmap (Text.pack . show) $ fromVar counter - ref <- liftIO $ newIORef $ const $ pure () - el "div" do - el "button" do - text "Ask a Value" - on @"click" do - t <- asks (.ien_prompt_tag) - val <- liftIO $ control t \cont -> writeIORef ref cont - jsCmd $ Call (Id "console") "log" [val] - el "button" do - text "Fill the value" - on @"click" do - cont <- liftIO $ readIORef ref - liftIO $ cont $ pure $ Obj [("this", Str "is"), ("some", Str "value")] - -main :: IO () -main = do - run 3000 $ runApp test01 - -baz :: IO Int -baz = do - let z :: Int = unsafeCoerce False - return $ z * 2 - -bar :: Int -> Int -bar dsfsd = dsfsd diff --git a/yarn.lock b/yarn.lock index 954fb59..266fd8e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@bjorn3/browser_wasi_shim@^0.3.0": +"@bjorn3/browser_wasi_shim@0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@bjorn3/browser_wasi_shim/-/browser_wasi_shim-0.3.0.tgz#8aa310eed2298bab435bd1f73ab100fbc3f018da" integrity sha512-FlRBYttPRLcWORzBe6g8nmYTafBkOEFeOqMYM4tAHJzFsQy4+xJA94z85a9BCs8S+Uzfh9LrkpII7DXr2iUVFg== @@ -52,142 +52,158 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@types/estree@^1.0.5": +"@types/eslint-scope@^3.7.7": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" + integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== -"@types/json-schema@^7.0.8": +"@types/json-schema@*", "@types/json-schema@^7.0.8": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/node@*": - version "22.7.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" - integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== - dependencies: - undici-types "~6.19.2" - -"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" - integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - -"@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== - -"@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== - -"@webassemblyjs/helper-buffer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" - integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== - -"@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" + version "22.10.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.1.tgz#41ffeee127b8975a05f8c4f83fb89bcb2987d766" + integrity sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ== + dependencies: + undici-types "~6.20.0" + +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" + integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== + dependencies: + "@webassemblyjs/helper-numbers" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + +"@webassemblyjs/floating-point-hex-parser@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" + integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA== + +"@webassemblyjs/helper-api-error@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" + integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ== + +"@webassemblyjs/helper-buffer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" + integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA== + +"@webassemblyjs/helper-numbers@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" + integrity sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.13.2" + "@webassemblyjs/helper-api-error" "1.13.2" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== +"@webassemblyjs/helper-wasm-bytecode@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" + integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA== -"@webassemblyjs/helper-wasm-section@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" - integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== +"@webassemblyjs/helper-wasm-section@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" + integrity sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw== dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/wasm-gen" "1.14.1" -"@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== +"@webassemblyjs/ieee754@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" + integrity sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== +"@webassemblyjs/leb128@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" + integrity sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== - -"@webassemblyjs/wasm-edit@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" - integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-opt" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - "@webassemblyjs/wast-printer" "1.12.1" - -"@webassemblyjs/wasm-gen@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" - integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wasm-opt@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" - integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - -"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" - integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-api-error" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - -"@webassemblyjs/wast-printer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" - integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== - dependencies: - "@webassemblyjs/ast" "1.12.1" +"@webassemblyjs/utf8@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" + integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ== + +"@webassemblyjs/wasm-edit@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" + integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/helper-wasm-section" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-opt" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + "@webassemblyjs/wast-printer" "1.14.1" + +"@webassemblyjs/wasm-gen@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" + integrity sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wasm-opt@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" + integrity sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" + integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-api-error" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wast-printer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" + integrity sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw== + dependencies: + "@webassemblyjs/ast" "1.14.1" "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^2.1.1": @@ -215,15 +231,10 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -acorn-import-attributes@^1.9.5: - version "1.9.5" - resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" - integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== - -acorn@^8.7.1, acorn@^8.8.2: - version "8.12.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" - integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== +acorn@^8.14.0, acorn@^8.8.2: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== ajv-keywords@^3.5.2: version "3.5.2" @@ -254,25 +265,25 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browserslist@^4.21.10: - version "4.24.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.0.tgz#a1325fe4bc80b64fda169629fc01b3d6cecd38d4" - integrity sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A== +browserslist@^4.24.0: + version "4.24.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580" + integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== dependencies: - caniuse-lite "^1.0.30001663" - electron-to-chromium "^1.5.28" + caniuse-lite "^1.0.30001669" + electron-to-chromium "^1.5.41" node-releases "^2.0.18" - update-browserslist-db "^1.1.0" + update-browserslist-db "^1.1.1" buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -caniuse-lite@^1.0.30001663: - version "1.0.30001667" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz#99fc5ea0d9c6e96897a104a8352604378377f949" - integrity sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw== +caniuse-lite@^1.0.30001669: + version "1.0.30001687" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz#d0ac634d043648498eedf7a3932836beba90ebae" + integrity sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ== chalk@^4.1.0: version "4.1.2" @@ -324,18 +335,18 @@ commander@^2.20.0: integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" which "^2.0.1" -electron-to-chromium@^1.5.28: - version "1.5.33" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz#8f64698661240e70fdbc4b032e6085e391f05e09" - integrity sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA== +electron-to-chromium@^1.5.41: + version "1.5.71" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.71.tgz#d8b5dba1e55b320f2f4e9b1ca80738f53fcfec2b" + integrity sha512-dB68l59BI75W1BUGVTAEJy45CEVuEGy9qPVVQ8pnHyHMn36PLPPoE1mjLH+lo9rKulO3HC2OhbACI/8tCqJBcA== enhanced-resolve@^5.0.0, enhanced-resolve@^5.17.1: version "5.17.1" @@ -600,9 +611,9 @@ path-parse@^1.0.7: integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== picocolors@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" - integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.3.1: version "2.3.1" @@ -755,9 +766,9 @@ terser-webpack-plugin@^5.3.10: terser "^5.26.0" terser@^5.26.0: - version "5.34.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.34.1.tgz#af40386bdbe54af0d063e0670afd55c3105abeb6" - integrity sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA== + version "5.37.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.37.0.tgz#38aa66d1cfc43d0638fab54e43ff8a4f72a21ba3" + integrity sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -771,7 +782,7 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -ts-loader@^9.5.1: +ts-loader@*: version "9.5.1" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.5.1.tgz#63d5912a86312f1fbe32cef0859fb8b2193d9b89" integrity sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg== @@ -782,22 +793,22 @@ ts-loader@^9.5.1: semver "^7.3.4" source-map "^0.7.4" -tslib@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" - integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== +tslib@*: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -typescript@^5.6.2: - version "5.6.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" - integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== +typescript@*: + version "5.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6" + integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== -undici-types@~6.19.2: - version "6.19.8" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" - integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== -update-browserslist-db@^1.1.0: +update-browserslist-db@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== @@ -820,7 +831,7 @@ watchpack@^2.4.1: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -webpack-cli@^5.1.4: +webpack-cli@*: version "5.1.4" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== @@ -853,18 +864,18 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.95.0: - version "5.95.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.95.0.tgz#8fd8c454fa60dad186fbe36c400a55848307b4c0" - integrity sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q== - dependencies: - "@types/estree" "^1.0.5" - "@webassemblyjs/ast" "^1.12.1" - "@webassemblyjs/wasm-edit" "^1.12.1" - "@webassemblyjs/wasm-parser" "^1.12.1" - acorn "^8.7.1" - acorn-import-attributes "^1.9.5" - browserslist "^4.21.10" +webpack@*: + version "5.97.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.97.1.tgz#972a8320a438b56ff0f1d94ade9e82eac155fa58" + integrity sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg== + dependencies: + "@types/eslint-scope" "^3.7.7" + "@types/estree" "^1.0.6" + "@webassemblyjs/ast" "^1.14.1" + "@webassemblyjs/wasm-edit" "^1.14.1" + "@webassemblyjs/wasm-parser" "^1.14.1" + acorn "^8.14.0" + browserslist "^4.24.0" chrome-trace-event "^1.0.2" enhanced-resolve "^5.17.1" es-module-lexer "^1.2.1" From 43b388b5b97e123942550ba02998c4ca823f3960 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 10 Dec 2024 04:51:52 +0400 Subject: [PATCH 63/64] Finish TodoMVC, add a new example --- Clickable/DOM.hs | 86 +++++++------- Clickable/HTML.hs | 75 ++++++++++++ Clickable/Internal.hs | 39 +++++-- Clickable/Types.hs | 35 +++--- Clickable/WASM.hs | 20 ++++ Clickable/WebSocket.hs | 2 + examples/stopwatch/StopWatch.hs | 194 ++++++++++++++++++++++++++++++++ examples/stopwatch/wasm.hs | 10 ++ examples/todomvc/App.hs | 36 ------ examples/todomvc/TodoList.hs | 15 +++ examples/todomvc/Utils.hs | 2 + examples/todomvc/wasm.hs | 4 +- examples/wasm.hs | 56 +++++++++ examples/websocket.hs | 63 +++++++++++ jsbits/proto.ts | 83 +++++++++++--- jsbits/wasm.ts | 8 ++ 16 files changed, 607 insertions(+), 121 deletions(-) create mode 100644 examples/stopwatch/StopWatch.hs create mode 100644 examples/stopwatch/wasm.hs delete mode 100644 examples/todomvc/App.hs create mode 100644 examples/wasm.hs create mode 100644 examples/websocket.hs diff --git a/Clickable/DOM.hs b/Clickable/DOM.hs index d07c7db..549bcfc 100644 --- a/Clickable/DOM.hs +++ b/Clickable/DOM.hs @@ -45,42 +45,42 @@ addEventListener script k = class EventName eventName where type EventListenerCb eventName :: Type - connectEventName :: EventListenerCb eventName -> JSM () + connectEventName :: JSExp -> EventListenerCb eventName -> JSM () instance EventName "click" where type EventListenerCb "click" = JSM () - connectEventName k = addEventListener - (genericEvent defaultListenerOptions "click" (PeekStack 0)) (const k) + connectEventName t k = addEventListener + (genericEvent defaultListenerOptions "click" t) (const k) instance EventName "mousedown" where type EventListenerCb "mousedown" = JSM () - connectEventName k = addEventListener - (genericEvent defaultListenerOptions "mousedown" (PeekStack 0)) (const k) + connectEventName t k = addEventListener + (genericEvent defaultListenerOptions "mousedown" t) (const k) instance EventName "mouseup" where type EventListenerCb "mouseup" = JSM () - connectEventName k = addEventListener - (genericEvent defaultListenerOptions "mouseup" (PeekStack 0)) (const k) + connectEventName t k = addEventListener + (genericEvent defaultListenerOptions "mouseup" t) (const k) instance EventName "mouseenter" where type EventListenerCb "mouseenter" = JSM () - connectEventName k = addEventListener - (genericEvent defaultListenerOptions "mouseenter" (PeekStack 0)) (const k) + connectEventName t k = addEventListener + (genericEvent defaultListenerOptions "mouseenter" t) (const k) instance EventName "mouseleave" where type EventListenerCb "mouseleave" = JSM () - connectEventName k = addEventListener - (genericEvent defaultListenerOptions "mouseleave" (PeekStack 0)) (const k) + connectEventName t k = addEventListener + (genericEvent defaultListenerOptions "mouseleave" t) (const k) instance EventName "dblclick" where type EventListenerCb "dblclick" = JSM () - connectEventName k = addEventListener - (genericEvent defaultListenerOptions "dblclick" (PeekStack 0)) (const k) + connectEventName t k = addEventListener + (genericEvent defaultListenerOptions "dblclick" t) (const k) instance EventName "submit" where type EventListenerCb "submit" = JSM () - connectEventName k = - addEventListener (genericEvent opt "submit" (PeekStack 0)) (const k) + connectEventName t k = + addEventListener (genericEvent opt "submit" t) (const k) where opt = ListenerOptions { prevent_default = True, @@ -89,48 +89,48 @@ instance EventName "submit" where instance EventName "input" where type EventListenerCb "input" = Text -> JSM () - connectEventName = addEventListener (inputEvent "input") + connectEventName t = addEventListener (inputEvent t "input") instance EventName "keydown" where type EventListenerCb "keydown" = Int32 -> JSM () - connectEventName = addEventListener (keyboardEvent "keydown") + connectEventName t = addEventListener (keyboardEvent t "keydown") instance EventName "keyup" where type EventListenerCb "keyup" = Int32 -> JSM () - connectEventName = addEventListener (keyboardEvent "keyup") + connectEventName t = addEventListener (keyboardEvent t "keyup") instance EventName "focus" where type EventListenerCb "focus" = JSM () - connectEventName k = addEventListener - (genericEvent defaultListenerOptions "focus" (PeekStack 0)) (const k) + connectEventName t k = addEventListener + (genericEvent defaultListenerOptions "focus" t) (const k) instance EventName "blur" where type EventListenerCb "blur" = JSM () - connectEventName k = addEventListener - (genericEvent defaultListenerOptions "blur" (PeekStack 0)) (const k) + connectEventName t k = addEventListener + (genericEvent defaultListenerOptions "blur" t) (const k) instance EventName "input/blur" where type EventListenerCb "input/blur" = Text -> JSM () - connectEventName = addEventListener (inputEvent "blur") + connectEventName t = addEventListener (inputEvent t "blur") instance EventName "input/focus" where type EventListenerCb "input/focus" = Text -> JSM () - connectEventName = addEventListener (inputEvent "focus") + connectEventName t = addEventListener (inputEvent t "focus") instance EventName "checkbox/change" where type EventListenerCb "checkbox/change" = Bool -> JSM () - connectEventName = addEventListener checkboxChangeEvent + connectEventName t = addEventListener (checkboxChangeEvent t) instance EventName "select/change" where type EventListenerCb "select/change" = Text -> JSM () - connectEventName = addEventListener selectChangeEvent + connectEventName t = addEventListener (selectChangeEvent t) instance EventName "mousewheel" where type EventListenerCb "mousewheel" = MouseWheel -> JSM () - connectEventName = addEventListener mouseWheelEvent + connectEventName t = addEventListener (mouseWheelEvent t) on :: forall eventName. EventName eventName => EventListenerCb eventName -> HTML () -on k = liftJSM $ connectEventName @eventName k +on k = liftJSM $ connectEventName @eventName (PeekStack 0) k -- https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event @@ -155,9 +155,9 @@ genericEvent opt eventName target (Event eventId) = stopPropagationStmt = if opt.stop_propagation then "event.stopPropagation();" else "" -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event -inputEvent :: Text -> Event Text -> JSExp -inputEvent eventName (Event eventId) = - Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] +inputEvent :: JSExp -> Text -> Event Text -> JSExp +inputEvent target eventName (Event eventId) = + Eval script `Apply` [target, Lam (TriggerEvent eventId (Arg 0))] where script = "(function(target, trigger){\n\ @@ -170,9 +170,9 @@ inputEvent eventName (Event eventId) = -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event -- https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event -keyboardEvent :: Text -> Event Int32 -> JSExp -keyboardEvent eventName (Event eventId) = - Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] +keyboardEvent :: JSExp -> Text -> Event Int32 -> JSExp +keyboardEvent target eventName (Event eventId) = + Eval script `Apply` [target, Lam (TriggerEvent eventId (Arg 0))] where script = "(function(target, trigger){\n\ @@ -184,9 +184,9 @@ keyboardEvent eventName (Event eventId) = \})" -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -checkboxChangeEvent :: Event Bool -> JSExp -checkboxChangeEvent (Event eventId) = - Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] +checkboxChangeEvent :: JSExp -> Event Bool -> JSExp +checkboxChangeEvent target (Event eventId) = + Eval script `Apply` [target, Lam (TriggerEvent eventId (Arg 0))] where script = "(function(target, trigger){\n\ @@ -198,9 +198,9 @@ checkboxChangeEvent (Event eventId) = \})" -- https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event -selectChangeEvent :: Event Text -> JSExp -selectChangeEvent (Event eventId) = - Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] +selectChangeEvent :: JSExp -> Event Text -> JSExp +selectChangeEvent target (Event eventId) = + Eval script `Apply` [target, Lam (TriggerEvent eventId (Arg 0))] where script = "(function(target, trigger){\n\ @@ -225,9 +225,9 @@ data MouseWheel = MouseWheel { deriving anyclass (FromJSVal, ToJSVal) -- https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent -mouseWheelEvent :: Event MouseWheel -> JSExp -mouseWheelEvent (Event eventId) = - Eval script `Apply` [PeekStack 0, Lam (TriggerEvent eventId (Arg 0))] +mouseWheelEvent :: JSExp -> Event MouseWheel -> JSExp +mouseWheelEvent target (Event eventId) = + Eval script `Apply` [target, Lam (TriggerEvent eventId (Arg 0))] where script = "(function(target, trigger){\n\ diff --git a/Clickable/HTML.hs b/Clickable/HTML.hs index 1b2900e..828e9aa 100644 --- a/Clickable/HTML.hs +++ b/Clickable/HTML.hs @@ -4,6 +4,8 @@ {-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE BlockArguments #-} {-# OPTIONS_GHC -Wall #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE DerivingStrategies #-} module Clickable.HTML where import Clickable.Internal @@ -11,6 +13,8 @@ import Clickable.Types import Control.Monad.Trans import Data.IORef import Data.Text (Text) +import Control.Monad +import Data.Coerce el :: Text -> HTML a -> HTML a el tagName child = HTML \s e -> do @@ -189,6 +193,77 @@ simpleList listDyn h = do ies' <- synchronize new ies liftIO $ writeIORef ref ies' +newtype ListKey = ListKey {unListKey :: ScopeId} + deriving newtype (Show, Eq, Ord) + +dynamicList :: forall a. + Dynamic [(ListKey, a)] -> + (ListKey -> a -> HTML ()) -> + HTML () +dynamicList listDyn h = do + place <- liftJSM insertPlaceholder + initial <- readDyn listDyn + liftJSM $ execHTML (Ref place) $ liftJSM $ updateList [] initial + liftJSM $ subscribe listDyn $ execHTML (Ref place) . liftJSM . updateList undefined + where + synchronize :: [(ListKey, a)] -> [(ListKey, a)] -> JSM () + synchronize [] [] = pure () + synchronize [] (n:ns) = do + -- New list is longer, append new elements + insertElem n Nothing + let refId = coerce $ fst n + scopeId = unListKey $ fst n + localScope scopeId $ execHTML (Ref refId) $ uncurry h n + synchronize [] ns + synchronize (o:os) [] = do + -- New list is shorter, delete the elements that no longer + -- present in the new list + mapM_ dropElem (o:os) + synchronize (o:os) (n:ns) + | fst n /= fst o = + case lookupOldPosition (fst n) (o:os) of + Just (zs, xs) -> do + forM_ zs dropElem + synchronize xs (n:ns) + Nothing -> do + insertElem n $ Just o + synchronize (o:os) ns + | otherwise = + synchronize os ns + + insertElem :: (ListKey, a) -> Maybe (ListKey, a) -> JSM () + insertElem lie Nothing = do + let refId = coerce $ fst lie + scopeId = unListKey $ fst lie + bindScope scopeId + localScope scopeId do + jsCmd $ AssignRef scopeId refId InsertPlaceholder + insertElem lie (Just (key, _)) = do + let refId = coerce $ fst lie + scopeId = unListKey $ fst lie + bindScope scopeId + localScope scopeId do + jsCmd $ AssignRef scopeId refId $ InsertPlaceholderBefore $ Ref (coerce key) + dropElem :: (ListKey, a) -> JSM () + dropElem ie = do + let refId = coerce $ fst ie + scopeId = unListKey $ fst ie + detachPlaceholder refId + destroyScope scopeId + updateList :: [(ListKey, a)] -> [(ListKey, a)] -> JSM () + updateList old new = do + synchronize new old + lookupOldPosition :: ListKey -> [(ListKey, a)] -> Maybe ([(ListKey, a)], [(ListKey, a)]) + lookupOldPosition k = go [] where + go :: [(ListKey, a)] -> [(ListKey, a)] -> Maybe ([(ListKey, a)], [(ListKey, a)]) + go _ [] = Nothing + go acc ((kx,x):xs) + | k == kx = Just (acc, (kx,x):xs) + | otherwise = go ((kx,x):acc) xs + +allocListKey :: JSM ListKey +allocListKey = fmap (ListKey . ScopeId) nextId + insertPlaceholder :: JSM RefId insertPlaceholder = JSM \e -> do ref <- newRefId.unJSM e diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index d5e827a..2400117 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -28,6 +28,8 @@ import Foreign.Ptr import GHC.Exts import GHC.Stack import Unsafe.Coerce +import Data.Int +import Data.Word newEvent :: JSM (Event a) newEvent = state \s -> @@ -80,6 +82,7 @@ subscribe (FromVar (OverrideVar _ var)) k = subscribe (FromVar (LensMap l var)) k = subscribe (FromVar var) (k . getConst . l Const) subscribe (MapVal v f) k = subscribe v (k . f) +subscribe (MapIOVal v f) k = subscribe v (k <=< liftIO . f) subscribe (SplatVal fv av) k = do src <- reactive h subscribe fv $ f src @@ -195,19 +198,23 @@ localScope s = local (\e -> e {ien_scope = s}) {-# INLINE localScope #-} newRefId :: JSM RefId -newRefId = reactive newRefIdFn +newRefId = fmap RefId nextId {-# INLINE newRefId #-} newRefIdFn :: ScopeId -> InternalState -> (InternalState, RefId) newRefIdFn _e s = (s {ist_id_supply = s.ist_id_supply + 1}, RefId s.ist_id_supply) {-# INLINE newRefIdFn #-} +nextId :: JSM Word32 +nextId = reactive \_ s -> (s {ist_id_supply = s.ist_id_supply + 1}, s.ist_id_supply) +{-# INLINE nextId #-} + freeScope :: ScopeId -> JSM () freeScope scope = do mres <- state updateState forM_ mres \res -> do forM_ (res.rsr_linked) destroyScope - sequence_ (res.rsr_finalizers) + sequence_ res.rsr_finalizers jsCmd $ FreeScope scope where updateState :: InternalState -> (Maybe Resources, InternalState) @@ -256,6 +263,16 @@ moveScope src dest = do rsr_finalizers = src'.rsr_finalizers <> dest'.rsr_finalizers } +bindScope :: ScopeId -> JSM () +bindScope child = reactive_ updateState + where + updateState :: ScopeId -> InternalState -> InternalState + updateState parent s = + s {ist_resources = Map.adjust updateRes parent s.ist_resources} + where + updateRes :: Resources -> Resources + updateRes r = r {rsr_linked = child : r.rsr_linked} + installFinalizer :: JSM () -> JSM () installFinalizer f = reactive_ $ installFinalizerFn f {-# INLINE installFinalizer #-} @@ -263,8 +280,9 @@ installFinalizer f = reactive_ $ installFinalizerFn f installFinalizerFn :: JSM () -> ScopeId -> InternalState -> InternalState installFinalizerFn k scope s = s {ist_resources = rsr} where - rsr = Map.adjust ins scope s.ist_resources - ins r = r {rsr_finalizers = k : r.rsr_finalizers} + rsr = Map.alter ins scope s.ist_resources + ins (Just r) = Just $ r {rsr_finalizers = k : r.rsr_finalizers} + ins Nothing = Just $ Resources scope [] [k] {-# INLINE installFinalizerFn #-} emptyState :: InternalState @@ -278,6 +296,7 @@ readDyn :: MonadIO m => Dynamic a -> m a readDyn (ConstVal a) = pure a readDyn (FromVar var) = readVar var readDyn (MapVal val f) = fmap f $ readDyn val +readDyn (MapIOVal val f) = liftIO . f =<< readDyn val readDyn (SplatVal f a) = liftA2 ($) (readDyn f) (readDyn a) readDyn (OverrideSub _ a) = readDyn a @@ -431,9 +450,9 @@ newInternalEnv bufSize consume = do ien_state <- newIORef emptyState (write, flush) <- commandBuffer (buf, bufSize) consume pure InternalEnv { - ien_command = write, - ien_flush = flush, - ien_state, - ien_scope = ScopeId 0, - ien_prompt_tag - } + ien_command = write, + ien_flush = flush, + ien_state, + ien_scope = ScopeId 0, + ien_prompt_tag + } diff --git a/Clickable/Types.hs b/Clickable/Types.hs index 1c8dd22..f10e788 100644 --- a/Clickable/Types.hs +++ b/Clickable/Types.hs @@ -14,6 +14,7 @@ module Clickable.Types where import Clickable.Binary +import Control.Monad.Fix import Control.Monad.Reader import Control.Monad.State.Strict import Data.Binary ( Binary ) @@ -28,11 +29,10 @@ import Data.Text qualified as Text import Data.Tuple import Data.Word import GHC.Exts +import GHC.Generics import GHC.Generics qualified as G import GHC.List qualified as List import GHC.Types -import GHC.Generics -import Control.Monad.Fix newtype JSM a = JSM {unJSM :: InternalEnv -> IO a} deriving ( @@ -46,15 +46,17 @@ newtype JSM a = JSM {unJSM :: InternalEnv -> IO a} instance MonadState InternalState JSM where state f = JSM \e -> atomicModifyIORef' e.ien_state (swap . f) - {-# INLINE state #-} get = JSM \e -> readIORef e.ien_state - {-# INLINE get #-} put s = JSM \e -> writeIORef e.ien_state s + {-# INLINE state #-} + {-# INLINE get #-} {-# INLINE put #-} class MonadJSM m where liftJSM :: JSM a -> m a +instance MonadJSM JSM where liftJSM x = x + data InternalEnv = InternalEnv { ien_command :: JSExp -> IO (), ien_flush :: IO (), @@ -144,6 +146,7 @@ data JSExp where ClassListAdd :: JSExp -> Text -> JSExp ClassListRemove :: JSExp -> Text -> JSExp InsertPlaceholder :: JSExp + InsertPlaceholderBefore :: JSExp -> JSExp ClearPlaceholder :: JSExp -> JSExp DetachPlaceholder :: JSExp -> JSExp @@ -164,6 +167,7 @@ data ClientMsg where StartMsg :: StartFlags -> ClientMsg EventMsg :: EventId -> JSExp -> ClientMsg ResumeMsg :: EventId -> JSExp -> ClientMsg + BeforeUnloadMsg :: ClientMsg deriving stock (Generic, Show) deriving anyclass Binary @@ -209,6 +213,7 @@ data Dynamic a where ConstVal :: a -> Dynamic a FromVar :: DynVar a -> Dynamic a MapVal :: Dynamic a -> (a -> b) -> Dynamic b + MapIOVal :: Dynamic a -> (a -> IO b) -> Dynamic b SplatVal :: Dynamic (a -> b) -> Dynamic a -> Dynamic b OverrideSub :: (forall b. SubscribeFn a b -> SubscribeFn a b) -> Dynamic a -> Dynamic a @@ -219,8 +224,8 @@ instance Functor Dynamic where {-# INLINE fmap #-} instance Applicative Dynamic where pure = ConstVal - {-# INLINE pure #-} (<*>) = SplatVal + {-# INLINE pure #-} {-# INLINE (<*>) #-} fromVar :: DynVar a -> Dynamic a @@ -355,19 +360,22 @@ instance FromJSVal Word where fromJSVal _ = Nothing instance FromJSVal Char where - fromJSVal = \case - Str a | Just (c, _) <- Text.uncons a -> Just c - | otherwise -> Nothing - _ -> Nothing + fromJSVal (Str a) + | Just (c, _) <- Text.uncons a =Just c + | otherwise = Nothing + fromJSVal _ = Nothing instance FromJSVal Text where - fromJSVal = \case Str a -> Just a; _ -> Nothing + fromJSVal (Str a) = Just a + fromJSVal _ = Nothing instance FromJSVal ByteString where - fromJSVal = \case U8Arr a -> Just a; _ -> Nothing + fromJSVal (U8Arr a) = Just a + fromJSVal _ = Nothing instance FromJSVal () where - fromJSVal = \case Null -> Just (); _ -> Nothing + fromJSVal Null = Just () + fromJSVal _ = Nothing instance FromJSVal a => FromJSVal [a] where fromJSVal = \case @@ -375,7 +383,8 @@ instance FromJSVal a => FromJSVal [a] where _ -> Nothing instance FromJSVal a => FromJSVal (Maybe a) where - fromJSVal = fmap Just . fromJSVal @a + fromJSVal Null = Just Nothing + fromJSVal v = Just $ fromJSVal @a v instance (FromJSVal a, FromJSVal b) => FromJSVal (a, b) where fromJSVal j = fromJSVal j >>= \case diff --git a/Clickable/WASM.hs b/Clickable/WASM.hs index 700011b..f71d233 100644 --- a/Clickable/WASM.hs +++ b/Clickable/WASM.hs @@ -9,6 +9,7 @@ {-# LANGUAGE UnboxedTuples #-} {-# OPTIONS_GHC -Wno-unused-do-bind #-} {-# OPTIONS_GHC -Wall #-} +{-# LANGUAGE RecordWildCards #-} module Clickable.WASM where import Clickable.Internal @@ -29,6 +30,7 @@ import Data.IORef import Control.Monad import Unsafe.Coerce import System.IO +import Debug.Trace foreign import ccall safe "clickable_eval_buffer" clickable_eval_buffer :: Ptr Word8 -> Int -> IO () @@ -58,6 +60,8 @@ mkWasmApp app inmsg = do Just (ResumeMsg contId pload) -> do cont <- atomicModifyIORef' env.ien_state $ lookupCont $ coerce contId forM_ cont \c -> runJSM env $ c.sub_callback $ unsafeCoerce $ ((pure pload) :: IO JSVal) + Just BeforeUnloadMsg -> do + runJSM env $ freeScope env.ien_scope _ -> error "mkWasmApp: Failed to parse incomming command" pure $ castPtr $ fst buf where @@ -72,3 +76,19 @@ loadMessage p len where loadByteString :: IO ByteString loadByteString = BSU.unsafePackCStringLen (castPtr p, len) + +data ResourcesShow = ResourcesShow { + rsr_parent :: ScopeId, + rsr_linked :: [ScopeId], + rsr_finalizers :: [String] +} deriving Show + +instance Show Resources where + show = show . convert + where + convert :: Resources -> ResourcesShow + convert Resources{..} = ResourcesShow { + rsr_parent, + rsr_linked, + rsr_finalizers = map (const "") rsr_finalizers + } diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index b5e16c5..d1edbdd 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -140,6 +140,8 @@ websocketApp cfg self p = forM_ cont \c -> runJSM conn.dsc_internal_env $ c.sub_callback $ unsafeCoerce $ ((pure pload) :: IO JSVal) reader conn (Right (EventMsg eid arg)) = void $ runJSM conn.dsc_internal_env $ triggerEvent (unsafeFromEventId eid) arg + reader conn (Right BeforeUnloadMsg) = do + runJSM conn.dsc_internal_env $ freeScope conn.dsc_internal_env.ien_scope reader conn (Left a) = void $ runJSM conn.dsc_internal_env a diff --git a/examples/stopwatch/StopWatch.hs b/examples/stopwatch/StopWatch.hs new file mode 100644 index 0000000..612044c --- /dev/null +++ b/examples/stopwatch/StopWatch.hs @@ -0,0 +1,194 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE StrictData #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# OPTIONS_GHC -Wall #-} +{-# OPTIONS_GHC -Wno-unused-do-bind #-} +{-# LANGUAGE DataKinds #-} +module StopWatch where + +import Clickable +import Data.Time +import Control.Monad.IO.Class +import qualified Data.Text as Text +import Data.Text (Text) +import Data.Int +import Control.Monad +import Data.String + +data StopWatchInstance = StopWatchInstance { + time_var :: DynVar (Maybe UTCTime, Maybe IntervalId) +} + +data StopWatchState = StopWatchState { + t0 :: Maybe UTCTime, + iid :: Maybe IntervalId +} + +newtype IntervalId = IntervalId {unIntervalId :: Int32} + deriving (ToJSVal, FromJSVal) + +run :: JSM () +run = do + timeVar <- newVar $ StopWatchState Nothing Nothing + clockEv <- newEvent + clockEv `subscribeEvent` \_ -> modifyVar_ timeVar Prelude.id + execHTMLBody do + el "style" $ text styles + liftJSM $ addEventListener spaceKeyEvent $ const $ toggleState clockEv timeVar + div_ [class_ "StopWatch-container"] do + h1_ [class_ "StopWatch-time"] do + dynText $ MapIOVal (fromVar timeVar) prettyTime' + button_ [class_ "StopWatch-button"] do + dynText $ fmap buttonTitle $ fromVar timeVar + on @"click" $ toggleState clockEv timeVar + t0 <- liftIO getCurrentTime + month t0 + where + -- updateTime :: UTCTime -> Maybe (UTCTime, IntervalId) -> Maybe (UTCTime, IntervalId) + -- updateTime _ Nothing = Nothing + -- updateTime t (Just (_, i)) = Just (t, i) + + toggleState :: Event () -> DynVar StopWatchState -> JSM () + toggleState clockEv self = do + liftIO $ print $ "toggleState" + s <- readVar self + case s of + StopWatchState Nothing Nothing -> do + iid <- setInterval clockEv + t0 <- liftIO getCurrentTime + writeVar self $ StopWatchState (Just t0) (Just iid) + StopWatchState (Just t) (Just iid) -> do + clearInterval iid + writeVar self $ StopWatchState (Just t) Nothing + StopWatchState _ _ -> do + writeVar self $ StopWatchState Nothing Nothing + + prettyTime' :: StopWatchState -> IO Text + prettyTime' (StopWatchState Nothing _) = pure "00:00:000" + prettyTime' (StopWatchState (Just t0) _) = do + t1 <- getCurrentTime + pure $ stopwatch t0 t1 + + buttonTitle :: StopWatchState -> Text + buttonTitle (StopWatchState Nothing Nothing) = "Start" + buttonTitle (StopWatchState (Just _) (Just _)) = "Stop" + buttonTitle (StopWatchState _ _) = "Reset" + +spaceKeyEvent :: Event () -> JSExp +spaceKeyEvent (Event eventId) = + Eval script `Apply` [Lam (TriggerEvent eventId (Arg 0))] + where + script = + "(function(trigger){\n\ + \ function listener(event){\n\ + \ if (event.target.classList.contains('StopWatch-button')) return;\n\ + \ if (event.keyCode != 32) return;\n\ + \ trigger();\n\ + \ }\n\ + \ window.addEventListener('keydown', listener);\n\ + \ return () => window.removeEventListener('keydown', listener);\n\ + \})" + +setInterval :: Event () -> JSM IntervalId +setInterval (Event eid) = do + v <- jsEval $ Eval "trigger => setInterval(trigger, 1)" `Apply` [Lam (TriggerEvent eid Null)] + maybe (error "setInterval: invalid result") pure $ fromJSVal v + +clearInterval :: IntervalId -> JSM () +clearInterval intervalId = + jsCmd $ Apply (Id "clearInterval") [toJSVal intervalId] + +-- | Calculate the difference between two moments in time and format it as mm:ss:mmmm +stopwatch :: UTCTime -> UTCTime -> Text +stopwatch begin now = + let diffSeconds = realToFrac $ diffUTCTime now begin :: Double + totalMilliseconds = round (diffSeconds * 1000) :: Int + minutes = totalMilliseconds `div` (60 * 1000) + seconds = (totalMilliseconds `div` 1000) `mod` 60 + milliseconds = totalMilliseconds `mod` 1000 + in pad2 minutes <> ":" <> pad2 seconds <> ":" <> pad4 milliseconds + +-- | Helper function to pad numbers to 2 digits +pad2 :: Int -> Text +pad2 n = if n < 10 then "0" <> show' n else show' n + +-- | Helper function to pad numbers to 4 digits +pad4 :: Int -> Text +pad4 n + | n < 10 = "00" <> show' n + | n < 100 = "0" <> show' n + | n < 1000 = show' n + | otherwise = show' n + +-- | Format a given UTCTime as HH:mm:ss:mmmm +prettyTime :: UTCTime -> Text +prettyTime time = + let dayTime = utctDayTime time + timeOfDay = timeToTimeOfDay dayTime + hours = todHour timeOfDay + minutes = todMin timeOfDay + seconds = floor (todSec timeOfDay) :: Int + milliseconds = round ((todSec timeOfDay - fromIntegral seconds) * 1000) :: Int + in pad2 hours <> ":" <> pad2 minutes <> ":" <> pad2 seconds <> ":" <> pad4 milliseconds + +show' :: Show a => a -> Text +show' = Text.pack . show + +styles :: Text +styles = "\ + \body {\ + \ font-family: arial;\ + \}\ + \.StopWatch-container {\ + \ margin: 0 auto;\ + \ text-align: center;\ + \}\ + \.StopWatch-time {\ + \ font-family: system-ui;\ + \ font-size: 196px;\ + \ font-weight: 400;\ + \}\ + \\ + \.StopWatch-button {\ + \ font-size: 48px;\ + \ border: none;\ + \ background: blue;\ + \ color: white;\ + \ border-radius: 32px;\ + \ padding: 4px 22px;\ + \ cursor: pointer;\ + \}\ + \" + +-- Here is how to create a table using my library. Complete the +-- function that builds calendar layout for given month +makeTable :: HTML () +makeTable = do + table_ [class_ "table"] do + tbody_ do + tr_ do td_ "One"; td_ "Two"; td_ "Three" + +month :: UTCTime -> HTML () +month t = do + let day = utctDay t + (y, m, _) = toGregorian day + firstDay = fromGregorian y m 1 + daysInMonth = gregorianMonthLength y m + firstWeekDay = dayOfWeek firstDay + startOffset = (fromEnum firstWeekDay - 1) `mod` 7 + days = [1..daysInMonth] + paddedDays = replicate startOffset "" ++ map show days + + table_ [class_ "table"] $ do + thead_ $ tr_ $ forM_ ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"] (th_ . fromString) + tbody_ $ forM_ (chunksOf 7 paddedDays) $ \week -> + tr_ $ forM_ week (td_ . fromString) + +chunksOf :: Int -> [a] -> [[a]] +chunksOf _ [] = [] +chunksOf n xs + | n <= 0 = error "chunksOf: chunk size must be positive" + | otherwise = take n xs : chunksOf n (drop n xs) diff --git a/examples/stopwatch/wasm.hs b/examples/stopwatch/wasm.hs new file mode 100644 index 0000000..9cc4440 --- /dev/null +++ b/examples/stopwatch/wasm.hs @@ -0,0 +1,10 @@ +import Clickable.WASM +import GHC.Ptr +import GHC.Word +import StopWatch + +main :: IO () +main = return () + +foreign export ccall wasm_app :: Ptr Word8 -> IO (Ptr Word8) +wasm_app = mkWasmApp $ const StopWatch.run diff --git a/examples/todomvc/App.hs b/examples/todomvc/App.hs deleted file mode 100644 index b610a25..0000000 --- a/examples/todomvc/App.hs +++ /dev/null @@ -1,36 +0,0 @@ -{-# LANGUAGE GHC2021 #-} -{-# LANGUAGE StrictData #-} -{-# LANGUAGE BlockArguments #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE OverloadedRecordDot #-} -{-# LANGUAGE DuplicateRecordFields #-} -{-# OPTIONS_GHC -Wall #-} -module App where - -import Data.Maybe -import Clickable - -import TodoList qualified as TodoList -import Utils -import TodoItem (TodoItemState(TodoItemState)) - -app :: StartFlags -> JSM () -app _ = do - items <- fromMaybe [] <$> readLocalStorage "todo-items" - stateVar <- TodoList.new items - installFinalizer do - s <- readVar stateVar - saveLocalStorage "todo-items" s.items - execHTMLBody do - el "style" $ text TodoList.styles - TodoList.view TodoList.TodoListConfig {self = stateVar} - liftJSM $ addEventListener popstateEvent \loc -> do - let f = fromMaybe TodoList.All $ TodoList.parseFilter loc.loc_hash - modifyVar_ stateVar \s -> s {TodoList.filter = f} - - -app1 :: StartFlags -> JSM () -app1 _ = do - items :: [TodoItemState] <- fromMaybe [] <$> readLocalStorage "todo-items" - execHTMLBody do - h1_ "sdfsdfsdfsd" diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index ddc54fe..a47b216 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -19,9 +19,24 @@ import Data.List qualified as List import Data.Text (Text) import Data.Text qualified as Text import GHC.Int +import Data.Maybe import TodoItem qualified as TodoItem +import Utils +run :: JSM () +run = do + items <- fromMaybe [] <$> readLocalStorage "todo-items" + stateVar <- TodoList.new items + installFinalizer do + s <- readVar stateVar + saveLocalStorage "todo-items" s.items + execHTMLBody do + el "style" $ text TodoList.styles + TodoList.view TodoList.TodoListConfig {self = stateVar} + liftJSM $ addEventListener popstateEvent \loc -> do + let f = fromMaybe TodoList.All $ TodoList.parseFilter loc.loc_hash + modifyVar_ stateVar \s -> s {TodoList.filter = f} data TodoListConfig = TodoListConfig { self :: DynVar TodoListState diff --git a/examples/todomvc/Utils.hs b/examples/todomvc/Utils.hs index 308af2d..991d9b9 100644 --- a/examples/todomvc/Utils.hs +++ b/examples/todomvc/Utils.hs @@ -7,11 +7,13 @@ module Utils where import Data.Text (Text) import Clickable +import Debug.Trace readLocalStorage :: FromJSVal v => Text -> JSM (Maybe v) readLocalStorage key = do let jsonParse e = Call (Id "JSON") "parse" [e] val <- jsEval $ jsonParse $ Call (Id "localStorage") "getItem" [Str key] + traceShowM val return $ fromJSVal val saveLocalStorage :: ToJSVal v => Text -> v -> JSM () diff --git a/examples/todomvc/wasm.hs b/examples/todomvc/wasm.hs index d208273..649a406 100644 --- a/examples/todomvc/wasm.hs +++ b/examples/todomvc/wasm.hs @@ -1,10 +1,10 @@ import Clickable.WASM import GHC.Ptr import GHC.Word -import App +import TodoList main :: IO () main = return () foreign export ccall wasm_app :: Ptr Word8 -> IO (Ptr Word8) -wasm_app = mkWasmApp app +wasm_app = mkWasmApp $ const TodoList.run diff --git a/examples/wasm.hs b/examples/wasm.hs new file mode 100644 index 0000000..31d788d --- /dev/null +++ b/examples/wasm.hs @@ -0,0 +1,56 @@ +{-# OPTIONS_GHC -Wno-unused-local-binds #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE RecursiveDo #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE StrictData #-} +{-# OPTIONS_GHC -Wno-unused-do-bind #-} +{-# LANGUAGE DataKinds #-} +module Main where + +import Clickable +import qualified Data.Text as Text +import Clickable.WASM +import Data.Word +import Foreign (Ptr) +import Data.IORef +import Control.Monad.Reader + +test01 :: JSM () +test01 = execHTMLBody do + counter <- liftJSM $ newVar 0 + el "div" do + property "className" (Str "container") + text "Lorem Ipsum" + el "h1" $ text "Fox jumps over a lazy dog" + el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" + el "button" do + text "Click Here" + on @"click" $ modifyVar_ counter succ + el "button" do + text "-" + on @"click" $ modifyVar_ counter pred + el "br" $ pure () + el "span" do + dynText $ fmap (Text.pack . show) $ fromVar counter + ref <- liftIO $ newIORef $ const $ pure () + el "div" do + el "button" do + text "Ask a Value" + on @"click" do + t <- asks (.ien_prompt_tag) + val <- liftIO $ control t \cont -> writeIORef ref cont + jsCmd $ Call (Id "console") "log" [val] + el "button" do + text "Fill the value" + on @"click" do + cont <- liftIO $ readIORef ref + liftIO $ cont $ pure $ Obj [("this", Str "is"), ("some", Str "value")] + +main :: IO () +main = pure () + +foreign export ccall wasm_app :: Ptr Word8 -> IO (Ptr Word8) +wasm_app :: Ptr Word8 -> IO (Ptr Word8) +wasm_app = mkWasmApp test01 diff --git a/examples/websocket.hs b/examples/websocket.hs new file mode 100644 index 0000000..172acf0 --- /dev/null +++ b/examples/websocket.hs @@ -0,0 +1,63 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE BlockArguments #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecursiveDo #-} +module Main where + +import Clickable.Html +import Clickable.Internal +import Clickable.Types +import Clickable.WebSocket +import Control.Monad.IO.Class +import Control.Monad.Reader +import Data.IORef +import Network.Wai.Handler.Warp (run) +import Unsafe.Coerce (unsafeCoerce) +import qualified Data.Text as Text + +test01 :: JSM () +test01 = do + counter <- newVar @Int 0 + attach do + el "div" do + prop "className" (Str "container") + text "Lorem Ipsum" + el "h1" $ text "Fox jumps over a lazy dog" + el "p" $ text "Lorem Ipsum sjfh lasfkjh asdl" + el "button" do + text "Click Here" + on @"click" $ modifyVar_ counter succ + el "button" do + text "-" + on @"click" $ modifyVar_ counter pred + el "br" $ pure () + el "span" do + dynText $ fmap (Text.pack . show) $ fromVar counter + ref <- liftIO $ newIORef $ const $ pure () + el "div" do + el "button" do + text "Ask a Value" + on @"click" do + t <- asks (.ien_prompt_tag) + val <- liftIO $ control t \cont -> writeIORef ref cont + jsCmd $ Call (Id "console") "log" [val] + el "button" do + text "Fill the value" + on @"click" do + cont <- liftIO $ readIORef ref + liftIO $ cont $ pure $ Obj [("this", Str "is"), ("some", Str "value")] + +main :: IO () +main = do + run 3000 $ runApp test01 + +baz :: IO Int +baz = do + let z :: Int = unsafeCoerce False + return $ z * 2 + +bar :: Int -> Int +bar dsfsd = dsfsd diff --git a/jsbits/proto.ts b/jsbits/proto.ts index 13dc0ab..4feb473 100644 --- a/jsbits/proto.ts +++ b/jsbits/proto.ts @@ -76,6 +76,7 @@ export enum ExprTag { ClassListAdd, ClassListRemove, InsertPlaceholder, + InsertPlaceholderBefore, ClearPlaceholder, DetachPlaceholder, @@ -131,6 +132,7 @@ export type Expr = | [ExprTag.ClassListAdd, Expr, string[]] | [ExprTag.ClassListRemove, Expr, string[]] | [ExprTag.InsertPlaceholder] + | [ExprTag.InsertPlaceholderBefore, Expr] | [ExprTag.ClearPlaceholder, Expr] | [ExprTag.DetachPlaceholder, Expr] @@ -464,6 +466,14 @@ export function evalNext(self: EvalState, args: List = null, prevRes: u const el = self.context.stack[VAL] as any; return utils.insertPlaceholder(el); }; + case ExprTag.InsertPlaceholderBefore: { + if (!self.context.stack) { + throw new Error("InsertPlaceholderBefore: empty stack"); + } + const el = self.context.stack[VAL] as any; + const anchor = evalNext(self, args, prevRes) as Element; + return utils.insertPlaceholderBefore(el, anchor); + }; case ExprTag.ClearPlaceholder: { const node = evalNext(self, args, prevRes); utils.clearPlaceholder(node as any, false); @@ -671,6 +681,9 @@ export function lookaheadNext(mem: DataView, ptr: Ptr): Ptr { case ExprTag.InsertPlaceholder: { return ptr; }; + case ExprTag.InsertPlaceholderBefore: { + return lookaheadNext(mem, ptr); + }; case ExprTag.ClearPlaceholder: { return lookaheadNext(mem, ptr); }; @@ -791,12 +804,14 @@ export enum ClientMsgTag { StartMsg, EventMsg, ResumeMsg, + BeforeUnloadMsg, } export type ClientMsg = | [ClientMsgTag.StartMsg, unknown] | [ClientMsgTag.EventMsg, number, unknown] | [ClientMsgTag.ResumeMsg, number, unknown] + | [ClientMsgTag.BeforeUnloadMsg] ; export function encodeClientMessage(self: EncoderState, val: ClientMsg) { @@ -821,6 +836,11 @@ export function encodeClientMessage(self: EncoderState, val: ClientMsg) { encodeValue(self, val[2]); return; } + case ClientMsgTag.BeforeUnloadMsg: { + self.mem.setUint8(self.begin, ClientMsgTag.BeforeUnloadMsg); + self.begin++; + return; + } } } @@ -835,11 +855,20 @@ function decodeString(s: EvalState): string { } namespace utils { - export function insert(builder: Element|Comment, child: Node): void { - if (builder instanceof Comment) { - builder.parentElement!.insertBefore(child, builder); + export function insert(root: Element|Comment, child: Node): void { + if (root instanceof Comment) { + root.parentElement!.insertBefore(child, root); } else { - builder.appendChild(child); + root.appendChild(child); + } + } + + export function insertBefore(root: Element|Comment, child: Node, anchor: Element|Comment): void { + const anchor_ = anchor instanceof Comment ? lookupOpen(anchor) : anchor; + if (root instanceof Comment) { + root.parentElement!.insertBefore(child, anchor_); + } else { + root.insertBefore(child, anchor_); } } @@ -851,26 +880,34 @@ namespace utils { } } - export function attr(builder: Element|Comment, attrName: string, attrValue: string): void { - const element = getBuilderElement(builder); + export function attr(root: Element|Comment, attrName: string, attrValue: string): void { + const element = getBuilderElement(root); element.setAttribute(attrName, attrValue); } - export function addEventListener(builder: Element|Comment, eventName: string, listener: EventListener): void { - const element = getBuilderElement(builder); + export function addEventListener(root: Element|Comment, eventName: string, listener: EventListener): void { + const element = getBuilderElement(root); element.addEventListener(eventName, listener); } - export function removeEventListener(builder: Element|Comment, eventName: string, listener: EventListener): void { - const element = getBuilderElement(builder); + export function removeEventListener(root: Element|Comment, eventName: string, listener: EventListener): void { + const element = getBuilderElement(root); element.removeEventListener(eventName, listener); } - export function insertPlaceholder(builder: Element|Comment): Comment { + export function insertPlaceholder(root: Element|Comment): Comment { + const begin = document.createComment('Placeholder {{{'); + const end = document.createComment('}}}'); + insert(root, begin); + insert(root, end); + return end; + } + + export function insertPlaceholderBefore(root: Element|Comment, anchor: Element|Comment): Comment { const begin = document.createComment('Placeholder {{{'); const end = document.createComment('}}}'); - insert(builder, begin); - insert(builder, end); + insertBefore(root, begin, anchor); + insertBefore(root, end, anchor); return end; } @@ -894,11 +931,11 @@ namespace utils { } } - export function getBuilderElement(builder: Element|Comment): Element { - if (builder instanceof Comment) { - return builder.parentElement!; + export function getBuilderElement(root: Element|Comment): Element { + if (root instanceof Comment) { + return root.parentElement!; } - return builder; + return root; } function isOpenPlaceholder(node: Node): boolean { @@ -914,6 +951,18 @@ namespace utils { } return false; } + + function lookupOpen(anchor: Node): Node|null { + let nestedCounter = 0; + for (;;) { + if (!anchor.previousSibling || + (nestedCounter == 0 && isOpenPlaceholder(anchor.previousSibling)) + ) return anchor.previousSibling; + if (isClosingPlaceholder(anchor.previousSibling)) nestedCounter++; + else if (isOpenPlaceholder(anchor.previousSibling)) nestedCounter--; + anchor = anchor.previousSibling!; + } + } }; export class RefStore { diff --git a/jsbits/wasm.ts b/jsbits/wasm.ts index 6b4ca59..4976fc4 100644 --- a/jsbits/wasm.ts +++ b/jsbits/wasm.ts @@ -89,6 +89,14 @@ export function runWasm(wasmUri: string, startFlags: unknown = null, options?: P proto.encodeClientMessage(encoderState, [ClientMsgTag.StartMsg, startFlags]); // @ts-ignore inst1.exports.wasm_app(buf); + window.addEventListener('beforeunload', () => { + // @ts-ignore + const mem = new DataView(inst1.exports.memory.buffer); + const encoderState = {mem, begin: buf, end: buf + (1024 * 100)}; + proto.encodeClientMessage(encoderState, [ClientMsgTag.BeforeUnloadMsg]); + // @ts-ignore + inst1.exports.wasm_app(buf); + }); }); }; From e6ba6a5a226e725aae0eabb6b08b49dcffe745b7 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 18 Dec 2024 03:01:16 +0400 Subject: [PATCH 64/64] WIP --- .dir-locals.el | 28 +- Clickable/HTML.hs | 10 +- Clickable/Internal.hs | 11 +- Clickable/WASM.hs | 2 + Clickable/WebSocket.hs | 2 +- .../StopWatch.hs => heatmap/HeatMap.hs} | 44 +- examples/{stopwatch => heatmap}/wasm.hs | 4 +- examples/todomvc/TodoList.hs | 163 +- hie.yaml | 2 +- public/bootstrap-icons.css | 2078 +++ public/bootstrap.css | 12111 ++++++++++++++++ public/fonts/bootstrap-icons.woff | Bin 0 -> 176032 bytes public/fonts/bootstrap-icons.woff2 | Bin 0 -> 130396 bytes public/heatmap.html | 12 + public/heatmap.wasm | Bin 0 -> 2702031 bytes public/index.bundle.js | 1 + public/stopwatch.wasm | Bin 0 -> 2699145 bytes public/todomvc.html | 11 + public/todomvc.wasm | Bin 0 -> 3189472 bytes 19 files changed, 14350 insertions(+), 129 deletions(-) rename examples/{stopwatch/StopWatch.hs => heatmap/HeatMap.hs} (89%) rename examples/{stopwatch => heatmap}/wasm.hs (71%) create mode 100644 public/bootstrap-icons.css create mode 100644 public/bootstrap.css create mode 100644 public/fonts/bootstrap-icons.woff create mode 100644 public/fonts/bootstrap-icons.woff2 create mode 100644 public/heatmap.html create mode 100755 public/heatmap.wasm create mode 100644 public/index.bundle.js create mode 100755 public/stopwatch.wasm create mode 100644 public/todomvc.html create mode 100755 public/todomvc.wasm diff --git a/.dir-locals.el b/.dir-locals.el index f51a98f..26ad995 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -1,21 +1,13 @@ -((nil - (eval . - (setq my-proj-dir - (file-name-directory - (let ((d (dir-locals-find-file "."))) - (if (stringp d) d (car d)))) - lsp-haskell-server-path (concat my-proj-dir "/bin/haskell-language-server")))) - - (haskell-mode +((haskell-mode (haskell-process-type . ghci) (haskell-process-args-ghci . ("-ferror-spans" "-fdiagnostics-color=never")) (eval . - (setq my-proj-dir - (file-name-directory - (let ((d (dir-locals-find-file "."))) - (if (stringp d) d (car d)))) - haskell-process-path-ghci (concat my-proj-dir "bin/ghci") - haskell-hoogle-server-command - (lambda (port) - (list (concat my-proj-dir "bin/hoogle") "server" - "--local" "-p" (number-to-string port))))))) + (let ((cwd (locate-dominating-file default-directory ".dir-locals.el"))) + (setq + haskell-process-path-ghci (concat cwd "bin/ghci") + haskell-hoogle-server-command + (lambda (port) + (list (concat cwd "bin/hoogle") "server" + "--local" "-p" (number-to-string port))) + lsp-haskell-server-path (concat cwd "/bin/haskell-language-server")) + )))) diff --git a/Clickable/HTML.hs b/Clickable/HTML.hs index 828e9aa..93642a5 100644 --- a/Clickable/HTML.hs +++ b/Clickable/HTML.hs @@ -203,8 +203,11 @@ dynamicList :: forall a. dynamicList listDyn h = do place <- liftJSM insertPlaceholder initial <- readDyn listDyn - liftJSM $ execHTML (Ref place) $ liftJSM $ updateList [] initial - liftJSM $ subscribe listDyn $ execHTML (Ref place) . liftJSM . updateList undefined + liftJSM $ execHTML (Ref place) $ liftJSM $ synchronize [] initial + liftJSM $ subscribeAccum listDyn (\new old -> do + execHTML (Ref place) $ liftJSM $ synchronize old new + pure new + ) initial where synchronize :: [(ListKey, a)] -> [(ListKey, a)] -> JSM () synchronize [] [] = pure () @@ -250,9 +253,6 @@ dynamicList listDyn h = do scopeId = unListKey $ fst ie detachPlaceholder refId destroyScope scopeId - updateList :: [(ListKey, a)] -> [(ListKey, a)] -> JSM () - updateList old new = do - synchronize new old lookupOldPosition :: ListKey -> [(ListKey, a)] -> Maybe ([(ListKey, a)], [(ListKey, a)]) lookupOldPosition k = go [] where go :: [(ListKey, a)] -> [(ListKey, a)] -> Maybe ([(ListKey, a)], [(ListKey, a)]) diff --git a/Clickable/Internal.hs b/Clickable/Internal.hs index 2400117..bc5f560 100644 --- a/Clickable/Internal.hs +++ b/Clickable/Internal.hs @@ -28,7 +28,6 @@ import Foreign.Ptr import GHC.Exts import GHC.Stack import Unsafe.Coerce -import Data.Int import Data.Word newEvent :: JSM (Event a) @@ -107,6 +106,14 @@ subscribe (OverrideSub f d) k = f subscribe' k' where k' a _ = k a subscribe' c = subscribe d \a -> c a () +subscribeAccum :: Dynamic a -> (a -> b -> JSM b) -> b -> JSM () +subscribeAccum d f acc = do + ref <- liftIO $ newIORef acc + subscribe d \a -> do + b <- liftIO $ readIORef ref + b' <- f a b + liftIO $ writeIORef ref b' + triggerEvent :: Event a -> a -> JSM () triggerEvent e a = modify $ triggerEventFn e a {-# INLINE triggerEvent #-} @@ -396,7 +403,7 @@ jsEval cmd = JSM \e -> do {-# INLINE jsEval #-} jsFlush :: JSM () -jsFlush = JSM \e -> void $ e.ien_flush +jsFlush = void $ jsEval Null {-# INLINE jsFlush #-} jsUnsafe :: (HasCallStack, FromJSVal a) => UnsafeJavaScript -> JSM a diff --git a/Clickable/WASM.hs b/Clickable/WASM.hs index f71d233..41ac47f 100644 --- a/Clickable/WASM.hs +++ b/Clickable/WASM.hs @@ -47,11 +47,13 @@ buf :: CStringLen mkWasmApp :: (StartFlags -> JSM ()) -> Ptr Word8 -> IO (Ptr Word8) mkWasmApp _app p | p == nullPtr = do + putStrLn "sdlfkjns;fnsdfjn" hSetBuffering stdout LineBuffering hSetBuffering stderr LineBuffering return $ castPtr $ fst buf mkWasmApp app inmsg = do msg <- loadMessage inmsg $ snd buf + traceShowM msg case msg of Just (StartMsg flags) -> runJSM env $ app flags diff --git a/Clickable/WebSocket.hs b/Clickable/WebSocket.hs index d1edbdd..6bdf3b6 100644 --- a/Clickable/WebSocket.hs +++ b/Clickable/WebSocket.hs @@ -210,4 +210,4 @@ defaultTemplate cfg = -- yarn run webpack --mode production && cat dist-newstyle/index.bundle.js | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' jsrts :: Builder jsrts = - "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,PG:()=>RefStore,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeString(e,t),encodeValue(e,n)}))}function encodeString(e,t){const n=new Uint8Array(e.mem.buffer).subarray(e.begin+8),r=(new TextEncoder).encodeInto(t,n);e.mem.setBigUint64(e.begin,BigInt(r.written),!1),e.begin+=8+r.written}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2])}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.Ref=25]=\"Ref\",e[e.FreeScope=26]=\"FreeScope\",e[e.MoveScope=27]=\"MoveScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertPlaceholder=36]=\"InsertPlaceholder\",e[e.ClearPlaceholder=37]=\"ClearPlaceholder\",e[e.DetachPlaceholder=38]=\"DetachPlaceholder\",e[e.CreateElement=39]=\"CreateElement\",e[e.CreateElementNS=40]=\"CreateElementNS\",e[e.CreateText=41]=\"CreateText\",e[e.UpdateText=42]=\"UpdateText\",e[e.Eval=43]=\"Eval\",e[e.TriggerEvent=44]=\"TriggerEvent\",e[e.Resume=45]=\"Resume\",e[e.Out=46]=\"Out\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e){return e instanceof Comment?e.parentElement:e}function r(e){return e instanceof Comment&&\"Placeholder {{{\"==e.textContent}e.insert=t,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,r){n(e).setAttribute(t,r)},e.addEventListener=function(e,t,r){n(e).addEventListener(t,r)},e.removeEventListener=function(e,t,r){n(e).removeEventListener(t,r)},e.insertPlaceholder=function(e){const n=document.createComment(\"Placeholder {{{\"),r=document.createComment(\"}}}\");return t(e,n),t(e,r),r},e.clearPlaceholder=function(e,t){if(e instanceof Comment){let s=0;for(;e.previousSibling&&(0!=s||!r(e.previousSibling));)(n=e.previousSibling)instanceof Comment&&\"}}}\"==n.textContent?s++:r(e.previousSibling)&&s--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\";var n},e.getBuilderElement=n}(utils||(utils={}));class RefStore{constructor(e=new Map,t=new Map){this.scopes=e,this.refs=t}assignRef(e,t,n){const r=this.scopes.get(e),s=r||new Set;r||this.scopes.set(e,s),s.add(t),this.refs.set(t,n)}moveScope(e,t){const n=this.scopes.get(e),r=this.scopes.get(t);n&&r&&(n.forEach((e=>r.add(e))),this.scopes.delete(e))}freeScope(e){const t=this.scopes.get(e);t&&(t.forEach((e=>this.refs.delete(e))),this.scopes.delete(e))}}}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null,n){const r=new WebSocket(e),s={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.EventMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},resumeCont:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.ResumeMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))}};r.onopen=e=>{const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.StartMsg,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},r.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({context:s,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},r.onerror=e=>{console.error(\"WebSocket error:\",e)},r.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(5e3,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(l.set(o,t.buf),_+=o.length,r+=BigInt(o.length),o.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of o){const n=l.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(o!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),o;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),n;if(a.set(l,t.buf),o+=l.length,l.length!=t.buf_len)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let o=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,o,!0),_;if(null==f)break;if(n-onull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(i,t,n);let o=0;for(const t of l){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:_}=s.fds[e].fd_write(n);if(l!=ERRNO_SUCCESS)return i.setUint32(r,o,!0),l;if(o+=_,_!=n.byteLength)break}return i.setUint32(r,o,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,o);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,l)}return ERRNO_BADF},path_link(e,t,n,r,i,a,l){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(o.slice(a,a+l)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,l,o,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:E,fd_obj:d}=s.fds[e].path_open(t,c,i,a,l,o);if(0!=E)return E;s.fds.push(d);const R=s.fds.length-1;return f.setUint32(_,R,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const l=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return l.setUint32(a,0,!0),ERRNO_BADF;o.set(e,r),l.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const o=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(l.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(o);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(o,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:l}=Path.from(t);if(null==l)return{ret:a,fd_obj:null};let{ret:o,entry:_}=this.dir.get_entry_for_path(l);if(null==_){if(o!=ERRNO_NOENT)return{ret:o,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:l,entry:o}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==l)return i;if(null!=o){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=o.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&o instanceof Directory))return ERRNO_EXIST;if(0!=o.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||o.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(l,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:l,entry:o}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==l?{ret:i,entry:null}:null!=o?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(l,s),o=s,{ret:ERRNO_SUCCESS,entry:o})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null,n){const r={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(){},resumeCont:function(){}},s=new WASI([],[],[new OpenFile(new File([])),new OpenFile(new File([])),new OpenFile(new File([]))]);function i(e,t){const n=new DataView(inst.exports.memory.buffer),s={context:Object.assign(Object.assign({},r),{resumeCont:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.ResumeMsg,r,s]),inst.exports.wasm_app(e)},triggerEvent:function(r,s){const i={mem:n,begin:e,end:e+t};proto.ni(i,[proto.JC.EventMsg,r,s]),inst.exports.wasm_app(e)}}),mem:n,isMutableMem:!0,begin:e,end:e+t};proto.iQ(s)}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:s.wasiImport,env:{clickable_eval_buffer:i}}))).then((e=>{inst=e,s.initialize(e),e.exports.hs_init(),e.exports.wasm_app(0)}))}function evalUint8Array(e,t){const n={context:{refs:(null==t?void 0:t.refs)||new proto.PG,stack:(null==t?void 0:t.stack)||null,triggerEvent:(null==t?void 0:t.triggerEvent)||function(){},resumeCont:(null==t?void 0:t.resumeCont)||function(){}},mem:new DataView(e.buffer),isMutableMem:!1,begin:0,end:e.byteLength};return proto.iQ(n)}function evalBase64(e,t){return evalUint8Array(Uint8Array.from(atob(e),(function(e){return e.charCodeAt(0)})),t)}window.clickable={runWebsocket,runWasm,evalUint8Array,evalBase64}})();" + "(()=>{\"use strict\";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,PG:()=>RefStore,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeString(e,t),encodeValue(e,n)}))}function encodeString(e,t){const n=new Uint8Array(e.mem.buffer).subarray(e.begin+8),r=(new TextEncoder).encodeInto(t,n);e.mem.setBigUint64(e.begin,BigInt(r.written),!1),e.begin+=8+r.written}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.BeforeUnloadMsg:return e.mem.setUint8(e.begin,ClientMsgTag.BeforeUnloadMsg),void e.begin++}}!function(e){e[e.Null=0]=\"Null\",e[e.Bool=1]=\"Bool\",e[e.I8=2]=\"I8\",e[e.I16=3]=\"I16\",e[e.I32=4]=\"I32\",e[e.I64=5]=\"I64\",e[e.U8=6]=\"U8\",e[e.U16=7]=\"U16\",e[e.U32=8]=\"U32\",e[e.U64=9]=\"U64\",e[e.F32=10]=\"F32\",e[e.F64=11]=\"F64\",e[e.Str=12]=\"Str\",e[e.Arr=13]=\"Arr\",e[e.Obj=14]=\"Obj\",e[e.U8Arr=15]=\"U8Arr\",e[e.Dot=16]=\"Dot\",e[e.SetProp=17]=\"SetProp\",e[e.Ix=18]=\"Ix\",e[e.Id=19]=\"Id\",e[e.Lam=20]=\"Lam\",e[e.Arg=21]=\"Arg\",e[e.Apply=22]=\"Apply\",e[e.Call=23]=\"Call\",e[e.AssignRef=24]=\"AssignRef\",e[e.Ref=25]=\"Ref\",e[e.FreeScope=26]=\"FreeScope\",e[e.MoveScope=27]=\"MoveScope\",e[e.PeekStack=28]=\"PeekStack\",e[e.PushStack=29]=\"PushStack\",e[e.PopStack=30]=\"PopStack\",e[e.PopIns=31]=\"PopIns\",e[e.ElementProp=32]=\"ElementProp\",e[e.ElementAttr=33]=\"ElementAttr\",e[e.ClassListAdd=34]=\"ClassListAdd\",e[e.ClassListRemove=35]=\"ClassListRemove\",e[e.InsertPlaceholder=36]=\"InsertPlaceholder\",e[e.InsertPlaceholderBefore=37]=\"InsertPlaceholderBefore\",e[e.ClearPlaceholder=38]=\"ClearPlaceholder\",e[e.DetachPlaceholder=39]=\"DetachPlaceholder\",e[e.CreateElement=40]=\"CreateElement\",e[e.CreateElementNS=41]=\"CreateElementNS\",e[e.CreateText=42]=\"CreateText\",e[e.UpdateText=43]=\"UpdateText\",e[e.Eval=44]=\"Eval\",e[e.TriggerEvent=45]=\"TriggerEvent\",e[e.Resume=46]=\"Resume\",e[e.Out=47]=\"Out\"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]=\"StartMsg\",e[e.EventMsg=1]=\"EventMsg\",e[e.ResumeMsg=2]=\"ResumeMsg\",e[e.BeforeUnloadMsg=3]=\"BeforeUnloadMsg\"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder(\"utf8\");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e,t,n){const r=n instanceof Comment?function(e){let t=0;for(;;){if(!e.previousSibling||0==t&&s(e.previousSibling))return e.previousSibling;i(e.previousSibling)?t++:s(e.previousSibling)&&t--,e=e.previousSibling}}(n):n;e instanceof Comment?e.parentElement.insertBefore(t,r):e.insertBefore(t,r)}function r(e){return e instanceof Comment?e.parentElement:e}function s(e){return e instanceof Comment&&\"Placeholder {{{\"==e.textContent}function i(e){return e instanceof Comment&&\"}}}\"==e.textContent}e.insert=t,e.insertBefore=n,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertPlaceholder=function(e){const n=document.createComment(\"Placeholder {{{\"),r=document.createComment(\"}}}\");return t(e,n),t(e,r),r},e.insertPlaceholderBefore=function(e,t){const r=document.createComment(\"Placeholder {{{\"),s=document.createComment(\"}}}\");return n(e,r,t),n(e,s,t),s},e.clearPlaceholder=function(e,t){if(e instanceof Comment){let n=0;for(;e.previousSibling&&(0!=n||!s(e.previousSibling));)i(e.previousSibling)?n++:s(e.previousSibling)&&n--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=\"\"},e.getBuilderElement=r}(utils||(utils={}));class RefStore{constructor(e=new Map,t=new Map){this.scopes=e,this.refs=t}assignRef(e,t,n){const r=this.scopes.get(e),s=r||new Set;r||this.scopes.set(e,s),s.add(t),this.refs.set(t,n)}moveScope(e,t){const n=this.scopes.get(e),r=this.scopes.get(t);n&&r&&(n.forEach((e=>r.add(e))),this.scopes.delete(e))}freeScope(e){const t=this.scopes.get(e);t&&(t.forEach((e=>this.refs.delete(e))),this.scopes.delete(e))}}}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if(\"object\"==typeof globalThis)return globalThis;try{return this||new Function(\"return this\")()}catch(e){if(\"object\"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null,n){const r=new WebSocket(e),s={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.EventMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},resumeCont:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.ResumeMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))}};r.onopen=e=>{const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.StartMsg,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},r.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({context:s,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},r.onerror=e=>{console.error(\"WebSocket error:\",e)},r.onclose=t=>{console.log(\"WebSocket connection closed, reloading the tab…\"),function t(n){const r=new WebSocket(e),s=Math.min(5e3,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super(\"exit with exit code \"+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(o.set(l,t.buf),_+=l.length,r+=BigInt(l.length),l.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of l){const n=o.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(l!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),l;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(i,t,n);let l=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,l,!0),n;if(a.set(o,t.buf),l+=o.length,o.length!=t.buf_len)break}return i.setUint32(r,l,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let l=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,l,!0),_;if(null==f)break;if(n-lnull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(i,t,n);let l=0;for(const t of o){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:_}=s.fds[e].fd_write(n);if(o!=ERRNO_SUCCESS)return i.setUint32(r,l,!0),o;if(l+=_,_!=n.byteLength)break}return i.setUint32(r,l,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=new TextDecoder(\"utf-8\").decode(o.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,l);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,o){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,o)}return ERRNO_BADF},path_link(e,t,n,r,i,a,o){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder(\"utf-8\").decode(l.slice(n,n+r)),f=new TextDecoder(\"utf-8\").decode(l.slice(a,a+o)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,o,l,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder(\"utf-8\").decode(u.slice(n,n+r));debug.log(c);const{ret:d,fd_obj:E}=s.fds[e].path_open(t,c,i,a,o,l);if(0!=d)return d;s.fds.push(E);const g=s.fds.length-1;return f.setUint32(_,g,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const o=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder(\"utf-8\").decode(l.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return o.setUint32(a,0,!0),ERRNO_BADF;l.set(e,r),o.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const l=new TextDecoder(\"utf-8\").decode(o.slice(t,t+n)),_=new TextDecoder(\"utf-8\").decode(o.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(l);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(l,u,!0)!=ERRNO_SUCCESS)throw\"path_link should always return success when relinking an inode back to the original place\";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder(\"utf-8\").decode(a.slice(e,e+t)),new TextDecoder(\"utf-8\").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder(\"utf-8\").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw\"async io not supported\"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw\"raised signal \"+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log(\"readdir_single\",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,\".\",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,\"..\",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:o}=Path.from(t);if(null==o)return{ret:a,fd_obj:null};let{ret:l,entry:_}=this.dir.get_entry_for_path(o);if(null==_){if(l!=ERRNO_NOENT)return{ret:l,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:o,entry:l}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==o)return i;if(null!=l){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=l.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&l instanceof Directory))return ERRNO_EXIST;if(0!=l.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||l.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(o,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith(\"/\"),t.startsWith(\"/\"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes(\"\\0\"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split(\"/\"))if(\"\"!==e&&\".\"!==e)if(\"..\"!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join(\"/\");return this.is_dir&&(e+=\"/\"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:o,entry:l}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==o?{ret:i,entry:null}:null!=l?{ret:ERRNO_EXIST,entry:null}:(debug.log(\"create\",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(o,s),l=s,{ret:ERRNO_SUCCESS,entry:l})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder(\"utf-8\",{fatal:!1});let n=\"\";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split(\"\\n\");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null,n){const r={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(){},resumeCont:function(){}},s=new OpenFileDebug(new File([]),consoleLineBuffering(console.log)),i=new OpenFileDebug(new File([]),consoleLineBuffering(console.log));window.stdout=s,window.stderr=i;const a=new WASI([],[],[new OpenFile(new File([])),s,i]);function o(e,t){const n={context:Object.assign(Object.assign({},r),{resumeCont:function(n,r){const s={mem:new DataView(inst.exports.memory.buffer),begin:e,end:e+t};proto.ni(s,[proto.JC.ResumeMsg,n,r]),inst.exports.wasm_app(e)},triggerEvent:function(n,r){const s={mem:new DataView(inst.exports.memory.buffer),begin:e,end:e+t};proto.ni(s,[proto.JC.EventMsg,n,r]),inst.exports.wasm_app(e)}}),mem:new DataView(inst.exports.memory.buffer),isMutableMem:!0,begin:e,end:e+t};proto.iQ(n)}function l(e,t){const n=new Uint8Array(inst.exports.memory.buffer).subarray(e,e+t);return console.log(new TextDecoder(\"utf8\").decode(n))}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:a.wasiImport,env:{clickable_eval_buffer:o,console_log:l}}))).then((e=>{inst=e,a.initialize(e),e.exports.hs_init();const n=e.exports.wasm_app(0),r={mem:new DataView(e.exports.memory.buffer),begin:n,end:n+102400};proto.ni(r,[proto.JC.StartMsg,t]),e.exports.wasm_app(n),window.addEventListener(\"beforeunload\",(()=>{const t={mem:new DataView(e.exports.memory.buffer),begin:n,end:n+102400};proto.ni(t,[proto.JC.BeforeUnloadMsg]),e.exports.wasm_app(n)}))}))}class OpenFileDebug extends OpenFile{constructor(e,t){super(e),this.printDebug=t}fd_write(e){return this.printDebug(e),super.fd_write(e)}fd_pwrite(e,t){return this.printDebug(e.subarray(Number(t))),super.fd_pwrite(e,t)}}function consoleLineBuffering(e){let t=[];return n=>{const r=n=>{if(0==n.byteLength)return;const s=n.findIndex((e=>e==\"\\n\".charCodeAt(0)));if(s>=0){const i=t.map((e=>new TextDecoder(\"utf8\").decode(e))).join(\"\");t=[];const a=new TextDecoder(\"utf8\").decode(n.subarray(0,s));e(i+a),r(n.subarray(s+1))}else t.push(n.slice())};r(n)}}function evalUint8Array(e,t){const n={context:{refs:(null==t?void 0:t.refs)||new proto.PG,stack:(null==t?void 0:t.stack)||null,triggerEvent:(null==t?void 0:t.triggerEvent)||function(){},resumeCont:(null==t?void 0:t.resumeCont)||function(){}},mem:new DataView(e.buffer),isMutableMem:!1,begin:0,end:e.byteLength};return proto.iQ(n)}function evalBase64(e,t){return evalUint8Array(Uint8Array.from(atob(e),(function(e){return e.charCodeAt(0)})),t)}window.clickable={runWebsocket,runWasm,evalUint8Array,evalBase64}})();" diff --git a/examples/stopwatch/StopWatch.hs b/examples/heatmap/HeatMap.hs similarity index 89% rename from examples/stopwatch/StopWatch.hs rename to examples/heatmap/HeatMap.hs index 612044c..1abbad1 100644 --- a/examples/stopwatch/StopWatch.hs +++ b/examples/heatmap/HeatMap.hs @@ -7,16 +7,20 @@ {-# OPTIONS_GHC -Wall #-} {-# OPTIONS_GHC -Wno-unused-do-bind #-} {-# LANGUAGE DataKinds #-} -module StopWatch where +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DerivingStrategies #-} +module HeatMap where import Clickable import Data.Time import Control.Monad.IO.Class -import qualified Data.Text as Text +import Data.Text qualified as Text import Data.Text (Text) import Data.Int import Control.Monad import Data.String +import Data.Map (Map) +import GHC.Generics (Generic) data StopWatchInstance = StopWatchInstance { time_var :: DynVar (Maybe UTCTime, Maybe IntervalId) @@ -28,7 +32,7 @@ data StopWatchState = StopWatchState { } newtype IntervalId = IntervalId {unIntervalId :: Int32} - deriving (ToJSVal, FromJSVal) + deriving newtype (ToJSVal, FromJSVal) run :: JSM () run = do @@ -45,15 +49,10 @@ run = do dynText $ fmap buttonTitle $ fromVar timeVar on @"click" $ toggleState clockEv timeVar t0 <- liftIO getCurrentTime - month t0 + month $ utctDay t0 where - -- updateTime :: UTCTime -> Maybe (UTCTime, IntervalId) -> Maybe (UTCTime, IntervalId) - -- updateTime _ Nothing = Nothing - -- updateTime t (Just (_, i)) = Just (t, i) - toggleState :: Event () -> DynVar StopWatchState -> JSM () toggleState clockEv self = do - liftIO $ print $ "toggleState" s <- readVar self case s of StopWatchState Nothing Nothing -> do @@ -77,6 +76,18 @@ run = do buttonTitle (StopWatchState (Just _) (Just _)) = "Stop" buttonTitle (StopWatchState _ _) = "Reset" + +data HeatMapInstance = HeatMapInstance { + heatmap :: Map Excercise (Map Day [HMVolume]), + selected_day :: DynVar Day +} + +newtype Excercise = Excercise {unExcercise :: Text} + +data HMVolume = HMScalar Double | HMDuration Double + deriving stock (Generic) + deriving anyclass (FromJSVal, ToJSVal) + spaceKeyEvent :: Event () -> JSExp spaceKeyEvent (Event eventId) = Eval script `Apply` [Lam (TriggerEvent eventId (Arg 0))] @@ -163,18 +174,9 @@ styles = "\ \}\ \" --- Here is how to create a table using my library. Complete the --- function that builds calendar layout for given month -makeTable :: HTML () -makeTable = do - table_ [class_ "table"] do - tbody_ do - tr_ do td_ "One"; td_ "Two"; td_ "Three" - -month :: UTCTime -> HTML () -month t = do - let day = utctDay t - (y, m, _) = toGregorian day +month :: Day -> HTML () +month day = do + let (y, m, _) = toGregorian day firstDay = fromGregorian y m 1 daysInMonth = gregorianMonthLength y m firstWeekDay = dayOfWeek firstDay diff --git a/examples/stopwatch/wasm.hs b/examples/heatmap/wasm.hs similarity index 71% rename from examples/stopwatch/wasm.hs rename to examples/heatmap/wasm.hs index 9cc4440..0575e4e 100644 --- a/examples/stopwatch/wasm.hs +++ b/examples/heatmap/wasm.hs @@ -1,10 +1,10 @@ import Clickable.WASM import GHC.Ptr import GHC.Word -import StopWatch +import HeatMap main :: IO () main = return () foreign export ccall wasm_app :: Ptr Word8 -> IO (Ptr Word8) -wasm_app = mkWasmApp $ const StopWatch.run +wasm_app = mkWasmApp $ const HeatMap.run diff --git a/examples/todomvc/TodoList.hs b/examples/todomvc/TodoList.hs index a47b216..b7edb11 100644 --- a/examples/todomvc/TodoList.hs +++ b/examples/todomvc/TodoList.hs @@ -29,35 +29,55 @@ run = do items <- fromMaybe [] <$> readLocalStorage "todo-items" stateVar <- TodoList.new items installFinalizer do - s <- readVar stateVar - saveLocalStorage "todo-items" s.items + items' <- readVar stateVar.items + items'' <- mapM (\(_, t) -> readVar t) items' + saveLocalStorage "todo-items" items'' execHTMLBody do el "style" $ text TodoList.styles TodoList.view TodoList.TodoListConfig {self = stateVar} liftJSM $ addEventListener popstateEvent \loc -> do let f = fromMaybe TodoList.All $ TodoList.parseFilter loc.loc_hash - modifyVar_ stateVar \s -> s {TodoList.filter = f} + writeVar stateVar.filter f data TodoListConfig = TodoListConfig { - self :: DynVar TodoListState + self :: TodoListInstance } -data TodoListState = TodoListState { - title :: Text, - items :: [TodoItem.TodoItemState], - filter :: Filter -} deriving (Show, Eq) +data TodoListInstance = TodoListInstance { + title :: DynVar Text, + items :: DynVar [(ListKey, DynVar TodoItem.TodoItemState)], + filter :: DynVar Filter, + todo_counter :: DynVar Int +} data Filter = All | Active | Completed deriving (Show, Eq) -new :: [TodoItem.TodoItemState] -> JSM (DynVar TodoListState) -new items = - newVar TodoListState { - title = "", - items = items, - filter = All +new :: [TodoItem.TodoItemState] -> JSM TodoListInstance +new savedItems = mdo + items <- newVar =<< mapM (mkItem todo_counter) savedItems + todo_counter <- newVar =<< calculateCounter =<< readVar items + title <- newVar "" + filter <- newVar All + -- Update counter after todo-items are deleted or inserted + subscribe (fromVar items) $ writeVar todo_counter <=< calculateCounter + pure TodoListInstance { + title, + items, + filter, + todo_counter } + where + mkItem ~todoCounter i = do + key <- allocListKey + var <- overrideVar (todoItemUpdated todoCounter) <$> newVar i + pure (key, var) + +calculateCounter :: [(ListKey, DynVar TodoItem.TodoItemState)] -> JSM Int +calculateCounter = + foldM (\c (_, s) -> counter c <$> readVar s) 0 + where + counter c s | s.completed = c | otherwise = c + 1 view :: TodoListConfig -> HTML () view cfg = do @@ -71,7 +91,7 @@ view cfg = do headerWidget = header_ [class_ "header"] do h1_ (text "todos") input_ [class_ "new-todo", placeholder_ "What needs to be done?", autofocus_ True] do - dynValue $ (.title) <$> fromVar cfg.self + dynValue $ fromVar cfg.self.title on @"input" $ eval cfg . InputAction on @"keydown" $ eval cfg . KeydownAction mainWidget = section_ [class_ "main"] do @@ -82,17 +102,18 @@ view cfg = do attribute "for" "toggle-all" text "Mark all as completed" ul_ [class_ "todo-list"] do - simpleList itemsDyn \todoRef -> + pure () + dynamicList (fromVar cfg.self.items) \key todoVar -> TodoItem.view TodoItem.TodoItemConfig { - self = lensMap (_2) $ overrideVar (todoItemUpdated cfg) todoRef, - is_hidden_dyn = liftA2 isHidden (fromVar cfg.self) (fromVar todoRef), - ask_delete_item = eval cfg . DeleteItemAction . fst =<< readVar todoRef + self = todoVar, + is_hidden_dyn = liftA2 isHidden (fromVar cfg.self.filter) (fromVar todoVar), + ask_delete_item = eval cfg $ DeleteItemAction key } footerWidget = footer_ [class_ "footer"] do toggleClass "hidden" hiddenDyn span_ [class_ "todo-count"] do - strong_ $ dynText $ Text.pack . show <$> itemsLeftDyn - dynText $ pluralize " item left" " items left" <$> itemsLeftDyn + strong_ $ dynText $ Text.pack . show <$> fromVar cfg.self.todo_counter + dynText $ pluralize " item left" " items left" <$> fromVar cfg.self.todo_counter ul_ [class_ "filters"] do forM_ [All, Active, Completed] filterWidget button_ [class_ "clear-completed"] do @@ -109,22 +130,13 @@ view cfg = do filterWidget :: Filter -> HTML () filterWidget flt = li_ do a_ [href_ (printFilter flt)] do - toggleClass "selected" $ filterSelectedDyn flt + toggleClass "selected" $ fmap (== flt) $ fromVar cfg.self.filter text $ Text.pack $ show flt hiddenDyn = - Prelude.null . (.items) <$> fromVar cfg.self - itemsLeftDyn = - countItemsLeft <$> fromVar cfg.self - filterSelectedDyn flt = - (==flt) . (.filter) <$> fromVar cfg.self - itemsDyn :: Dynamic [(Int, TodoItem.TodoItemState)] - itemsDyn = (\s -> zip [0..] s.items) <$> fromVar cfg.self - countItemsLeft TodoListState{items} = - foldl (\acc TodoItem.TodoItemState{completed} -> - if not completed then acc + 1 else acc) 0 items - isHidden :: TodoListState -> (Int, TodoItem.TodoItemState) -> Bool - isHidden listState (_, itemState) = - case (listState.filter, itemState.completed) of + fmap List.null $ fromVar cfg.self.items + isHidden :: Filter -> TodoItem.TodoItemState -> Bool + isHidden f itemState = + case (f, itemState.completed) of (Active, True) -> True (Completed, False) -> True _ -> False @@ -134,63 +146,63 @@ data TodoListAction a where InputAction :: Text -> TodoListAction () CommitAction :: TodoListAction () KeydownAction :: Int32 -> TodoListAction () - DeleteItemAction :: Int -> TodoListAction () + DeleteItemAction :: ListKey -> TodoListAction () ClearCompletedAction :: TodoListAction () eval :: TodoListConfig -> TodoListAction a -> JSM a -eval cfg (ToggleAllAction isChecked) = - modifyVar_ cfg.self \s -> s { - items = fmap (\i -> i {TodoItem.completed = isChecked}) s.items - } +eval cfg (ToggleAllAction isChecked) = do + items <- readVar cfg.self.items + forM_ items \(_, s) -> + modifyVar_ s \i -> i {TodoItem.completed = isChecked} + eval cfg (InputAction newVal) = - modifyVar_ cfg.self \s -> s {title = newVal} + writeVar cfg.self.title newVal eval cfg CommitAction = do - title <- Text.strip . (.title) <$> readVar cfg.self + title <- Text.strip <$> readVar cfg.self.title case title of - "" -> return () - t -> modifyVar_ cfg.self \s -> s { - items = s.items <> [newTodo t], - title = "" - } + "" -> pure () + t -> do + todo <- newTodo t + modifyVar_ cfg.self.items (<> [todo]) + writeVar cfg.self.title "" where - newTodo t = TodoItem.emptyState {TodoItem.title = t} + newTodo t = do + key <- allocListKey + var <- fmap (overrideVar (todoItemUpdated cfg.self.todo_counter)) $ + newVar $ TodoItem.emptyState {TodoItem.title = t} + pure (key, var) eval cfg (KeydownAction key) = case key of 13 {- Enter -} -> eval cfg CommitAction _ -> return () -eval cfg (DeleteItemAction itemIx) = - modifyVar_ cfg.self \s -> s {items = deleteIx itemIx s.items} +eval cfg (DeleteItemAction key) = + modifyVar_ cfg.self.items $ deleteKey key where - deleteIx :: Int -> [a] -> [a] - deleteIx _ [] = [] - deleteIx i (a:as) | i == 0 = as | otherwise = a : deleteIx (i-1) as -eval cfg ClearCompletedAction = - modifyVar_ cfg.self \s -> s - {items = (List.filter (not . TodoItem.completed)) s.items} + deleteKey _ [] = [] + deleteKey k ((k', a):as) + | k == k' = as + | otherwise = (k', a) : deleteKey k as +eval cfg ClearCompletedAction = do + items <- readVar cfg.self.items + items' <- filterM (\(_, v) -> not . (.completed) <$> readVar v) items + writeVar cfg.self.items items' -- | Synchronize TodoItem state with the larger state of TodoList -- widget. todoItemUpdated :: - TodoListConfig -> - UpdateFn (Int, TodoItem.TodoItemState) -> - UpdateFn (Int, TodoItem.TodoItemState) -todoItemUpdated cfg next f = do + DynVar Int -> + UpdateFn TodoItem.TodoItemState -> + UpdateFn TodoItem.TodoItemState +todoItemUpdated ~todoCounter next f = do -- Update the local TodoItemState ((s, s'), result) <- next g -- Filter out irrelevant updates - let needPropagateUpdate = (snd s).completed /= (snd s').completed - -- Update the same item in the larger TodoListState - if needPropagateUpdate - then modifyVar cfg.self $ h s' - else modifyVarQuiet cfg.self $ h s' + case (s.completed, s'.completed) of + (True, False) -> modifyVar_ todoCounter (+1) + (False, True) -> modifyVar_ todoCounter (+ (-1)) + _ -> pure () pure result where g s = let (s', a) = f s in (s', ((s, s'), a)) - h (i, e) s = (s {items = updateIx i e s.items}, ()) - - updateIx :: Int -> a -> [a] -> [a] - updateIx 0 a (_:xs) = a : xs - updateIx n a (x:xs) = x : updateIx (pred n) a xs - updateIx _ _ [] = [] pluralize :: Text -> Text -> Int -> Text pluralize singular _plural 0 = singular @@ -207,13 +219,6 @@ printFilter All = "#/" printFilter Active = "#/active" printFilter Completed = "#/completed" --- TODO: rewrite without lenses -_2 :: Lens' (a, b) b -_2 f a = fmap (setter a) (f (getter a)) - where - setter (a', _) c = (a', c) - getter (_, b) = b - styles :: Text styles = "\ \body {\ diff --git a/hie.yaml b/hie.yaml index ddfc1ba..dc4e783 100644 --- a/hie.yaml +++ b/hie.yaml @@ -1,3 +1,3 @@ cradle: direct: - arguments: [-i./examples/todomvc] + arguments: ["-i./examples/todomvc", "-i./examples/heatmap"] diff --git a/public/bootstrap-icons.css b/public/bootstrap-icons.css new file mode 100644 index 0000000..bc84a5f --- /dev/null +++ b/public/bootstrap-icons.css @@ -0,0 +1,2078 @@ +/*! + * Bootstrap Icons v1.11.3 (https://icons.getbootstrap.com/) + * Copyright 2019-2024 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */ + +@font-face { + font-display: block; + font-family: "bootstrap-icons"; + src: url("./fonts/bootstrap-icons.woff2?dd67030699838ea613ee6dbda90effa6") format("woff2"), +url("./fonts/bootstrap-icons.woff?dd67030699838ea613ee6dbda90effa6") format("woff"); +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-123::before { content: "\f67f"; } +.bi-alarm-fill::before { content: "\f101"; } +.bi-alarm::before { content: "\f102"; } +.bi-align-bottom::before { content: "\f103"; } +.bi-align-center::before { content: "\f104"; } +.bi-align-end::before { content: "\f105"; } +.bi-align-middle::before { content: "\f106"; } +.bi-align-start::before { content: "\f107"; } +.bi-align-top::before { content: "\f108"; } +.bi-alt::before { content: "\f109"; } +.bi-app-indicator::before { content: "\f10a"; } +.bi-app::before { content: "\f10b"; } +.bi-archive-fill::before { content: "\f10c"; } +.bi-archive::before { content: "\f10d"; } +.bi-arrow-90deg-down::before { content: "\f10e"; } +.bi-arrow-90deg-left::before { content: "\f10f"; } +.bi-arrow-90deg-right::before { content: "\f110"; } +.bi-arrow-90deg-up::before { content: "\f111"; } +.bi-arrow-bar-down::before { content: "\f112"; } +.bi-arrow-bar-left::before { content: "\f113"; } +.bi-arrow-bar-right::before { content: "\f114"; } +.bi-arrow-bar-up::before { content: "\f115"; } +.bi-arrow-clockwise::before { content: "\f116"; } +.bi-arrow-counterclockwise::before { content: "\f117"; } +.bi-arrow-down-circle-fill::before { content: "\f118"; } +.bi-arrow-down-circle::before { content: "\f119"; } +.bi-arrow-down-left-circle-fill::before { content: "\f11a"; } +.bi-arrow-down-left-circle::before { content: "\f11b"; } +.bi-arrow-down-left-square-fill::before { content: "\f11c"; } +.bi-arrow-down-left-square::before { content: "\f11d"; } +.bi-arrow-down-left::before { content: "\f11e"; } +.bi-arrow-down-right-circle-fill::before { content: "\f11f"; } +.bi-arrow-down-right-circle::before { content: "\f120"; } +.bi-arrow-down-right-square-fill::before { content: "\f121"; } +.bi-arrow-down-right-square::before { content: "\f122"; } +.bi-arrow-down-right::before { content: "\f123"; } +.bi-arrow-down-short::before { content: "\f124"; } +.bi-arrow-down-square-fill::before { content: "\f125"; } +.bi-arrow-down-square::before { content: "\f126"; } +.bi-arrow-down-up::before { content: "\f127"; } +.bi-arrow-down::before { content: "\f128"; } +.bi-arrow-left-circle-fill::before { content: "\f129"; } +.bi-arrow-left-circle::before { content: "\f12a"; } +.bi-arrow-left-right::before { content: "\f12b"; } +.bi-arrow-left-short::before { content: "\f12c"; } +.bi-arrow-left-square-fill::before { content: "\f12d"; } +.bi-arrow-left-square::before { content: "\f12e"; } +.bi-arrow-left::before { content: "\f12f"; } +.bi-arrow-repeat::before { content: "\f130"; } +.bi-arrow-return-left::before { content: "\f131"; } +.bi-arrow-return-right::before { content: "\f132"; } +.bi-arrow-right-circle-fill::before { content: "\f133"; } +.bi-arrow-right-circle::before { content: "\f134"; } +.bi-arrow-right-short::before { content: "\f135"; } +.bi-arrow-right-square-fill::before { content: "\f136"; } +.bi-arrow-right-square::before { content: "\f137"; } +.bi-arrow-right::before { content: "\f138"; } +.bi-arrow-up-circle-fill::before { content: "\f139"; } +.bi-arrow-up-circle::before { content: "\f13a"; } +.bi-arrow-up-left-circle-fill::before { content: "\f13b"; } +.bi-arrow-up-left-circle::before { content: "\f13c"; } +.bi-arrow-up-left-square-fill::before { content: "\f13d"; } +.bi-arrow-up-left-square::before { content: "\f13e"; } +.bi-arrow-up-left::before { content: "\f13f"; } +.bi-arrow-up-right-circle-fill::before { content: "\f140"; } +.bi-arrow-up-right-circle::before { content: "\f141"; } +.bi-arrow-up-right-square-fill::before { content: "\f142"; } +.bi-arrow-up-right-square::before { content: "\f143"; } +.bi-arrow-up-right::before { content: "\f144"; } +.bi-arrow-up-short::before { content: "\f145"; } +.bi-arrow-up-square-fill::before { content: "\f146"; } +.bi-arrow-up-square::before { content: "\f147"; } +.bi-arrow-up::before { content: "\f148"; } +.bi-arrows-angle-contract::before { content: "\f149"; } +.bi-arrows-angle-expand::before { content: "\f14a"; } +.bi-arrows-collapse::before { content: "\f14b"; } +.bi-arrows-expand::before { content: "\f14c"; } +.bi-arrows-fullscreen::before { content: "\f14d"; } +.bi-arrows-move::before { content: "\f14e"; } +.bi-aspect-ratio-fill::before { content: "\f14f"; } +.bi-aspect-ratio::before { content: "\f150"; } +.bi-asterisk::before { content: "\f151"; } +.bi-at::before { content: "\f152"; } +.bi-award-fill::before { content: "\f153"; } +.bi-award::before { content: "\f154"; } +.bi-back::before { content: "\f155"; } +.bi-backspace-fill::before { content: "\f156"; } +.bi-backspace-reverse-fill::before { content: "\f157"; } +.bi-backspace-reverse::before { content: "\f158"; } +.bi-backspace::before { content: "\f159"; } +.bi-badge-3d-fill::before { content: "\f15a"; } +.bi-badge-3d::before { content: "\f15b"; } +.bi-badge-4k-fill::before { content: "\f15c"; } +.bi-badge-4k::before { content: "\f15d"; } +.bi-badge-8k-fill::before { content: "\f15e"; } +.bi-badge-8k::before { content: "\f15f"; } +.bi-badge-ad-fill::before { content: "\f160"; } +.bi-badge-ad::before { content: "\f161"; } +.bi-badge-ar-fill::before { content: "\f162"; } +.bi-badge-ar::before { content: "\f163"; } +.bi-badge-cc-fill::before { content: "\f164"; } +.bi-badge-cc::before { content: "\f165"; } +.bi-badge-hd-fill::before { content: "\f166"; } +.bi-badge-hd::before { content: "\f167"; } +.bi-badge-tm-fill::before { content: "\f168"; } +.bi-badge-tm::before { content: "\f169"; } +.bi-badge-vo-fill::before { content: "\f16a"; } +.bi-badge-vo::before { content: "\f16b"; } +.bi-badge-vr-fill::before { content: "\f16c"; } +.bi-badge-vr::before { content: "\f16d"; } +.bi-badge-wc-fill::before { content: "\f16e"; } +.bi-badge-wc::before { content: "\f16f"; } +.bi-bag-check-fill::before { content: "\f170"; } +.bi-bag-check::before { content: "\f171"; } +.bi-bag-dash-fill::before { content: "\f172"; } +.bi-bag-dash::before { content: "\f173"; } +.bi-bag-fill::before { content: "\f174"; } +.bi-bag-plus-fill::before { content: "\f175"; } +.bi-bag-plus::before { content: "\f176"; } +.bi-bag-x-fill::before { content: "\f177"; } +.bi-bag-x::before { content: "\f178"; } +.bi-bag::before { content: "\f179"; } +.bi-bar-chart-fill::before { content: "\f17a"; } +.bi-bar-chart-line-fill::before { content: "\f17b"; } +.bi-bar-chart-line::before { content: "\f17c"; } +.bi-bar-chart-steps::before { content: "\f17d"; } +.bi-bar-chart::before { content: "\f17e"; } +.bi-basket-fill::before { content: "\f17f"; } +.bi-basket::before { content: "\f180"; } +.bi-basket2-fill::before { content: "\f181"; } +.bi-basket2::before { content: "\f182"; } +.bi-basket3-fill::before { content: "\f183"; } +.bi-basket3::before { content: "\f184"; } +.bi-battery-charging::before { content: "\f185"; } +.bi-battery-full::before { content: "\f186"; } +.bi-battery-half::before { content: "\f187"; } +.bi-battery::before { content: "\f188"; } +.bi-bell-fill::before { content: "\f189"; } +.bi-bell::before { content: "\f18a"; } +.bi-bezier::before { content: "\f18b"; } +.bi-bezier2::before { content: "\f18c"; } +.bi-bicycle::before { content: "\f18d"; } +.bi-binoculars-fill::before { content: "\f18e"; } +.bi-binoculars::before { content: "\f18f"; } +.bi-blockquote-left::before { content: "\f190"; } +.bi-blockquote-right::before { content: "\f191"; } +.bi-book-fill::before { content: "\f192"; } +.bi-book-half::before { content: "\f193"; } +.bi-book::before { content: "\f194"; } +.bi-bookmark-check-fill::before { content: "\f195"; } +.bi-bookmark-check::before { content: "\f196"; } +.bi-bookmark-dash-fill::before { content: "\f197"; } +.bi-bookmark-dash::before { content: "\f198"; } +.bi-bookmark-fill::before { content: "\f199"; } +.bi-bookmark-heart-fill::before { content: "\f19a"; } +.bi-bookmark-heart::before { content: "\f19b"; } +.bi-bookmark-plus-fill::before { content: "\f19c"; } +.bi-bookmark-plus::before { content: "\f19d"; } +.bi-bookmark-star-fill::before { content: "\f19e"; } +.bi-bookmark-star::before { content: "\f19f"; } +.bi-bookmark-x-fill::before { content: "\f1a0"; } +.bi-bookmark-x::before { content: "\f1a1"; } +.bi-bookmark::before { content: "\f1a2"; } +.bi-bookmarks-fill::before { content: "\f1a3"; } +.bi-bookmarks::before { content: "\f1a4"; } +.bi-bookshelf::before { content: "\f1a5"; } +.bi-bootstrap-fill::before { content: "\f1a6"; } +.bi-bootstrap-reboot::before { content: "\f1a7"; } +.bi-bootstrap::before { content: "\f1a8"; } +.bi-border-all::before { content: "\f1a9"; } +.bi-border-bottom::before { content: "\f1aa"; } +.bi-border-center::before { content: "\f1ab"; } +.bi-border-inner::before { content: "\f1ac"; } +.bi-border-left::before { content: "\f1ad"; } +.bi-border-middle::before { content: "\f1ae"; } +.bi-border-outer::before { content: "\f1af"; } +.bi-border-right::before { content: "\f1b0"; } +.bi-border-style::before { content: "\f1b1"; } +.bi-border-top::before { content: "\f1b2"; } +.bi-border-width::before { content: "\f1b3"; } +.bi-border::before { content: "\f1b4"; } +.bi-bounding-box-circles::before { content: "\f1b5"; } +.bi-bounding-box::before { content: "\f1b6"; } +.bi-box-arrow-down-left::before { content: "\f1b7"; } +.bi-box-arrow-down-right::before { content: "\f1b8"; } +.bi-box-arrow-down::before { content: "\f1b9"; } +.bi-box-arrow-in-down-left::before { content: "\f1ba"; } +.bi-box-arrow-in-down-right::before { content: "\f1bb"; } +.bi-box-arrow-in-down::before { content: "\f1bc"; } +.bi-box-arrow-in-left::before { content: "\f1bd"; } +.bi-box-arrow-in-right::before { content: "\f1be"; } +.bi-box-arrow-in-up-left::before { content: "\f1bf"; } +.bi-box-arrow-in-up-right::before { content: "\f1c0"; } +.bi-box-arrow-in-up::before { content: "\f1c1"; } +.bi-box-arrow-left::before { content: "\f1c2"; } +.bi-box-arrow-right::before { content: "\f1c3"; } +.bi-box-arrow-up-left::before { content: "\f1c4"; } +.bi-box-arrow-up-right::before { content: "\f1c5"; } +.bi-box-arrow-up::before { content: "\f1c6"; } +.bi-box-seam::before { content: "\f1c7"; } +.bi-box::before { content: "\f1c8"; } +.bi-braces::before { content: "\f1c9"; } +.bi-bricks::before { content: "\f1ca"; } +.bi-briefcase-fill::before { content: "\f1cb"; } +.bi-briefcase::before { content: "\f1cc"; } +.bi-brightness-alt-high-fill::before { content: "\f1cd"; } +.bi-brightness-alt-high::before { content: "\f1ce"; } +.bi-brightness-alt-low-fill::before { content: "\f1cf"; } +.bi-brightness-alt-low::before { content: "\f1d0"; } +.bi-brightness-high-fill::before { content: "\f1d1"; } +.bi-brightness-high::before { content: "\f1d2"; } +.bi-brightness-low-fill::before { content: "\f1d3"; } +.bi-brightness-low::before { content: "\f1d4"; } +.bi-broadcast-pin::before { content: "\f1d5"; } +.bi-broadcast::before { content: "\f1d6"; } +.bi-brush-fill::before { content: "\f1d7"; } +.bi-brush::before { content: "\f1d8"; } +.bi-bucket-fill::before { content: "\f1d9"; } +.bi-bucket::before { content: "\f1da"; } +.bi-bug-fill::before { content: "\f1db"; } +.bi-bug::before { content: "\f1dc"; } +.bi-building::before { content: "\f1dd"; } +.bi-bullseye::before { content: "\f1de"; } +.bi-calculator-fill::before { content: "\f1df"; } +.bi-calculator::before { content: "\f1e0"; } +.bi-calendar-check-fill::before { content: "\f1e1"; } +.bi-calendar-check::before { content: "\f1e2"; } +.bi-calendar-date-fill::before { content: "\f1e3"; } +.bi-calendar-date::before { content: "\f1e4"; } +.bi-calendar-day-fill::before { content: "\f1e5"; } +.bi-calendar-day::before { content: "\f1e6"; } +.bi-calendar-event-fill::before { content: "\f1e7"; } +.bi-calendar-event::before { content: "\f1e8"; } +.bi-calendar-fill::before { content: "\f1e9"; } +.bi-calendar-minus-fill::before { content: "\f1ea"; } +.bi-calendar-minus::before { content: "\f1eb"; } +.bi-calendar-month-fill::before { content: "\f1ec"; } +.bi-calendar-month::before { content: "\f1ed"; } +.bi-calendar-plus-fill::before { content: "\f1ee"; } +.bi-calendar-plus::before { content: "\f1ef"; } +.bi-calendar-range-fill::before { content: "\f1f0"; } +.bi-calendar-range::before { content: "\f1f1"; } +.bi-calendar-week-fill::before { content: "\f1f2"; } +.bi-calendar-week::before { content: "\f1f3"; } +.bi-calendar-x-fill::before { content: "\f1f4"; } +.bi-calendar-x::before { content: "\f1f5"; } +.bi-calendar::before { content: "\f1f6"; } +.bi-calendar2-check-fill::before { content: "\f1f7"; } +.bi-calendar2-check::before { content: "\f1f8"; } +.bi-calendar2-date-fill::before { content: "\f1f9"; } +.bi-calendar2-date::before { content: "\f1fa"; } +.bi-calendar2-day-fill::before { content: "\f1fb"; } +.bi-calendar2-day::before { content: "\f1fc"; } +.bi-calendar2-event-fill::before { content: "\f1fd"; } +.bi-calendar2-event::before { content: "\f1fe"; } +.bi-calendar2-fill::before { content: "\f1ff"; } +.bi-calendar2-minus-fill::before { content: "\f200"; } +.bi-calendar2-minus::before { content: "\f201"; } +.bi-calendar2-month-fill::before { content: "\f202"; } +.bi-calendar2-month::before { content: "\f203"; } +.bi-calendar2-plus-fill::before { content: "\f204"; } +.bi-calendar2-plus::before { content: "\f205"; } +.bi-calendar2-range-fill::before { content: "\f206"; } +.bi-calendar2-range::before { content: "\f207"; } +.bi-calendar2-week-fill::before { content: "\f208"; } +.bi-calendar2-week::before { content: "\f209"; } +.bi-calendar2-x-fill::before { content: "\f20a"; } +.bi-calendar2-x::before { content: "\f20b"; } +.bi-calendar2::before { content: "\f20c"; } +.bi-calendar3-event-fill::before { content: "\f20d"; } +.bi-calendar3-event::before { content: "\f20e"; } +.bi-calendar3-fill::before { content: "\f20f"; } +.bi-calendar3-range-fill::before { content: "\f210"; } +.bi-calendar3-range::before { content: "\f211"; } +.bi-calendar3-week-fill::before { content: "\f212"; } +.bi-calendar3-week::before { content: "\f213"; } +.bi-calendar3::before { content: "\f214"; } +.bi-calendar4-event::before { content: "\f215"; } +.bi-calendar4-range::before { content: "\f216"; } +.bi-calendar4-week::before { content: "\f217"; } +.bi-calendar4::before { content: "\f218"; } +.bi-camera-fill::before { content: "\f219"; } +.bi-camera-reels-fill::before { content: "\f21a"; } +.bi-camera-reels::before { content: "\f21b"; } +.bi-camera-video-fill::before { content: "\f21c"; } +.bi-camera-video-off-fill::before { content: "\f21d"; } +.bi-camera-video-off::before { content: "\f21e"; } +.bi-camera-video::before { content: "\f21f"; } +.bi-camera::before { content: "\f220"; } +.bi-camera2::before { content: "\f221"; } +.bi-capslock-fill::before { content: "\f222"; } +.bi-capslock::before { content: "\f223"; } +.bi-card-checklist::before { content: "\f224"; } +.bi-card-heading::before { content: "\f225"; } +.bi-card-image::before { content: "\f226"; } +.bi-card-list::before { content: "\f227"; } +.bi-card-text::before { content: "\f228"; } +.bi-caret-down-fill::before { content: "\f229"; } +.bi-caret-down-square-fill::before { content: "\f22a"; } +.bi-caret-down-square::before { content: "\f22b"; } +.bi-caret-down::before { content: "\f22c"; } +.bi-caret-left-fill::before { content: "\f22d"; } +.bi-caret-left-square-fill::before { content: "\f22e"; } +.bi-caret-left-square::before { content: "\f22f"; } +.bi-caret-left::before { content: "\f230"; } +.bi-caret-right-fill::before { content: "\f231"; } +.bi-caret-right-square-fill::before { content: "\f232"; } +.bi-caret-right-square::before { content: "\f233"; } +.bi-caret-right::before { content: "\f234"; } +.bi-caret-up-fill::before { content: "\f235"; } +.bi-caret-up-square-fill::before { content: "\f236"; } +.bi-caret-up-square::before { content: "\f237"; } +.bi-caret-up::before { content: "\f238"; } +.bi-cart-check-fill::before { content: "\f239"; } +.bi-cart-check::before { content: "\f23a"; } +.bi-cart-dash-fill::before { content: "\f23b"; } +.bi-cart-dash::before { content: "\f23c"; } +.bi-cart-fill::before { content: "\f23d"; } +.bi-cart-plus-fill::before { content: "\f23e"; } +.bi-cart-plus::before { content: "\f23f"; } +.bi-cart-x-fill::before { content: "\f240"; } +.bi-cart-x::before { content: "\f241"; } +.bi-cart::before { content: "\f242"; } +.bi-cart2::before { content: "\f243"; } +.bi-cart3::before { content: "\f244"; } +.bi-cart4::before { content: "\f245"; } +.bi-cash-stack::before { content: "\f246"; } +.bi-cash::before { content: "\f247"; } +.bi-cast::before { content: "\f248"; } +.bi-chat-dots-fill::before { content: "\f249"; } +.bi-chat-dots::before { content: "\f24a"; } +.bi-chat-fill::before { content: "\f24b"; } +.bi-chat-left-dots-fill::before { content: "\f24c"; } +.bi-chat-left-dots::before { content: "\f24d"; } +.bi-chat-left-fill::before { content: "\f24e"; } +.bi-chat-left-quote-fill::before { content: "\f24f"; } +.bi-chat-left-quote::before { content: "\f250"; } +.bi-chat-left-text-fill::before { content: "\f251"; } +.bi-chat-left-text::before { content: "\f252"; } +.bi-chat-left::before { content: "\f253"; } +.bi-chat-quote-fill::before { content: "\f254"; } +.bi-chat-quote::before { content: "\f255"; } +.bi-chat-right-dots-fill::before { content: "\f256"; } +.bi-chat-right-dots::before { content: "\f257"; } +.bi-chat-right-fill::before { content: "\f258"; } +.bi-chat-right-quote-fill::before { content: "\f259"; } +.bi-chat-right-quote::before { content: "\f25a"; } +.bi-chat-right-text-fill::before { content: "\f25b"; } +.bi-chat-right-text::before { content: "\f25c"; } +.bi-chat-right::before { content: "\f25d"; } +.bi-chat-square-dots-fill::before { content: "\f25e"; } +.bi-chat-square-dots::before { content: "\f25f"; } +.bi-chat-square-fill::before { content: "\f260"; } +.bi-chat-square-quote-fill::before { content: "\f261"; } +.bi-chat-square-quote::before { content: "\f262"; } +.bi-chat-square-text-fill::before { content: "\f263"; } +.bi-chat-square-text::before { content: "\f264"; } +.bi-chat-square::before { content: "\f265"; } +.bi-chat-text-fill::before { content: "\f266"; } +.bi-chat-text::before { content: "\f267"; } +.bi-chat::before { content: "\f268"; } +.bi-check-all::before { content: "\f269"; } +.bi-check-circle-fill::before { content: "\f26a"; } +.bi-check-circle::before { content: "\f26b"; } +.bi-check-square-fill::before { content: "\f26c"; } +.bi-check-square::before { content: "\f26d"; } +.bi-check::before { content: "\f26e"; } +.bi-check2-all::before { content: "\f26f"; } +.bi-check2-circle::before { content: "\f270"; } +.bi-check2-square::before { content: "\f271"; } +.bi-check2::before { content: "\f272"; } +.bi-chevron-bar-contract::before { content: "\f273"; } +.bi-chevron-bar-down::before { content: "\f274"; } +.bi-chevron-bar-expand::before { content: "\f275"; } +.bi-chevron-bar-left::before { content: "\f276"; } +.bi-chevron-bar-right::before { content: "\f277"; } +.bi-chevron-bar-up::before { content: "\f278"; } +.bi-chevron-compact-down::before { content: "\f279"; } +.bi-chevron-compact-left::before { content: "\f27a"; } +.bi-chevron-compact-right::before { content: "\f27b"; } +.bi-chevron-compact-up::before { content: "\f27c"; } +.bi-chevron-contract::before { content: "\f27d"; } +.bi-chevron-double-down::before { content: "\f27e"; } +.bi-chevron-double-left::before { content: "\f27f"; } +.bi-chevron-double-right::before { content: "\f280"; } +.bi-chevron-double-up::before { content: "\f281"; } +.bi-chevron-down::before { content: "\f282"; } +.bi-chevron-expand::before { content: "\f283"; } +.bi-chevron-left::before { content: "\f284"; } +.bi-chevron-right::before { content: "\f285"; } +.bi-chevron-up::before { content: "\f286"; } +.bi-circle-fill::before { content: "\f287"; } +.bi-circle-half::before { content: "\f288"; } +.bi-circle-square::before { content: "\f289"; } +.bi-circle::before { content: "\f28a"; } +.bi-clipboard-check::before { content: "\f28b"; } +.bi-clipboard-data::before { content: "\f28c"; } +.bi-clipboard-minus::before { content: "\f28d"; } +.bi-clipboard-plus::before { content: "\f28e"; } +.bi-clipboard-x::before { content: "\f28f"; } +.bi-clipboard::before { content: "\f290"; } +.bi-clock-fill::before { content: "\f291"; } +.bi-clock-history::before { content: "\f292"; } +.bi-clock::before { content: "\f293"; } +.bi-cloud-arrow-down-fill::before { content: "\f294"; } +.bi-cloud-arrow-down::before { content: "\f295"; } +.bi-cloud-arrow-up-fill::before { content: "\f296"; } +.bi-cloud-arrow-up::before { content: "\f297"; } +.bi-cloud-check-fill::before { content: "\f298"; } +.bi-cloud-check::before { content: "\f299"; } +.bi-cloud-download-fill::before { content: "\f29a"; } +.bi-cloud-download::before { content: "\f29b"; } +.bi-cloud-drizzle-fill::before { content: "\f29c"; } +.bi-cloud-drizzle::before { content: "\f29d"; } +.bi-cloud-fill::before { content: "\f29e"; } +.bi-cloud-fog-fill::before { content: "\f29f"; } +.bi-cloud-fog::before { content: "\f2a0"; } +.bi-cloud-fog2-fill::before { content: "\f2a1"; } +.bi-cloud-fog2::before { content: "\f2a2"; } +.bi-cloud-hail-fill::before { content: "\f2a3"; } +.bi-cloud-hail::before { content: "\f2a4"; } +.bi-cloud-haze-fill::before { content: "\f2a6"; } +.bi-cloud-haze::before { content: "\f2a7"; } +.bi-cloud-haze2-fill::before { content: "\f2a8"; } +.bi-cloud-lightning-fill::before { content: "\f2a9"; } +.bi-cloud-lightning-rain-fill::before { content: "\f2aa"; } +.bi-cloud-lightning-rain::before { content: "\f2ab"; } +.bi-cloud-lightning::before { content: "\f2ac"; } +.bi-cloud-minus-fill::before { content: "\f2ad"; } +.bi-cloud-minus::before { content: "\f2ae"; } +.bi-cloud-moon-fill::before { content: "\f2af"; } +.bi-cloud-moon::before { content: "\f2b0"; } +.bi-cloud-plus-fill::before { content: "\f2b1"; } +.bi-cloud-plus::before { content: "\f2b2"; } +.bi-cloud-rain-fill::before { content: "\f2b3"; } +.bi-cloud-rain-heavy-fill::before { content: "\f2b4"; } +.bi-cloud-rain-heavy::before { content: "\f2b5"; } +.bi-cloud-rain::before { content: "\f2b6"; } +.bi-cloud-slash-fill::before { content: "\f2b7"; } +.bi-cloud-slash::before { content: "\f2b8"; } +.bi-cloud-sleet-fill::before { content: "\f2b9"; } +.bi-cloud-sleet::before { content: "\f2ba"; } +.bi-cloud-snow-fill::before { content: "\f2bb"; } +.bi-cloud-snow::before { content: "\f2bc"; } +.bi-cloud-sun-fill::before { content: "\f2bd"; } +.bi-cloud-sun::before { content: "\f2be"; } +.bi-cloud-upload-fill::before { content: "\f2bf"; } +.bi-cloud-upload::before { content: "\f2c0"; } +.bi-cloud::before { content: "\f2c1"; } +.bi-clouds-fill::before { content: "\f2c2"; } +.bi-clouds::before { content: "\f2c3"; } +.bi-cloudy-fill::before { content: "\f2c4"; } +.bi-cloudy::before { content: "\f2c5"; } +.bi-code-slash::before { content: "\f2c6"; } +.bi-code-square::before { content: "\f2c7"; } +.bi-code::before { content: "\f2c8"; } +.bi-collection-fill::before { content: "\f2c9"; } +.bi-collection-play-fill::before { content: "\f2ca"; } +.bi-collection-play::before { content: "\f2cb"; } +.bi-collection::before { content: "\f2cc"; } +.bi-columns-gap::before { content: "\f2cd"; } +.bi-columns::before { content: "\f2ce"; } +.bi-command::before { content: "\f2cf"; } +.bi-compass-fill::before { content: "\f2d0"; } +.bi-compass::before { content: "\f2d1"; } +.bi-cone-striped::before { content: "\f2d2"; } +.bi-cone::before { content: "\f2d3"; } +.bi-controller::before { content: "\f2d4"; } +.bi-cpu-fill::before { content: "\f2d5"; } +.bi-cpu::before { content: "\f2d6"; } +.bi-credit-card-2-back-fill::before { content: "\f2d7"; } +.bi-credit-card-2-back::before { content: "\f2d8"; } +.bi-credit-card-2-front-fill::before { content: "\f2d9"; } +.bi-credit-card-2-front::before { content: "\f2da"; } +.bi-credit-card-fill::before { content: "\f2db"; } +.bi-credit-card::before { content: "\f2dc"; } +.bi-crop::before { content: "\f2dd"; } +.bi-cup-fill::before { content: "\f2de"; } +.bi-cup-straw::before { content: "\f2df"; } +.bi-cup::before { content: "\f2e0"; } +.bi-cursor-fill::before { content: "\f2e1"; } +.bi-cursor-text::before { content: "\f2e2"; } +.bi-cursor::before { content: "\f2e3"; } +.bi-dash-circle-dotted::before { content: "\f2e4"; } +.bi-dash-circle-fill::before { content: "\f2e5"; } +.bi-dash-circle::before { content: "\f2e6"; } +.bi-dash-square-dotted::before { content: "\f2e7"; } +.bi-dash-square-fill::before { content: "\f2e8"; } +.bi-dash-square::before { content: "\f2e9"; } +.bi-dash::before { content: "\f2ea"; } +.bi-diagram-2-fill::before { content: "\f2eb"; } +.bi-diagram-2::before { content: "\f2ec"; } +.bi-diagram-3-fill::before { content: "\f2ed"; } +.bi-diagram-3::before { content: "\f2ee"; } +.bi-diamond-fill::before { content: "\f2ef"; } +.bi-diamond-half::before { content: "\f2f0"; } +.bi-diamond::before { content: "\f2f1"; } +.bi-dice-1-fill::before { content: "\f2f2"; } +.bi-dice-1::before { content: "\f2f3"; } +.bi-dice-2-fill::before { content: "\f2f4"; } +.bi-dice-2::before { content: "\f2f5"; } +.bi-dice-3-fill::before { content: "\f2f6"; } +.bi-dice-3::before { content: "\f2f7"; } +.bi-dice-4-fill::before { content: "\f2f8"; } +.bi-dice-4::before { content: "\f2f9"; } +.bi-dice-5-fill::before { content: "\f2fa"; } +.bi-dice-5::before { content: "\f2fb"; } +.bi-dice-6-fill::before { content: "\f2fc"; } +.bi-dice-6::before { content: "\f2fd"; } +.bi-disc-fill::before { content: "\f2fe"; } +.bi-disc::before { content: "\f2ff"; } +.bi-discord::before { content: "\f300"; } +.bi-display-fill::before { content: "\f301"; } +.bi-display::before { content: "\f302"; } +.bi-distribute-horizontal::before { content: "\f303"; } +.bi-distribute-vertical::before { content: "\f304"; } +.bi-door-closed-fill::before { content: "\f305"; } +.bi-door-closed::before { content: "\f306"; } +.bi-door-open-fill::before { content: "\f307"; } +.bi-door-open::before { content: "\f308"; } +.bi-dot::before { content: "\f309"; } +.bi-download::before { content: "\f30a"; } +.bi-droplet-fill::before { content: "\f30b"; } +.bi-droplet-half::before { content: "\f30c"; } +.bi-droplet::before { content: "\f30d"; } +.bi-earbuds::before { content: "\f30e"; } +.bi-easel-fill::before { content: "\f30f"; } +.bi-easel::before { content: "\f310"; } +.bi-egg-fill::before { content: "\f311"; } +.bi-egg-fried::before { content: "\f312"; } +.bi-egg::before { content: "\f313"; } +.bi-eject-fill::before { content: "\f314"; } +.bi-eject::before { content: "\f315"; } +.bi-emoji-angry-fill::before { content: "\f316"; } +.bi-emoji-angry::before { content: "\f317"; } +.bi-emoji-dizzy-fill::before { content: "\f318"; } +.bi-emoji-dizzy::before { content: "\f319"; } +.bi-emoji-expressionless-fill::before { content: "\f31a"; } +.bi-emoji-expressionless::before { content: "\f31b"; } +.bi-emoji-frown-fill::before { content: "\f31c"; } +.bi-emoji-frown::before { content: "\f31d"; } +.bi-emoji-heart-eyes-fill::before { content: "\f31e"; } +.bi-emoji-heart-eyes::before { content: "\f31f"; } +.bi-emoji-laughing-fill::before { content: "\f320"; } +.bi-emoji-laughing::before { content: "\f321"; } +.bi-emoji-neutral-fill::before { content: "\f322"; } +.bi-emoji-neutral::before { content: "\f323"; } +.bi-emoji-smile-fill::before { content: "\f324"; } +.bi-emoji-smile-upside-down-fill::before { content: "\f325"; } +.bi-emoji-smile-upside-down::before { content: "\f326"; } +.bi-emoji-smile::before { content: "\f327"; } +.bi-emoji-sunglasses-fill::before { content: "\f328"; } +.bi-emoji-sunglasses::before { content: "\f329"; } +.bi-emoji-wink-fill::before { content: "\f32a"; } +.bi-emoji-wink::before { content: "\f32b"; } +.bi-envelope-fill::before { content: "\f32c"; } +.bi-envelope-open-fill::before { content: "\f32d"; } +.bi-envelope-open::before { content: "\f32e"; } +.bi-envelope::before { content: "\f32f"; } +.bi-eraser-fill::before { content: "\f330"; } +.bi-eraser::before { content: "\f331"; } +.bi-exclamation-circle-fill::before { content: "\f332"; } +.bi-exclamation-circle::before { content: "\f333"; } +.bi-exclamation-diamond-fill::before { content: "\f334"; } +.bi-exclamation-diamond::before { content: "\f335"; } +.bi-exclamation-octagon-fill::before { content: "\f336"; } +.bi-exclamation-octagon::before { content: "\f337"; } +.bi-exclamation-square-fill::before { content: "\f338"; } +.bi-exclamation-square::before { content: "\f339"; } +.bi-exclamation-triangle-fill::before { content: "\f33a"; } +.bi-exclamation-triangle::before { content: "\f33b"; } +.bi-exclamation::before { content: "\f33c"; } +.bi-exclude::before { content: "\f33d"; } +.bi-eye-fill::before { content: "\f33e"; } +.bi-eye-slash-fill::before { content: "\f33f"; } +.bi-eye-slash::before { content: "\f340"; } +.bi-eye::before { content: "\f341"; } +.bi-eyedropper::before { content: "\f342"; } +.bi-eyeglasses::before { content: "\f343"; } +.bi-facebook::before { content: "\f344"; } +.bi-file-arrow-down-fill::before { content: "\f345"; } +.bi-file-arrow-down::before { content: "\f346"; } +.bi-file-arrow-up-fill::before { content: "\f347"; } +.bi-file-arrow-up::before { content: "\f348"; } +.bi-file-bar-graph-fill::before { content: "\f349"; } +.bi-file-bar-graph::before { content: "\f34a"; } +.bi-file-binary-fill::before { content: "\f34b"; } +.bi-file-binary::before { content: "\f34c"; } +.bi-file-break-fill::before { content: "\f34d"; } +.bi-file-break::before { content: "\f34e"; } +.bi-file-check-fill::before { content: "\f34f"; } +.bi-file-check::before { content: "\f350"; } +.bi-file-code-fill::before { content: "\f351"; } +.bi-file-code::before { content: "\f352"; } +.bi-file-diff-fill::before { content: "\f353"; } +.bi-file-diff::before { content: "\f354"; } +.bi-file-earmark-arrow-down-fill::before { content: "\f355"; } +.bi-file-earmark-arrow-down::before { content: "\f356"; } +.bi-file-earmark-arrow-up-fill::before { content: "\f357"; } +.bi-file-earmark-arrow-up::before { content: "\f358"; } +.bi-file-earmark-bar-graph-fill::before { content: "\f359"; } +.bi-file-earmark-bar-graph::before { content: "\f35a"; } +.bi-file-earmark-binary-fill::before { content: "\f35b"; } +.bi-file-earmark-binary::before { content: "\f35c"; } +.bi-file-earmark-break-fill::before { content: "\f35d"; } +.bi-file-earmark-break::before { content: "\f35e"; } +.bi-file-earmark-check-fill::before { content: "\f35f"; } +.bi-file-earmark-check::before { content: "\f360"; } +.bi-file-earmark-code-fill::before { content: "\f361"; } +.bi-file-earmark-code::before { content: "\f362"; } +.bi-file-earmark-diff-fill::before { content: "\f363"; } +.bi-file-earmark-diff::before { content: "\f364"; } +.bi-file-earmark-easel-fill::before { content: "\f365"; } +.bi-file-earmark-easel::before { content: "\f366"; } +.bi-file-earmark-excel-fill::before { content: "\f367"; } +.bi-file-earmark-excel::before { content: "\f368"; } +.bi-file-earmark-fill::before { content: "\f369"; } +.bi-file-earmark-font-fill::before { content: "\f36a"; } +.bi-file-earmark-font::before { content: "\f36b"; } +.bi-file-earmark-image-fill::before { content: "\f36c"; } +.bi-file-earmark-image::before { content: "\f36d"; } +.bi-file-earmark-lock-fill::before { content: "\f36e"; } +.bi-file-earmark-lock::before { content: "\f36f"; } +.bi-file-earmark-lock2-fill::before { content: "\f370"; } +.bi-file-earmark-lock2::before { content: "\f371"; } +.bi-file-earmark-medical-fill::before { content: "\f372"; } +.bi-file-earmark-medical::before { content: "\f373"; } +.bi-file-earmark-minus-fill::before { content: "\f374"; } +.bi-file-earmark-minus::before { content: "\f375"; } +.bi-file-earmark-music-fill::before { content: "\f376"; } +.bi-file-earmark-music::before { content: "\f377"; } +.bi-file-earmark-person-fill::before { content: "\f378"; } +.bi-file-earmark-person::before { content: "\f379"; } +.bi-file-earmark-play-fill::before { content: "\f37a"; } +.bi-file-earmark-play::before { content: "\f37b"; } +.bi-file-earmark-plus-fill::before { content: "\f37c"; } +.bi-file-earmark-plus::before { content: "\f37d"; } +.bi-file-earmark-post-fill::before { content: "\f37e"; } +.bi-file-earmark-post::before { content: "\f37f"; } +.bi-file-earmark-ppt-fill::before { content: "\f380"; } +.bi-file-earmark-ppt::before { content: "\f381"; } +.bi-file-earmark-richtext-fill::before { content: "\f382"; } +.bi-file-earmark-richtext::before { content: "\f383"; } +.bi-file-earmark-ruled-fill::before { content: "\f384"; } +.bi-file-earmark-ruled::before { content: "\f385"; } +.bi-file-earmark-slides-fill::before { content: "\f386"; } +.bi-file-earmark-slides::before { content: "\f387"; } +.bi-file-earmark-spreadsheet-fill::before { content: "\f388"; } +.bi-file-earmark-spreadsheet::before { content: "\f389"; } +.bi-file-earmark-text-fill::before { content: "\f38a"; } +.bi-file-earmark-text::before { content: "\f38b"; } +.bi-file-earmark-word-fill::before { content: "\f38c"; } +.bi-file-earmark-word::before { content: "\f38d"; } +.bi-file-earmark-x-fill::before { content: "\f38e"; } +.bi-file-earmark-x::before { content: "\f38f"; } +.bi-file-earmark-zip-fill::before { content: "\f390"; } +.bi-file-earmark-zip::before { content: "\f391"; } +.bi-file-earmark::before { content: "\f392"; } +.bi-file-easel-fill::before { content: "\f393"; } +.bi-file-easel::before { content: "\f394"; } +.bi-file-excel-fill::before { content: "\f395"; } +.bi-file-excel::before { content: "\f396"; } +.bi-file-fill::before { content: "\f397"; } +.bi-file-font-fill::before { content: "\f398"; } +.bi-file-font::before { content: "\f399"; } +.bi-file-image-fill::before { content: "\f39a"; } +.bi-file-image::before { content: "\f39b"; } +.bi-file-lock-fill::before { content: "\f39c"; } +.bi-file-lock::before { content: "\f39d"; } +.bi-file-lock2-fill::before { content: "\f39e"; } +.bi-file-lock2::before { content: "\f39f"; } +.bi-file-medical-fill::before { content: "\f3a0"; } +.bi-file-medical::before { content: "\f3a1"; } +.bi-file-minus-fill::before { content: "\f3a2"; } +.bi-file-minus::before { content: "\f3a3"; } +.bi-file-music-fill::before { content: "\f3a4"; } +.bi-file-music::before { content: "\f3a5"; } +.bi-file-person-fill::before { content: "\f3a6"; } +.bi-file-person::before { content: "\f3a7"; } +.bi-file-play-fill::before { content: "\f3a8"; } +.bi-file-play::before { content: "\f3a9"; } +.bi-file-plus-fill::before { content: "\f3aa"; } +.bi-file-plus::before { content: "\f3ab"; } +.bi-file-post-fill::before { content: "\f3ac"; } +.bi-file-post::before { content: "\f3ad"; } +.bi-file-ppt-fill::before { content: "\f3ae"; } +.bi-file-ppt::before { content: "\f3af"; } +.bi-file-richtext-fill::before { content: "\f3b0"; } +.bi-file-richtext::before { content: "\f3b1"; } +.bi-file-ruled-fill::before { content: "\f3b2"; } +.bi-file-ruled::before { content: "\f3b3"; } +.bi-file-slides-fill::before { content: "\f3b4"; } +.bi-file-slides::before { content: "\f3b5"; } +.bi-file-spreadsheet-fill::before { content: "\f3b6"; } +.bi-file-spreadsheet::before { content: "\f3b7"; } +.bi-file-text-fill::before { content: "\f3b8"; } +.bi-file-text::before { content: "\f3b9"; } +.bi-file-word-fill::before { content: "\f3ba"; } +.bi-file-word::before { content: "\f3bb"; } +.bi-file-x-fill::before { content: "\f3bc"; } +.bi-file-x::before { content: "\f3bd"; } +.bi-file-zip-fill::before { content: "\f3be"; } +.bi-file-zip::before { content: "\f3bf"; } +.bi-file::before { content: "\f3c0"; } +.bi-files-alt::before { content: "\f3c1"; } +.bi-files::before { content: "\f3c2"; } +.bi-film::before { content: "\f3c3"; } +.bi-filter-circle-fill::before { content: "\f3c4"; } +.bi-filter-circle::before { content: "\f3c5"; } +.bi-filter-left::before { content: "\f3c6"; } +.bi-filter-right::before { content: "\f3c7"; } +.bi-filter-square-fill::before { content: "\f3c8"; } +.bi-filter-square::before { content: "\f3c9"; } +.bi-filter::before { content: "\f3ca"; } +.bi-flag-fill::before { content: "\f3cb"; } +.bi-flag::before { content: "\f3cc"; } +.bi-flower1::before { content: "\f3cd"; } +.bi-flower2::before { content: "\f3ce"; } +.bi-flower3::before { content: "\f3cf"; } +.bi-folder-check::before { content: "\f3d0"; } +.bi-folder-fill::before { content: "\f3d1"; } +.bi-folder-minus::before { content: "\f3d2"; } +.bi-folder-plus::before { content: "\f3d3"; } +.bi-folder-symlink-fill::before { content: "\f3d4"; } +.bi-folder-symlink::before { content: "\f3d5"; } +.bi-folder-x::before { content: "\f3d6"; } +.bi-folder::before { content: "\f3d7"; } +.bi-folder2-open::before { content: "\f3d8"; } +.bi-folder2::before { content: "\f3d9"; } +.bi-fonts::before { content: "\f3da"; } +.bi-forward-fill::before { content: "\f3db"; } +.bi-forward::before { content: "\f3dc"; } +.bi-front::before { content: "\f3dd"; } +.bi-fullscreen-exit::before { content: "\f3de"; } +.bi-fullscreen::before { content: "\f3df"; } +.bi-funnel-fill::before { content: "\f3e0"; } +.bi-funnel::before { content: "\f3e1"; } +.bi-gear-fill::before { content: "\f3e2"; } +.bi-gear-wide-connected::before { content: "\f3e3"; } +.bi-gear-wide::before { content: "\f3e4"; } +.bi-gear::before { content: "\f3e5"; } +.bi-gem::before { content: "\f3e6"; } +.bi-geo-alt-fill::before { content: "\f3e7"; } +.bi-geo-alt::before { content: "\f3e8"; } +.bi-geo-fill::before { content: "\f3e9"; } +.bi-geo::before { content: "\f3ea"; } +.bi-gift-fill::before { content: "\f3eb"; } +.bi-gift::before { content: "\f3ec"; } +.bi-github::before { content: "\f3ed"; } +.bi-globe::before { content: "\f3ee"; } +.bi-globe2::before { content: "\f3ef"; } +.bi-google::before { content: "\f3f0"; } +.bi-graph-down::before { content: "\f3f1"; } +.bi-graph-up::before { content: "\f3f2"; } +.bi-grid-1x2-fill::before { content: "\f3f3"; } +.bi-grid-1x2::before { content: "\f3f4"; } +.bi-grid-3x2-gap-fill::before { content: "\f3f5"; } +.bi-grid-3x2-gap::before { content: "\f3f6"; } +.bi-grid-3x2::before { content: "\f3f7"; } +.bi-grid-3x3-gap-fill::before { content: "\f3f8"; } +.bi-grid-3x3-gap::before { content: "\f3f9"; } +.bi-grid-3x3::before { content: "\f3fa"; } +.bi-grid-fill::before { content: "\f3fb"; } +.bi-grid::before { content: "\f3fc"; } +.bi-grip-horizontal::before { content: "\f3fd"; } +.bi-grip-vertical::before { content: "\f3fe"; } +.bi-hammer::before { content: "\f3ff"; } +.bi-hand-index-fill::before { content: "\f400"; } +.bi-hand-index-thumb-fill::before { content: "\f401"; } +.bi-hand-index-thumb::before { content: "\f402"; } +.bi-hand-index::before { content: "\f403"; } +.bi-hand-thumbs-down-fill::before { content: "\f404"; } +.bi-hand-thumbs-down::before { content: "\f405"; } +.bi-hand-thumbs-up-fill::before { content: "\f406"; } +.bi-hand-thumbs-up::before { content: "\f407"; } +.bi-handbag-fill::before { content: "\f408"; } +.bi-handbag::before { content: "\f409"; } +.bi-hash::before { content: "\f40a"; } +.bi-hdd-fill::before { content: "\f40b"; } +.bi-hdd-network-fill::before { content: "\f40c"; } +.bi-hdd-network::before { content: "\f40d"; } +.bi-hdd-rack-fill::before { content: "\f40e"; } +.bi-hdd-rack::before { content: "\f40f"; } +.bi-hdd-stack-fill::before { content: "\f410"; } +.bi-hdd-stack::before { content: "\f411"; } +.bi-hdd::before { content: "\f412"; } +.bi-headphones::before { content: "\f413"; } +.bi-headset::before { content: "\f414"; } +.bi-heart-fill::before { content: "\f415"; } +.bi-heart-half::before { content: "\f416"; } +.bi-heart::before { content: "\f417"; } +.bi-heptagon-fill::before { content: "\f418"; } +.bi-heptagon-half::before { content: "\f419"; } +.bi-heptagon::before { content: "\f41a"; } +.bi-hexagon-fill::before { content: "\f41b"; } +.bi-hexagon-half::before { content: "\f41c"; } +.bi-hexagon::before { content: "\f41d"; } +.bi-hourglass-bottom::before { content: "\f41e"; } +.bi-hourglass-split::before { content: "\f41f"; } +.bi-hourglass-top::before { content: "\f420"; } +.bi-hourglass::before { content: "\f421"; } +.bi-house-door-fill::before { content: "\f422"; } +.bi-house-door::before { content: "\f423"; } +.bi-house-fill::before { content: "\f424"; } +.bi-house::before { content: "\f425"; } +.bi-hr::before { content: "\f426"; } +.bi-hurricane::before { content: "\f427"; } +.bi-image-alt::before { content: "\f428"; } +.bi-image-fill::before { content: "\f429"; } +.bi-image::before { content: "\f42a"; } +.bi-images::before { content: "\f42b"; } +.bi-inbox-fill::before { content: "\f42c"; } +.bi-inbox::before { content: "\f42d"; } +.bi-inboxes-fill::before { content: "\f42e"; } +.bi-inboxes::before { content: "\f42f"; } +.bi-info-circle-fill::before { content: "\f430"; } +.bi-info-circle::before { content: "\f431"; } +.bi-info-square-fill::before { content: "\f432"; } +.bi-info-square::before { content: "\f433"; } +.bi-info::before { content: "\f434"; } +.bi-input-cursor-text::before { content: "\f435"; } +.bi-input-cursor::before { content: "\f436"; } +.bi-instagram::before { content: "\f437"; } +.bi-intersect::before { content: "\f438"; } +.bi-journal-album::before { content: "\f439"; } +.bi-journal-arrow-down::before { content: "\f43a"; } +.bi-journal-arrow-up::before { content: "\f43b"; } +.bi-journal-bookmark-fill::before { content: "\f43c"; } +.bi-journal-bookmark::before { content: "\f43d"; } +.bi-journal-check::before { content: "\f43e"; } +.bi-journal-code::before { content: "\f43f"; } +.bi-journal-medical::before { content: "\f440"; } +.bi-journal-minus::before { content: "\f441"; } +.bi-journal-plus::before { content: "\f442"; } +.bi-journal-richtext::before { content: "\f443"; } +.bi-journal-text::before { content: "\f444"; } +.bi-journal-x::before { content: "\f445"; } +.bi-journal::before { content: "\f446"; } +.bi-journals::before { content: "\f447"; } +.bi-joystick::before { content: "\f448"; } +.bi-justify-left::before { content: "\f449"; } +.bi-justify-right::before { content: "\f44a"; } +.bi-justify::before { content: "\f44b"; } +.bi-kanban-fill::before { content: "\f44c"; } +.bi-kanban::before { content: "\f44d"; } +.bi-key-fill::before { content: "\f44e"; } +.bi-key::before { content: "\f44f"; } +.bi-keyboard-fill::before { content: "\f450"; } +.bi-keyboard::before { content: "\f451"; } +.bi-ladder::before { content: "\f452"; } +.bi-lamp-fill::before { content: "\f453"; } +.bi-lamp::before { content: "\f454"; } +.bi-laptop-fill::before { content: "\f455"; } +.bi-laptop::before { content: "\f456"; } +.bi-layer-backward::before { content: "\f457"; } +.bi-layer-forward::before { content: "\f458"; } +.bi-layers-fill::before { content: "\f459"; } +.bi-layers-half::before { content: "\f45a"; } +.bi-layers::before { content: "\f45b"; } +.bi-layout-sidebar-inset-reverse::before { content: "\f45c"; } +.bi-layout-sidebar-inset::before { content: "\f45d"; } +.bi-layout-sidebar-reverse::before { content: "\f45e"; } +.bi-layout-sidebar::before { content: "\f45f"; } +.bi-layout-split::before { content: "\f460"; } +.bi-layout-text-sidebar-reverse::before { content: "\f461"; } +.bi-layout-text-sidebar::before { content: "\f462"; } +.bi-layout-text-window-reverse::before { content: "\f463"; } +.bi-layout-text-window::before { content: "\f464"; } +.bi-layout-three-columns::before { content: "\f465"; } +.bi-layout-wtf::before { content: "\f466"; } +.bi-life-preserver::before { content: "\f467"; } +.bi-lightbulb-fill::before { content: "\f468"; } +.bi-lightbulb-off-fill::before { content: "\f469"; } +.bi-lightbulb-off::before { content: "\f46a"; } +.bi-lightbulb::before { content: "\f46b"; } +.bi-lightning-charge-fill::before { content: "\f46c"; } +.bi-lightning-charge::before { content: "\f46d"; } +.bi-lightning-fill::before { content: "\f46e"; } +.bi-lightning::before { content: "\f46f"; } +.bi-link-45deg::before { content: "\f470"; } +.bi-link::before { content: "\f471"; } +.bi-linkedin::before { content: "\f472"; } +.bi-list-check::before { content: "\f473"; } +.bi-list-nested::before { content: "\f474"; } +.bi-list-ol::before { content: "\f475"; } +.bi-list-stars::before { content: "\f476"; } +.bi-list-task::before { content: "\f477"; } +.bi-list-ul::before { content: "\f478"; } +.bi-list::before { content: "\f479"; } +.bi-lock-fill::before { content: "\f47a"; } +.bi-lock::before { content: "\f47b"; } +.bi-mailbox::before { content: "\f47c"; } +.bi-mailbox2::before { content: "\f47d"; } +.bi-map-fill::before { content: "\f47e"; } +.bi-map::before { content: "\f47f"; } +.bi-markdown-fill::before { content: "\f480"; } +.bi-markdown::before { content: "\f481"; } +.bi-mask::before { content: "\f482"; } +.bi-megaphone-fill::before { content: "\f483"; } +.bi-megaphone::before { content: "\f484"; } +.bi-menu-app-fill::before { content: "\f485"; } +.bi-menu-app::before { content: "\f486"; } +.bi-menu-button-fill::before { content: "\f487"; } +.bi-menu-button-wide-fill::before { content: "\f488"; } +.bi-menu-button-wide::before { content: "\f489"; } +.bi-menu-button::before { content: "\f48a"; } +.bi-menu-down::before { content: "\f48b"; } +.bi-menu-up::before { content: "\f48c"; } +.bi-mic-fill::before { content: "\f48d"; } +.bi-mic-mute-fill::before { content: "\f48e"; } +.bi-mic-mute::before { content: "\f48f"; } +.bi-mic::before { content: "\f490"; } +.bi-minecart-loaded::before { content: "\f491"; } +.bi-minecart::before { content: "\f492"; } +.bi-moisture::before { content: "\f493"; } +.bi-moon-fill::before { content: "\f494"; } +.bi-moon-stars-fill::before { content: "\f495"; } +.bi-moon-stars::before { content: "\f496"; } +.bi-moon::before { content: "\f497"; } +.bi-mouse-fill::before { content: "\f498"; } +.bi-mouse::before { content: "\f499"; } +.bi-mouse2-fill::before { content: "\f49a"; } +.bi-mouse2::before { content: "\f49b"; } +.bi-mouse3-fill::before { content: "\f49c"; } +.bi-mouse3::before { content: "\f49d"; } +.bi-music-note-beamed::before { content: "\f49e"; } +.bi-music-note-list::before { content: "\f49f"; } +.bi-music-note::before { content: "\f4a0"; } +.bi-music-player-fill::before { content: "\f4a1"; } +.bi-music-player::before { content: "\f4a2"; } +.bi-newspaper::before { content: "\f4a3"; } +.bi-node-minus-fill::before { content: "\f4a4"; } +.bi-node-minus::before { content: "\f4a5"; } +.bi-node-plus-fill::before { content: "\f4a6"; } +.bi-node-plus::before { content: "\f4a7"; } +.bi-nut-fill::before { content: "\f4a8"; } +.bi-nut::before { content: "\f4a9"; } +.bi-octagon-fill::before { content: "\f4aa"; } +.bi-octagon-half::before { content: "\f4ab"; } +.bi-octagon::before { content: "\f4ac"; } +.bi-option::before { content: "\f4ad"; } +.bi-outlet::before { content: "\f4ae"; } +.bi-paint-bucket::before { content: "\f4af"; } +.bi-palette-fill::before { content: "\f4b0"; } +.bi-palette::before { content: "\f4b1"; } +.bi-palette2::before { content: "\f4b2"; } +.bi-paperclip::before { content: "\f4b3"; } +.bi-paragraph::before { content: "\f4b4"; } +.bi-patch-check-fill::before { content: "\f4b5"; } +.bi-patch-check::before { content: "\f4b6"; } +.bi-patch-exclamation-fill::before { content: "\f4b7"; } +.bi-patch-exclamation::before { content: "\f4b8"; } +.bi-patch-minus-fill::before { content: "\f4b9"; } +.bi-patch-minus::before { content: "\f4ba"; } +.bi-patch-plus-fill::before { content: "\f4bb"; } +.bi-patch-plus::before { content: "\f4bc"; } +.bi-patch-question-fill::before { content: "\f4bd"; } +.bi-patch-question::before { content: "\f4be"; } +.bi-pause-btn-fill::before { content: "\f4bf"; } +.bi-pause-btn::before { content: "\f4c0"; } +.bi-pause-circle-fill::before { content: "\f4c1"; } +.bi-pause-circle::before { content: "\f4c2"; } +.bi-pause-fill::before { content: "\f4c3"; } +.bi-pause::before { content: "\f4c4"; } +.bi-peace-fill::before { content: "\f4c5"; } +.bi-peace::before { content: "\f4c6"; } +.bi-pen-fill::before { content: "\f4c7"; } +.bi-pen::before { content: "\f4c8"; } +.bi-pencil-fill::before { content: "\f4c9"; } +.bi-pencil-square::before { content: "\f4ca"; } +.bi-pencil::before { content: "\f4cb"; } +.bi-pentagon-fill::before { content: "\f4cc"; } +.bi-pentagon-half::before { content: "\f4cd"; } +.bi-pentagon::before { content: "\f4ce"; } +.bi-people-fill::before { content: "\f4cf"; } +.bi-people::before { content: "\f4d0"; } +.bi-percent::before { content: "\f4d1"; } +.bi-person-badge-fill::before { content: "\f4d2"; } +.bi-person-badge::before { content: "\f4d3"; } +.bi-person-bounding-box::before { content: "\f4d4"; } +.bi-person-check-fill::before { content: "\f4d5"; } +.bi-person-check::before { content: "\f4d6"; } +.bi-person-circle::before { content: "\f4d7"; } +.bi-person-dash-fill::before { content: "\f4d8"; } +.bi-person-dash::before { content: "\f4d9"; } +.bi-person-fill::before { content: "\f4da"; } +.bi-person-lines-fill::before { content: "\f4db"; } +.bi-person-plus-fill::before { content: "\f4dc"; } +.bi-person-plus::before { content: "\f4dd"; } +.bi-person-square::before { content: "\f4de"; } +.bi-person-x-fill::before { content: "\f4df"; } +.bi-person-x::before { content: "\f4e0"; } +.bi-person::before { content: "\f4e1"; } +.bi-phone-fill::before { content: "\f4e2"; } +.bi-phone-landscape-fill::before { content: "\f4e3"; } +.bi-phone-landscape::before { content: "\f4e4"; } +.bi-phone-vibrate-fill::before { content: "\f4e5"; } +.bi-phone-vibrate::before { content: "\f4e6"; } +.bi-phone::before { content: "\f4e7"; } +.bi-pie-chart-fill::before { content: "\f4e8"; } +.bi-pie-chart::before { content: "\f4e9"; } +.bi-pin-angle-fill::before { content: "\f4ea"; } +.bi-pin-angle::before { content: "\f4eb"; } +.bi-pin-fill::before { content: "\f4ec"; } +.bi-pin::before { content: "\f4ed"; } +.bi-pip-fill::before { content: "\f4ee"; } +.bi-pip::before { content: "\f4ef"; } +.bi-play-btn-fill::before { content: "\f4f0"; } +.bi-play-btn::before { content: "\f4f1"; } +.bi-play-circle-fill::before { content: "\f4f2"; } +.bi-play-circle::before { content: "\f4f3"; } +.bi-play-fill::before { content: "\f4f4"; } +.bi-play::before { content: "\f4f5"; } +.bi-plug-fill::before { content: "\f4f6"; } +.bi-plug::before { content: "\f4f7"; } +.bi-plus-circle-dotted::before { content: "\f4f8"; } +.bi-plus-circle-fill::before { content: "\f4f9"; } +.bi-plus-circle::before { content: "\f4fa"; } +.bi-plus-square-dotted::before { content: "\f4fb"; } +.bi-plus-square-fill::before { content: "\f4fc"; } +.bi-plus-square::before { content: "\f4fd"; } +.bi-plus::before { content: "\f4fe"; } +.bi-power::before { content: "\f4ff"; } +.bi-printer-fill::before { content: "\f500"; } +.bi-printer::before { content: "\f501"; } +.bi-puzzle-fill::before { content: "\f502"; } +.bi-puzzle::before { content: "\f503"; } +.bi-question-circle-fill::before { content: "\f504"; } +.bi-question-circle::before { content: "\f505"; } +.bi-question-diamond-fill::before { content: "\f506"; } +.bi-question-diamond::before { content: "\f507"; } +.bi-question-octagon-fill::before { content: "\f508"; } +.bi-question-octagon::before { content: "\f509"; } +.bi-question-square-fill::before { content: "\f50a"; } +.bi-question-square::before { content: "\f50b"; } +.bi-question::before { content: "\f50c"; } +.bi-rainbow::before { content: "\f50d"; } +.bi-receipt-cutoff::before { content: "\f50e"; } +.bi-receipt::before { content: "\f50f"; } +.bi-reception-0::before { content: "\f510"; } +.bi-reception-1::before { content: "\f511"; } +.bi-reception-2::before { content: "\f512"; } +.bi-reception-3::before { content: "\f513"; } +.bi-reception-4::before { content: "\f514"; } +.bi-record-btn-fill::before { content: "\f515"; } +.bi-record-btn::before { content: "\f516"; } +.bi-record-circle-fill::before { content: "\f517"; } +.bi-record-circle::before { content: "\f518"; } +.bi-record-fill::before { content: "\f519"; } +.bi-record::before { content: "\f51a"; } +.bi-record2-fill::before { content: "\f51b"; } +.bi-record2::before { content: "\f51c"; } +.bi-reply-all-fill::before { content: "\f51d"; } +.bi-reply-all::before { content: "\f51e"; } +.bi-reply-fill::before { content: "\f51f"; } +.bi-reply::before { content: "\f520"; } +.bi-rss-fill::before { content: "\f521"; } +.bi-rss::before { content: "\f522"; } +.bi-rulers::before { content: "\f523"; } +.bi-save-fill::before { content: "\f524"; } +.bi-save::before { content: "\f525"; } +.bi-save2-fill::before { content: "\f526"; } +.bi-save2::before { content: "\f527"; } +.bi-scissors::before { content: "\f528"; } +.bi-screwdriver::before { content: "\f529"; } +.bi-search::before { content: "\f52a"; } +.bi-segmented-nav::before { content: "\f52b"; } +.bi-server::before { content: "\f52c"; } +.bi-share-fill::before { content: "\f52d"; } +.bi-share::before { content: "\f52e"; } +.bi-shield-check::before { content: "\f52f"; } +.bi-shield-exclamation::before { content: "\f530"; } +.bi-shield-fill-check::before { content: "\f531"; } +.bi-shield-fill-exclamation::before { content: "\f532"; } +.bi-shield-fill-minus::before { content: "\f533"; } +.bi-shield-fill-plus::before { content: "\f534"; } +.bi-shield-fill-x::before { content: "\f535"; } +.bi-shield-fill::before { content: "\f536"; } +.bi-shield-lock-fill::before { content: "\f537"; } +.bi-shield-lock::before { content: "\f538"; } +.bi-shield-minus::before { content: "\f539"; } +.bi-shield-plus::before { content: "\f53a"; } +.bi-shield-shaded::before { content: "\f53b"; } +.bi-shield-slash-fill::before { content: "\f53c"; } +.bi-shield-slash::before { content: "\f53d"; } +.bi-shield-x::before { content: "\f53e"; } +.bi-shield::before { content: "\f53f"; } +.bi-shift-fill::before { content: "\f540"; } +.bi-shift::before { content: "\f541"; } +.bi-shop-window::before { content: "\f542"; } +.bi-shop::before { content: "\f543"; } +.bi-shuffle::before { content: "\f544"; } +.bi-signpost-2-fill::before { content: "\f545"; } +.bi-signpost-2::before { content: "\f546"; } +.bi-signpost-fill::before { content: "\f547"; } +.bi-signpost-split-fill::before { content: "\f548"; } +.bi-signpost-split::before { content: "\f549"; } +.bi-signpost::before { content: "\f54a"; } +.bi-sim-fill::before { content: "\f54b"; } +.bi-sim::before { content: "\f54c"; } +.bi-skip-backward-btn-fill::before { content: "\f54d"; } +.bi-skip-backward-btn::before { content: "\f54e"; } +.bi-skip-backward-circle-fill::before { content: "\f54f"; } +.bi-skip-backward-circle::before { content: "\f550"; } +.bi-skip-backward-fill::before { content: "\f551"; } +.bi-skip-backward::before { content: "\f552"; } +.bi-skip-end-btn-fill::before { content: "\f553"; } +.bi-skip-end-btn::before { content: "\f554"; } +.bi-skip-end-circle-fill::before { content: "\f555"; } +.bi-skip-end-circle::before { content: "\f556"; } +.bi-skip-end-fill::before { content: "\f557"; } +.bi-skip-end::before { content: "\f558"; } +.bi-skip-forward-btn-fill::before { content: "\f559"; } +.bi-skip-forward-btn::before { content: "\f55a"; } +.bi-skip-forward-circle-fill::before { content: "\f55b"; } +.bi-skip-forward-circle::before { content: "\f55c"; } +.bi-skip-forward-fill::before { content: "\f55d"; } +.bi-skip-forward::before { content: "\f55e"; } +.bi-skip-start-btn-fill::before { content: "\f55f"; } +.bi-skip-start-btn::before { content: "\f560"; } +.bi-skip-start-circle-fill::before { content: "\f561"; } +.bi-skip-start-circle::before { content: "\f562"; } +.bi-skip-start-fill::before { content: "\f563"; } +.bi-skip-start::before { content: "\f564"; } +.bi-slack::before { content: "\f565"; } +.bi-slash-circle-fill::before { content: "\f566"; } +.bi-slash-circle::before { content: "\f567"; } +.bi-slash-square-fill::before { content: "\f568"; } +.bi-slash-square::before { content: "\f569"; } +.bi-slash::before { content: "\f56a"; } +.bi-sliders::before { content: "\f56b"; } +.bi-smartwatch::before { content: "\f56c"; } +.bi-snow::before { content: "\f56d"; } +.bi-snow2::before { content: "\f56e"; } +.bi-snow3::before { content: "\f56f"; } +.bi-sort-alpha-down-alt::before { content: "\f570"; } +.bi-sort-alpha-down::before { content: "\f571"; } +.bi-sort-alpha-up-alt::before { content: "\f572"; } +.bi-sort-alpha-up::before { content: "\f573"; } +.bi-sort-down-alt::before { content: "\f574"; } +.bi-sort-down::before { content: "\f575"; } +.bi-sort-numeric-down-alt::before { content: "\f576"; } +.bi-sort-numeric-down::before { content: "\f577"; } +.bi-sort-numeric-up-alt::before { content: "\f578"; } +.bi-sort-numeric-up::before { content: "\f579"; } +.bi-sort-up-alt::before { content: "\f57a"; } +.bi-sort-up::before { content: "\f57b"; } +.bi-soundwave::before { content: "\f57c"; } +.bi-speaker-fill::before { content: "\f57d"; } +.bi-speaker::before { content: "\f57e"; } +.bi-speedometer::before { content: "\f57f"; } +.bi-speedometer2::before { content: "\f580"; } +.bi-spellcheck::before { content: "\f581"; } +.bi-square-fill::before { content: "\f582"; } +.bi-square-half::before { content: "\f583"; } +.bi-square::before { content: "\f584"; } +.bi-stack::before { content: "\f585"; } +.bi-star-fill::before { content: "\f586"; } +.bi-star-half::before { content: "\f587"; } +.bi-star::before { content: "\f588"; } +.bi-stars::before { content: "\f589"; } +.bi-stickies-fill::before { content: "\f58a"; } +.bi-stickies::before { content: "\f58b"; } +.bi-sticky-fill::before { content: "\f58c"; } +.bi-sticky::before { content: "\f58d"; } +.bi-stop-btn-fill::before { content: "\f58e"; } +.bi-stop-btn::before { content: "\f58f"; } +.bi-stop-circle-fill::before { content: "\f590"; } +.bi-stop-circle::before { content: "\f591"; } +.bi-stop-fill::before { content: "\f592"; } +.bi-stop::before { content: "\f593"; } +.bi-stoplights-fill::before { content: "\f594"; } +.bi-stoplights::before { content: "\f595"; } +.bi-stopwatch-fill::before { content: "\f596"; } +.bi-stopwatch::before { content: "\f597"; } +.bi-subtract::before { content: "\f598"; } +.bi-suit-club-fill::before { content: "\f599"; } +.bi-suit-club::before { content: "\f59a"; } +.bi-suit-diamond-fill::before { content: "\f59b"; } +.bi-suit-diamond::before { content: "\f59c"; } +.bi-suit-heart-fill::before { content: "\f59d"; } +.bi-suit-heart::before { content: "\f59e"; } +.bi-suit-spade-fill::before { content: "\f59f"; } +.bi-suit-spade::before { content: "\f5a0"; } +.bi-sun-fill::before { content: "\f5a1"; } +.bi-sun::before { content: "\f5a2"; } +.bi-sunglasses::before { content: "\f5a3"; } +.bi-sunrise-fill::before { content: "\f5a4"; } +.bi-sunrise::before { content: "\f5a5"; } +.bi-sunset-fill::before { content: "\f5a6"; } +.bi-sunset::before { content: "\f5a7"; } +.bi-symmetry-horizontal::before { content: "\f5a8"; } +.bi-symmetry-vertical::before { content: "\f5a9"; } +.bi-table::before { content: "\f5aa"; } +.bi-tablet-fill::before { content: "\f5ab"; } +.bi-tablet-landscape-fill::before { content: "\f5ac"; } +.bi-tablet-landscape::before { content: "\f5ad"; } +.bi-tablet::before { content: "\f5ae"; } +.bi-tag-fill::before { content: "\f5af"; } +.bi-tag::before { content: "\f5b0"; } +.bi-tags-fill::before { content: "\f5b1"; } +.bi-tags::before { content: "\f5b2"; } +.bi-telegram::before { content: "\f5b3"; } +.bi-telephone-fill::before { content: "\f5b4"; } +.bi-telephone-forward-fill::before { content: "\f5b5"; } +.bi-telephone-forward::before { content: "\f5b6"; } +.bi-telephone-inbound-fill::before { content: "\f5b7"; } +.bi-telephone-inbound::before { content: "\f5b8"; } +.bi-telephone-minus-fill::before { content: "\f5b9"; } +.bi-telephone-minus::before { content: "\f5ba"; } +.bi-telephone-outbound-fill::before { content: "\f5bb"; } +.bi-telephone-outbound::before { content: "\f5bc"; } +.bi-telephone-plus-fill::before { content: "\f5bd"; } +.bi-telephone-plus::before { content: "\f5be"; } +.bi-telephone-x-fill::before { content: "\f5bf"; } +.bi-telephone-x::before { content: "\f5c0"; } +.bi-telephone::before { content: "\f5c1"; } +.bi-terminal-fill::before { content: "\f5c2"; } +.bi-terminal::before { content: "\f5c3"; } +.bi-text-center::before { content: "\f5c4"; } +.bi-text-indent-left::before { content: "\f5c5"; } +.bi-text-indent-right::before { content: "\f5c6"; } +.bi-text-left::before { content: "\f5c7"; } +.bi-text-paragraph::before { content: "\f5c8"; } +.bi-text-right::before { content: "\f5c9"; } +.bi-textarea-resize::before { content: "\f5ca"; } +.bi-textarea-t::before { content: "\f5cb"; } +.bi-textarea::before { content: "\f5cc"; } +.bi-thermometer-half::before { content: "\f5cd"; } +.bi-thermometer-high::before { content: "\f5ce"; } +.bi-thermometer-low::before { content: "\f5cf"; } +.bi-thermometer-snow::before { content: "\f5d0"; } +.bi-thermometer-sun::before { content: "\f5d1"; } +.bi-thermometer::before { content: "\f5d2"; } +.bi-three-dots-vertical::before { content: "\f5d3"; } +.bi-three-dots::before { content: "\f5d4"; } +.bi-toggle-off::before { content: "\f5d5"; } +.bi-toggle-on::before { content: "\f5d6"; } +.bi-toggle2-off::before { content: "\f5d7"; } +.bi-toggle2-on::before { content: "\f5d8"; } +.bi-toggles::before { content: "\f5d9"; } +.bi-toggles2::before { content: "\f5da"; } +.bi-tools::before { content: "\f5db"; } +.bi-tornado::before { content: "\f5dc"; } +.bi-trash-fill::before { content: "\f5dd"; } +.bi-trash::before { content: "\f5de"; } +.bi-trash2-fill::before { content: "\f5df"; } +.bi-trash2::before { content: "\f5e0"; } +.bi-tree-fill::before { content: "\f5e1"; } +.bi-tree::before { content: "\f5e2"; } +.bi-triangle-fill::before { content: "\f5e3"; } +.bi-triangle-half::before { content: "\f5e4"; } +.bi-triangle::before { content: "\f5e5"; } +.bi-trophy-fill::before { content: "\f5e6"; } +.bi-trophy::before { content: "\f5e7"; } +.bi-tropical-storm::before { content: "\f5e8"; } +.bi-truck-flatbed::before { content: "\f5e9"; } +.bi-truck::before { content: "\f5ea"; } +.bi-tsunami::before { content: "\f5eb"; } +.bi-tv-fill::before { content: "\f5ec"; } +.bi-tv::before { content: "\f5ed"; } +.bi-twitch::before { content: "\f5ee"; } +.bi-twitter::before { content: "\f5ef"; } +.bi-type-bold::before { content: "\f5f0"; } +.bi-type-h1::before { content: "\f5f1"; } +.bi-type-h2::before { content: "\f5f2"; } +.bi-type-h3::before { content: "\f5f3"; } +.bi-type-italic::before { content: "\f5f4"; } +.bi-type-strikethrough::before { content: "\f5f5"; } +.bi-type-underline::before { content: "\f5f6"; } +.bi-type::before { content: "\f5f7"; } +.bi-ui-checks-grid::before { content: "\f5f8"; } +.bi-ui-checks::before { content: "\f5f9"; } +.bi-ui-radios-grid::before { content: "\f5fa"; } +.bi-ui-radios::before { content: "\f5fb"; } +.bi-umbrella-fill::before { content: "\f5fc"; } +.bi-umbrella::before { content: "\f5fd"; } +.bi-union::before { content: "\f5fe"; } +.bi-unlock-fill::before { content: "\f5ff"; } +.bi-unlock::before { content: "\f600"; } +.bi-upc-scan::before { content: "\f601"; } +.bi-upc::before { content: "\f602"; } +.bi-upload::before { content: "\f603"; } +.bi-vector-pen::before { content: "\f604"; } +.bi-view-list::before { content: "\f605"; } +.bi-view-stacked::before { content: "\f606"; } +.bi-vinyl-fill::before { content: "\f607"; } +.bi-vinyl::before { content: "\f608"; } +.bi-voicemail::before { content: "\f609"; } +.bi-volume-down-fill::before { content: "\f60a"; } +.bi-volume-down::before { content: "\f60b"; } +.bi-volume-mute-fill::before { content: "\f60c"; } +.bi-volume-mute::before { content: "\f60d"; } +.bi-volume-off-fill::before { content: "\f60e"; } +.bi-volume-off::before { content: "\f60f"; } +.bi-volume-up-fill::before { content: "\f610"; } +.bi-volume-up::before { content: "\f611"; } +.bi-vr::before { content: "\f612"; } +.bi-wallet-fill::before { content: "\f613"; } +.bi-wallet::before { content: "\f614"; } +.bi-wallet2::before { content: "\f615"; } +.bi-watch::before { content: "\f616"; } +.bi-water::before { content: "\f617"; } +.bi-whatsapp::before { content: "\f618"; } +.bi-wifi-1::before { content: "\f619"; } +.bi-wifi-2::before { content: "\f61a"; } +.bi-wifi-off::before { content: "\f61b"; } +.bi-wifi::before { content: "\f61c"; } +.bi-wind::before { content: "\f61d"; } +.bi-window-dock::before { content: "\f61e"; } +.bi-window-sidebar::before { content: "\f61f"; } +.bi-window::before { content: "\f620"; } +.bi-wrench::before { content: "\f621"; } +.bi-x-circle-fill::before { content: "\f622"; } +.bi-x-circle::before { content: "\f623"; } +.bi-x-diamond-fill::before { content: "\f624"; } +.bi-x-diamond::before { content: "\f625"; } +.bi-x-octagon-fill::before { content: "\f626"; } +.bi-x-octagon::before { content: "\f627"; } +.bi-x-square-fill::before { content: "\f628"; } +.bi-x-square::before { content: "\f629"; } +.bi-x::before { content: "\f62a"; } +.bi-youtube::before { content: "\f62b"; } +.bi-zoom-in::before { content: "\f62c"; } +.bi-zoom-out::before { content: "\f62d"; } +.bi-bank::before { content: "\f62e"; } +.bi-bank2::before { content: "\f62f"; } +.bi-bell-slash-fill::before { content: "\f630"; } +.bi-bell-slash::before { content: "\f631"; } +.bi-cash-coin::before { content: "\f632"; } +.bi-check-lg::before { content: "\f633"; } +.bi-coin::before { content: "\f634"; } +.bi-currency-bitcoin::before { content: "\f635"; } +.bi-currency-dollar::before { content: "\f636"; } +.bi-currency-euro::before { content: "\f637"; } +.bi-currency-exchange::before { content: "\f638"; } +.bi-currency-pound::before { content: "\f639"; } +.bi-currency-yen::before { content: "\f63a"; } +.bi-dash-lg::before { content: "\f63b"; } +.bi-exclamation-lg::before { content: "\f63c"; } +.bi-file-earmark-pdf-fill::before { content: "\f63d"; } +.bi-file-earmark-pdf::before { content: "\f63e"; } +.bi-file-pdf-fill::before { content: "\f63f"; } +.bi-file-pdf::before { content: "\f640"; } +.bi-gender-ambiguous::before { content: "\f641"; } +.bi-gender-female::before { content: "\f642"; } +.bi-gender-male::before { content: "\f643"; } +.bi-gender-trans::before { content: "\f644"; } +.bi-headset-vr::before { content: "\f645"; } +.bi-info-lg::before { content: "\f646"; } +.bi-mastodon::before { content: "\f647"; } +.bi-messenger::before { content: "\f648"; } +.bi-piggy-bank-fill::before { content: "\f649"; } +.bi-piggy-bank::before { content: "\f64a"; } +.bi-pin-map-fill::before { content: "\f64b"; } +.bi-pin-map::before { content: "\f64c"; } +.bi-plus-lg::before { content: "\f64d"; } +.bi-question-lg::before { content: "\f64e"; } +.bi-recycle::before { content: "\f64f"; } +.bi-reddit::before { content: "\f650"; } +.bi-safe-fill::before { content: "\f651"; } +.bi-safe2-fill::before { content: "\f652"; } +.bi-safe2::before { content: "\f653"; } +.bi-sd-card-fill::before { content: "\f654"; } +.bi-sd-card::before { content: "\f655"; } +.bi-skype::before { content: "\f656"; } +.bi-slash-lg::before { content: "\f657"; } +.bi-translate::before { content: "\f658"; } +.bi-x-lg::before { content: "\f659"; } +.bi-safe::before { content: "\f65a"; } +.bi-apple::before { content: "\f65b"; } +.bi-microsoft::before { content: "\f65d"; } +.bi-windows::before { content: "\f65e"; } +.bi-behance::before { content: "\f65c"; } +.bi-dribbble::before { content: "\f65f"; } +.bi-line::before { content: "\f660"; } +.bi-medium::before { content: "\f661"; } +.bi-paypal::before { content: "\f662"; } +.bi-pinterest::before { content: "\f663"; } +.bi-signal::before { content: "\f664"; } +.bi-snapchat::before { content: "\f665"; } +.bi-spotify::before { content: "\f666"; } +.bi-stack-overflow::before { content: "\f667"; } +.bi-strava::before { content: "\f668"; } +.bi-wordpress::before { content: "\f669"; } +.bi-vimeo::before { content: "\f66a"; } +.bi-activity::before { content: "\f66b"; } +.bi-easel2-fill::before { content: "\f66c"; } +.bi-easel2::before { content: "\f66d"; } +.bi-easel3-fill::before { content: "\f66e"; } +.bi-easel3::before { content: "\f66f"; } +.bi-fan::before { content: "\f670"; } +.bi-fingerprint::before { content: "\f671"; } +.bi-graph-down-arrow::before { content: "\f672"; } +.bi-graph-up-arrow::before { content: "\f673"; } +.bi-hypnotize::before { content: "\f674"; } +.bi-magic::before { content: "\f675"; } +.bi-person-rolodex::before { content: "\f676"; } +.bi-person-video::before { content: "\f677"; } +.bi-person-video2::before { content: "\f678"; } +.bi-person-video3::before { content: "\f679"; } +.bi-person-workspace::before { content: "\f67a"; } +.bi-radioactive::before { content: "\f67b"; } +.bi-webcam-fill::before { content: "\f67c"; } +.bi-webcam::before { content: "\f67d"; } +.bi-yin-yang::before { content: "\f67e"; } +.bi-bandaid-fill::before { content: "\f680"; } +.bi-bandaid::before { content: "\f681"; } +.bi-bluetooth::before { content: "\f682"; } +.bi-body-text::before { content: "\f683"; } +.bi-boombox::before { content: "\f684"; } +.bi-boxes::before { content: "\f685"; } +.bi-dpad-fill::before { content: "\f686"; } +.bi-dpad::before { content: "\f687"; } +.bi-ear-fill::before { content: "\f688"; } +.bi-ear::before { content: "\f689"; } +.bi-envelope-check-fill::before { content: "\f68b"; } +.bi-envelope-check::before { content: "\f68c"; } +.bi-envelope-dash-fill::before { content: "\f68e"; } +.bi-envelope-dash::before { content: "\f68f"; } +.bi-envelope-exclamation-fill::before { content: "\f691"; } +.bi-envelope-exclamation::before { content: "\f692"; } +.bi-envelope-plus-fill::before { content: "\f693"; } +.bi-envelope-plus::before { content: "\f694"; } +.bi-envelope-slash-fill::before { content: "\f696"; } +.bi-envelope-slash::before { content: "\f697"; } +.bi-envelope-x-fill::before { content: "\f699"; } +.bi-envelope-x::before { content: "\f69a"; } +.bi-explicit-fill::before { content: "\f69b"; } +.bi-explicit::before { content: "\f69c"; } +.bi-git::before { content: "\f69d"; } +.bi-infinity::before { content: "\f69e"; } +.bi-list-columns-reverse::before { content: "\f69f"; } +.bi-list-columns::before { content: "\f6a0"; } +.bi-meta::before { content: "\f6a1"; } +.bi-nintendo-switch::before { content: "\f6a4"; } +.bi-pc-display-horizontal::before { content: "\f6a5"; } +.bi-pc-display::before { content: "\f6a6"; } +.bi-pc-horizontal::before { content: "\f6a7"; } +.bi-pc::before { content: "\f6a8"; } +.bi-playstation::before { content: "\f6a9"; } +.bi-plus-slash-minus::before { content: "\f6aa"; } +.bi-projector-fill::before { content: "\f6ab"; } +.bi-projector::before { content: "\f6ac"; } +.bi-qr-code-scan::before { content: "\f6ad"; } +.bi-qr-code::before { content: "\f6ae"; } +.bi-quora::before { content: "\f6af"; } +.bi-quote::before { content: "\f6b0"; } +.bi-robot::before { content: "\f6b1"; } +.bi-send-check-fill::before { content: "\f6b2"; } +.bi-send-check::before { content: "\f6b3"; } +.bi-send-dash-fill::before { content: "\f6b4"; } +.bi-send-dash::before { content: "\f6b5"; } +.bi-send-exclamation-fill::before { content: "\f6b7"; } +.bi-send-exclamation::before { content: "\f6b8"; } +.bi-send-fill::before { content: "\f6b9"; } +.bi-send-plus-fill::before { content: "\f6ba"; } +.bi-send-plus::before { content: "\f6bb"; } +.bi-send-slash-fill::before { content: "\f6bc"; } +.bi-send-slash::before { content: "\f6bd"; } +.bi-send-x-fill::before { content: "\f6be"; } +.bi-send-x::before { content: "\f6bf"; } +.bi-send::before { content: "\f6c0"; } +.bi-steam::before { content: "\f6c1"; } +.bi-terminal-dash::before { content: "\f6c3"; } +.bi-terminal-plus::before { content: "\f6c4"; } +.bi-terminal-split::before { content: "\f6c5"; } +.bi-ticket-detailed-fill::before { content: "\f6c6"; } +.bi-ticket-detailed::before { content: "\f6c7"; } +.bi-ticket-fill::before { content: "\f6c8"; } +.bi-ticket-perforated-fill::before { content: "\f6c9"; } +.bi-ticket-perforated::before { content: "\f6ca"; } +.bi-ticket::before { content: "\f6cb"; } +.bi-tiktok::before { content: "\f6cc"; } +.bi-window-dash::before { content: "\f6cd"; } +.bi-window-desktop::before { content: "\f6ce"; } +.bi-window-fullscreen::before { content: "\f6cf"; } +.bi-window-plus::before { content: "\f6d0"; } +.bi-window-split::before { content: "\f6d1"; } +.bi-window-stack::before { content: "\f6d2"; } +.bi-window-x::before { content: "\f6d3"; } +.bi-xbox::before { content: "\f6d4"; } +.bi-ethernet::before { content: "\f6d5"; } +.bi-hdmi-fill::before { content: "\f6d6"; } +.bi-hdmi::before { content: "\f6d7"; } +.bi-usb-c-fill::before { content: "\f6d8"; } +.bi-usb-c::before { content: "\f6d9"; } +.bi-usb-fill::before { content: "\f6da"; } +.bi-usb-plug-fill::before { content: "\f6db"; } +.bi-usb-plug::before { content: "\f6dc"; } +.bi-usb-symbol::before { content: "\f6dd"; } +.bi-usb::before { content: "\f6de"; } +.bi-boombox-fill::before { content: "\f6df"; } +.bi-displayport::before { content: "\f6e1"; } +.bi-gpu-card::before { content: "\f6e2"; } +.bi-memory::before { content: "\f6e3"; } +.bi-modem-fill::before { content: "\f6e4"; } +.bi-modem::before { content: "\f6e5"; } +.bi-motherboard-fill::before { content: "\f6e6"; } +.bi-motherboard::before { content: "\f6e7"; } +.bi-optical-audio-fill::before { content: "\f6e8"; } +.bi-optical-audio::before { content: "\f6e9"; } +.bi-pci-card::before { content: "\f6ea"; } +.bi-router-fill::before { content: "\f6eb"; } +.bi-router::before { content: "\f6ec"; } +.bi-thunderbolt-fill::before { content: "\f6ef"; } +.bi-thunderbolt::before { content: "\f6f0"; } +.bi-usb-drive-fill::before { content: "\f6f1"; } +.bi-usb-drive::before { content: "\f6f2"; } +.bi-usb-micro-fill::before { content: "\f6f3"; } +.bi-usb-micro::before { content: "\f6f4"; } +.bi-usb-mini-fill::before { content: "\f6f5"; } +.bi-usb-mini::before { content: "\f6f6"; } +.bi-cloud-haze2::before { content: "\f6f7"; } +.bi-device-hdd-fill::before { content: "\f6f8"; } +.bi-device-hdd::before { content: "\f6f9"; } +.bi-device-ssd-fill::before { content: "\f6fa"; } +.bi-device-ssd::before { content: "\f6fb"; } +.bi-displayport-fill::before { content: "\f6fc"; } +.bi-mortarboard-fill::before { content: "\f6fd"; } +.bi-mortarboard::before { content: "\f6fe"; } +.bi-terminal-x::before { content: "\f6ff"; } +.bi-arrow-through-heart-fill::before { content: "\f700"; } +.bi-arrow-through-heart::before { content: "\f701"; } +.bi-badge-sd-fill::before { content: "\f702"; } +.bi-badge-sd::before { content: "\f703"; } +.bi-bag-heart-fill::before { content: "\f704"; } +.bi-bag-heart::before { content: "\f705"; } +.bi-balloon-fill::before { content: "\f706"; } +.bi-balloon-heart-fill::before { content: "\f707"; } +.bi-balloon-heart::before { content: "\f708"; } +.bi-balloon::before { content: "\f709"; } +.bi-box2-fill::before { content: "\f70a"; } +.bi-box2-heart-fill::before { content: "\f70b"; } +.bi-box2-heart::before { content: "\f70c"; } +.bi-box2::before { content: "\f70d"; } +.bi-braces-asterisk::before { content: "\f70e"; } +.bi-calendar-heart-fill::before { content: "\f70f"; } +.bi-calendar-heart::before { content: "\f710"; } +.bi-calendar2-heart-fill::before { content: "\f711"; } +.bi-calendar2-heart::before { content: "\f712"; } +.bi-chat-heart-fill::before { content: "\f713"; } +.bi-chat-heart::before { content: "\f714"; } +.bi-chat-left-heart-fill::before { content: "\f715"; } +.bi-chat-left-heart::before { content: "\f716"; } +.bi-chat-right-heart-fill::before { content: "\f717"; } +.bi-chat-right-heart::before { content: "\f718"; } +.bi-chat-square-heart-fill::before { content: "\f719"; } +.bi-chat-square-heart::before { content: "\f71a"; } +.bi-clipboard-check-fill::before { content: "\f71b"; } +.bi-clipboard-data-fill::before { content: "\f71c"; } +.bi-clipboard-fill::before { content: "\f71d"; } +.bi-clipboard-heart-fill::before { content: "\f71e"; } +.bi-clipboard-heart::before { content: "\f71f"; } +.bi-clipboard-minus-fill::before { content: "\f720"; } +.bi-clipboard-plus-fill::before { content: "\f721"; } +.bi-clipboard-pulse::before { content: "\f722"; } +.bi-clipboard-x-fill::before { content: "\f723"; } +.bi-clipboard2-check-fill::before { content: "\f724"; } +.bi-clipboard2-check::before { content: "\f725"; } +.bi-clipboard2-data-fill::before { content: "\f726"; } +.bi-clipboard2-data::before { content: "\f727"; } +.bi-clipboard2-fill::before { content: "\f728"; } +.bi-clipboard2-heart-fill::before { content: "\f729"; } +.bi-clipboard2-heart::before { content: "\f72a"; } +.bi-clipboard2-minus-fill::before { content: "\f72b"; } +.bi-clipboard2-minus::before { content: "\f72c"; } +.bi-clipboard2-plus-fill::before { content: "\f72d"; } +.bi-clipboard2-plus::before { content: "\f72e"; } +.bi-clipboard2-pulse-fill::before { content: "\f72f"; } +.bi-clipboard2-pulse::before { content: "\f730"; } +.bi-clipboard2-x-fill::before { content: "\f731"; } +.bi-clipboard2-x::before { content: "\f732"; } +.bi-clipboard2::before { content: "\f733"; } +.bi-emoji-kiss-fill::before { content: "\f734"; } +.bi-emoji-kiss::before { content: "\f735"; } +.bi-envelope-heart-fill::before { content: "\f736"; } +.bi-envelope-heart::before { content: "\f737"; } +.bi-envelope-open-heart-fill::before { content: "\f738"; } +.bi-envelope-open-heart::before { content: "\f739"; } +.bi-envelope-paper-fill::before { content: "\f73a"; } +.bi-envelope-paper-heart-fill::before { content: "\f73b"; } +.bi-envelope-paper-heart::before { content: "\f73c"; } +.bi-envelope-paper::before { content: "\f73d"; } +.bi-filetype-aac::before { content: "\f73e"; } +.bi-filetype-ai::before { content: "\f73f"; } +.bi-filetype-bmp::before { content: "\f740"; } +.bi-filetype-cs::before { content: "\f741"; } +.bi-filetype-css::before { content: "\f742"; } +.bi-filetype-csv::before { content: "\f743"; } +.bi-filetype-doc::before { content: "\f744"; } +.bi-filetype-docx::before { content: "\f745"; } +.bi-filetype-exe::before { content: "\f746"; } +.bi-filetype-gif::before { content: "\f747"; } +.bi-filetype-heic::before { content: "\f748"; } +.bi-filetype-html::before { content: "\f749"; } +.bi-filetype-java::before { content: "\f74a"; } +.bi-filetype-jpg::before { content: "\f74b"; } +.bi-filetype-js::before { content: "\f74c"; } +.bi-filetype-jsx::before { content: "\f74d"; } +.bi-filetype-key::before { content: "\f74e"; } +.bi-filetype-m4p::before { content: "\f74f"; } +.bi-filetype-md::before { content: "\f750"; } +.bi-filetype-mdx::before { content: "\f751"; } +.bi-filetype-mov::before { content: "\f752"; } +.bi-filetype-mp3::before { content: "\f753"; } +.bi-filetype-mp4::before { content: "\f754"; } +.bi-filetype-otf::before { content: "\f755"; } +.bi-filetype-pdf::before { content: "\f756"; } +.bi-filetype-php::before { content: "\f757"; } +.bi-filetype-png::before { content: "\f758"; } +.bi-filetype-ppt::before { content: "\f75a"; } +.bi-filetype-psd::before { content: "\f75b"; } +.bi-filetype-py::before { content: "\f75c"; } +.bi-filetype-raw::before { content: "\f75d"; } +.bi-filetype-rb::before { content: "\f75e"; } +.bi-filetype-sass::before { content: "\f75f"; } +.bi-filetype-scss::before { content: "\f760"; } +.bi-filetype-sh::before { content: "\f761"; } +.bi-filetype-svg::before { content: "\f762"; } +.bi-filetype-tiff::before { content: "\f763"; } +.bi-filetype-tsx::before { content: "\f764"; } +.bi-filetype-ttf::before { content: "\f765"; } +.bi-filetype-txt::before { content: "\f766"; } +.bi-filetype-wav::before { content: "\f767"; } +.bi-filetype-woff::before { content: "\f768"; } +.bi-filetype-xls::before { content: "\f76a"; } +.bi-filetype-xml::before { content: "\f76b"; } +.bi-filetype-yml::before { content: "\f76c"; } +.bi-heart-arrow::before { content: "\f76d"; } +.bi-heart-pulse-fill::before { content: "\f76e"; } +.bi-heart-pulse::before { content: "\f76f"; } +.bi-heartbreak-fill::before { content: "\f770"; } +.bi-heartbreak::before { content: "\f771"; } +.bi-hearts::before { content: "\f772"; } +.bi-hospital-fill::before { content: "\f773"; } +.bi-hospital::before { content: "\f774"; } +.bi-house-heart-fill::before { content: "\f775"; } +.bi-house-heart::before { content: "\f776"; } +.bi-incognito::before { content: "\f777"; } +.bi-magnet-fill::before { content: "\f778"; } +.bi-magnet::before { content: "\f779"; } +.bi-person-heart::before { content: "\f77a"; } +.bi-person-hearts::before { content: "\f77b"; } +.bi-phone-flip::before { content: "\f77c"; } +.bi-plugin::before { content: "\f77d"; } +.bi-postage-fill::before { content: "\f77e"; } +.bi-postage-heart-fill::before { content: "\f77f"; } +.bi-postage-heart::before { content: "\f780"; } +.bi-postage::before { content: "\f781"; } +.bi-postcard-fill::before { content: "\f782"; } +.bi-postcard-heart-fill::before { content: "\f783"; } +.bi-postcard-heart::before { content: "\f784"; } +.bi-postcard::before { content: "\f785"; } +.bi-search-heart-fill::before { content: "\f786"; } +.bi-search-heart::before { content: "\f787"; } +.bi-sliders2-vertical::before { content: "\f788"; } +.bi-sliders2::before { content: "\f789"; } +.bi-trash3-fill::before { content: "\f78a"; } +.bi-trash3::before { content: "\f78b"; } +.bi-valentine::before { content: "\f78c"; } +.bi-valentine2::before { content: "\f78d"; } +.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; } +.bi-wrench-adjustable-circle::before { content: "\f78f"; } +.bi-wrench-adjustable::before { content: "\f790"; } +.bi-filetype-json::before { content: "\f791"; } +.bi-filetype-pptx::before { content: "\f792"; } +.bi-filetype-xlsx::before { content: "\f793"; } +.bi-1-circle-fill::before { content: "\f796"; } +.bi-1-circle::before { content: "\f797"; } +.bi-1-square-fill::before { content: "\f798"; } +.bi-1-square::before { content: "\f799"; } +.bi-2-circle-fill::before { content: "\f79c"; } +.bi-2-circle::before { content: "\f79d"; } +.bi-2-square-fill::before { content: "\f79e"; } +.bi-2-square::before { content: "\f79f"; } +.bi-3-circle-fill::before { content: "\f7a2"; } +.bi-3-circle::before { content: "\f7a3"; } +.bi-3-square-fill::before { content: "\f7a4"; } +.bi-3-square::before { content: "\f7a5"; } +.bi-4-circle-fill::before { content: "\f7a8"; } +.bi-4-circle::before { content: "\f7a9"; } +.bi-4-square-fill::before { content: "\f7aa"; } +.bi-4-square::before { content: "\f7ab"; } +.bi-5-circle-fill::before { content: "\f7ae"; } +.bi-5-circle::before { content: "\f7af"; } +.bi-5-square-fill::before { content: "\f7b0"; } +.bi-5-square::before { content: "\f7b1"; } +.bi-6-circle-fill::before { content: "\f7b4"; } +.bi-6-circle::before { content: "\f7b5"; } +.bi-6-square-fill::before { content: "\f7b6"; } +.bi-6-square::before { content: "\f7b7"; } +.bi-7-circle-fill::before { content: "\f7ba"; } +.bi-7-circle::before { content: "\f7bb"; } +.bi-7-square-fill::before { content: "\f7bc"; } +.bi-7-square::before { content: "\f7bd"; } +.bi-8-circle-fill::before { content: "\f7c0"; } +.bi-8-circle::before { content: "\f7c1"; } +.bi-8-square-fill::before { content: "\f7c2"; } +.bi-8-square::before { content: "\f7c3"; } +.bi-9-circle-fill::before { content: "\f7c6"; } +.bi-9-circle::before { content: "\f7c7"; } +.bi-9-square-fill::before { content: "\f7c8"; } +.bi-9-square::before { content: "\f7c9"; } +.bi-airplane-engines-fill::before { content: "\f7ca"; } +.bi-airplane-engines::before { content: "\f7cb"; } +.bi-airplane-fill::before { content: "\f7cc"; } +.bi-airplane::before { content: "\f7cd"; } +.bi-alexa::before { content: "\f7ce"; } +.bi-alipay::before { content: "\f7cf"; } +.bi-android::before { content: "\f7d0"; } +.bi-android2::before { content: "\f7d1"; } +.bi-box-fill::before { content: "\f7d2"; } +.bi-box-seam-fill::before { content: "\f7d3"; } +.bi-browser-chrome::before { content: "\f7d4"; } +.bi-browser-edge::before { content: "\f7d5"; } +.bi-browser-firefox::before { content: "\f7d6"; } +.bi-browser-safari::before { content: "\f7d7"; } +.bi-c-circle-fill::before { content: "\f7da"; } +.bi-c-circle::before { content: "\f7db"; } +.bi-c-square-fill::before { content: "\f7dc"; } +.bi-c-square::before { content: "\f7dd"; } +.bi-capsule-pill::before { content: "\f7de"; } +.bi-capsule::before { content: "\f7df"; } +.bi-car-front-fill::before { content: "\f7e0"; } +.bi-car-front::before { content: "\f7e1"; } +.bi-cassette-fill::before { content: "\f7e2"; } +.bi-cassette::before { content: "\f7e3"; } +.bi-cc-circle-fill::before { content: "\f7e6"; } +.bi-cc-circle::before { content: "\f7e7"; } +.bi-cc-square-fill::before { content: "\f7e8"; } +.bi-cc-square::before { content: "\f7e9"; } +.bi-cup-hot-fill::before { content: "\f7ea"; } +.bi-cup-hot::before { content: "\f7eb"; } +.bi-currency-rupee::before { content: "\f7ec"; } +.bi-dropbox::before { content: "\f7ed"; } +.bi-escape::before { content: "\f7ee"; } +.bi-fast-forward-btn-fill::before { content: "\f7ef"; } +.bi-fast-forward-btn::before { content: "\f7f0"; } +.bi-fast-forward-circle-fill::before { content: "\f7f1"; } +.bi-fast-forward-circle::before { content: "\f7f2"; } +.bi-fast-forward-fill::before { content: "\f7f3"; } +.bi-fast-forward::before { content: "\f7f4"; } +.bi-filetype-sql::before { content: "\f7f5"; } +.bi-fire::before { content: "\f7f6"; } +.bi-google-play::before { content: "\f7f7"; } +.bi-h-circle-fill::before { content: "\f7fa"; } +.bi-h-circle::before { content: "\f7fb"; } +.bi-h-square-fill::before { content: "\f7fc"; } +.bi-h-square::before { content: "\f7fd"; } +.bi-indent::before { content: "\f7fe"; } +.bi-lungs-fill::before { content: "\f7ff"; } +.bi-lungs::before { content: "\f800"; } +.bi-microsoft-teams::before { content: "\f801"; } +.bi-p-circle-fill::before { content: "\f804"; } +.bi-p-circle::before { content: "\f805"; } +.bi-p-square-fill::before { content: "\f806"; } +.bi-p-square::before { content: "\f807"; } +.bi-pass-fill::before { content: "\f808"; } +.bi-pass::before { content: "\f809"; } +.bi-prescription::before { content: "\f80a"; } +.bi-prescription2::before { content: "\f80b"; } +.bi-r-circle-fill::before { content: "\f80e"; } +.bi-r-circle::before { content: "\f80f"; } +.bi-r-square-fill::before { content: "\f810"; } +.bi-r-square::before { content: "\f811"; } +.bi-repeat-1::before { content: "\f812"; } +.bi-repeat::before { content: "\f813"; } +.bi-rewind-btn-fill::before { content: "\f814"; } +.bi-rewind-btn::before { content: "\f815"; } +.bi-rewind-circle-fill::before { content: "\f816"; } +.bi-rewind-circle::before { content: "\f817"; } +.bi-rewind-fill::before { content: "\f818"; } +.bi-rewind::before { content: "\f819"; } +.bi-train-freight-front-fill::before { content: "\f81a"; } +.bi-train-freight-front::before { content: "\f81b"; } +.bi-train-front-fill::before { content: "\f81c"; } +.bi-train-front::before { content: "\f81d"; } +.bi-train-lightrail-front-fill::before { content: "\f81e"; } +.bi-train-lightrail-front::before { content: "\f81f"; } +.bi-truck-front-fill::before { content: "\f820"; } +.bi-truck-front::before { content: "\f821"; } +.bi-ubuntu::before { content: "\f822"; } +.bi-unindent::before { content: "\f823"; } +.bi-unity::before { content: "\f824"; } +.bi-universal-access-circle::before { content: "\f825"; } +.bi-universal-access::before { content: "\f826"; } +.bi-virus::before { content: "\f827"; } +.bi-virus2::before { content: "\f828"; } +.bi-wechat::before { content: "\f829"; } +.bi-yelp::before { content: "\f82a"; } +.bi-sign-stop-fill::before { content: "\f82b"; } +.bi-sign-stop-lights-fill::before { content: "\f82c"; } +.bi-sign-stop-lights::before { content: "\f82d"; } +.bi-sign-stop::before { content: "\f82e"; } +.bi-sign-turn-left-fill::before { content: "\f82f"; } +.bi-sign-turn-left::before { content: "\f830"; } +.bi-sign-turn-right-fill::before { content: "\f831"; } +.bi-sign-turn-right::before { content: "\f832"; } +.bi-sign-turn-slight-left-fill::before { content: "\f833"; } +.bi-sign-turn-slight-left::before { content: "\f834"; } +.bi-sign-turn-slight-right-fill::before { content: "\f835"; } +.bi-sign-turn-slight-right::before { content: "\f836"; } +.bi-sign-yield-fill::before { content: "\f837"; } +.bi-sign-yield::before { content: "\f838"; } +.bi-ev-station-fill::before { content: "\f839"; } +.bi-ev-station::before { content: "\f83a"; } +.bi-fuel-pump-diesel-fill::before { content: "\f83b"; } +.bi-fuel-pump-diesel::before { content: "\f83c"; } +.bi-fuel-pump-fill::before { content: "\f83d"; } +.bi-fuel-pump::before { content: "\f83e"; } +.bi-0-circle-fill::before { content: "\f83f"; } +.bi-0-circle::before { content: "\f840"; } +.bi-0-square-fill::before { content: "\f841"; } +.bi-0-square::before { content: "\f842"; } +.bi-rocket-fill::before { content: "\f843"; } +.bi-rocket-takeoff-fill::before { content: "\f844"; } +.bi-rocket-takeoff::before { content: "\f845"; } +.bi-rocket::before { content: "\f846"; } +.bi-stripe::before { content: "\f847"; } +.bi-subscript::before { content: "\f848"; } +.bi-superscript::before { content: "\f849"; } +.bi-trello::before { content: "\f84a"; } +.bi-envelope-at-fill::before { content: "\f84b"; } +.bi-envelope-at::before { content: "\f84c"; } +.bi-regex::before { content: "\f84d"; } +.bi-text-wrap::before { content: "\f84e"; } +.bi-sign-dead-end-fill::before { content: "\f84f"; } +.bi-sign-dead-end::before { content: "\f850"; } +.bi-sign-do-not-enter-fill::before { content: "\f851"; } +.bi-sign-do-not-enter::before { content: "\f852"; } +.bi-sign-intersection-fill::before { content: "\f853"; } +.bi-sign-intersection-side-fill::before { content: "\f854"; } +.bi-sign-intersection-side::before { content: "\f855"; } +.bi-sign-intersection-t-fill::before { content: "\f856"; } +.bi-sign-intersection-t::before { content: "\f857"; } +.bi-sign-intersection-y-fill::before { content: "\f858"; } +.bi-sign-intersection-y::before { content: "\f859"; } +.bi-sign-intersection::before { content: "\f85a"; } +.bi-sign-merge-left-fill::before { content: "\f85b"; } +.bi-sign-merge-left::before { content: "\f85c"; } +.bi-sign-merge-right-fill::before { content: "\f85d"; } +.bi-sign-merge-right::before { content: "\f85e"; } +.bi-sign-no-left-turn-fill::before { content: "\f85f"; } +.bi-sign-no-left-turn::before { content: "\f860"; } +.bi-sign-no-parking-fill::before { content: "\f861"; } +.bi-sign-no-parking::before { content: "\f862"; } +.bi-sign-no-right-turn-fill::before { content: "\f863"; } +.bi-sign-no-right-turn::before { content: "\f864"; } +.bi-sign-railroad-fill::before { content: "\f865"; } +.bi-sign-railroad::before { content: "\f866"; } +.bi-building-add::before { content: "\f867"; } +.bi-building-check::before { content: "\f868"; } +.bi-building-dash::before { content: "\f869"; } +.bi-building-down::before { content: "\f86a"; } +.bi-building-exclamation::before { content: "\f86b"; } +.bi-building-fill-add::before { content: "\f86c"; } +.bi-building-fill-check::before { content: "\f86d"; } +.bi-building-fill-dash::before { content: "\f86e"; } +.bi-building-fill-down::before { content: "\f86f"; } +.bi-building-fill-exclamation::before { content: "\f870"; } +.bi-building-fill-gear::before { content: "\f871"; } +.bi-building-fill-lock::before { content: "\f872"; } +.bi-building-fill-slash::before { content: "\f873"; } +.bi-building-fill-up::before { content: "\f874"; } +.bi-building-fill-x::before { content: "\f875"; } +.bi-building-fill::before { content: "\f876"; } +.bi-building-gear::before { content: "\f877"; } +.bi-building-lock::before { content: "\f878"; } +.bi-building-slash::before { content: "\f879"; } +.bi-building-up::before { content: "\f87a"; } +.bi-building-x::before { content: "\f87b"; } +.bi-buildings-fill::before { content: "\f87c"; } +.bi-buildings::before { content: "\f87d"; } +.bi-bus-front-fill::before { content: "\f87e"; } +.bi-bus-front::before { content: "\f87f"; } +.bi-ev-front-fill::before { content: "\f880"; } +.bi-ev-front::before { content: "\f881"; } +.bi-globe-americas::before { content: "\f882"; } +.bi-globe-asia-australia::before { content: "\f883"; } +.bi-globe-central-south-asia::before { content: "\f884"; } +.bi-globe-europe-africa::before { content: "\f885"; } +.bi-house-add-fill::before { content: "\f886"; } +.bi-house-add::before { content: "\f887"; } +.bi-house-check-fill::before { content: "\f888"; } +.bi-house-check::before { content: "\f889"; } +.bi-house-dash-fill::before { content: "\f88a"; } +.bi-house-dash::before { content: "\f88b"; } +.bi-house-down-fill::before { content: "\f88c"; } +.bi-house-down::before { content: "\f88d"; } +.bi-house-exclamation-fill::before { content: "\f88e"; } +.bi-house-exclamation::before { content: "\f88f"; } +.bi-house-gear-fill::before { content: "\f890"; } +.bi-house-gear::before { content: "\f891"; } +.bi-house-lock-fill::before { content: "\f892"; } +.bi-house-lock::before { content: "\f893"; } +.bi-house-slash-fill::before { content: "\f894"; } +.bi-house-slash::before { content: "\f895"; } +.bi-house-up-fill::before { content: "\f896"; } +.bi-house-up::before { content: "\f897"; } +.bi-house-x-fill::before { content: "\f898"; } +.bi-house-x::before { content: "\f899"; } +.bi-person-add::before { content: "\f89a"; } +.bi-person-down::before { content: "\f89b"; } +.bi-person-exclamation::before { content: "\f89c"; } +.bi-person-fill-add::before { content: "\f89d"; } +.bi-person-fill-check::before { content: "\f89e"; } +.bi-person-fill-dash::before { content: "\f89f"; } +.bi-person-fill-down::before { content: "\f8a0"; } +.bi-person-fill-exclamation::before { content: "\f8a1"; } +.bi-person-fill-gear::before { content: "\f8a2"; } +.bi-person-fill-lock::before { content: "\f8a3"; } +.bi-person-fill-slash::before { content: "\f8a4"; } +.bi-person-fill-up::before { content: "\f8a5"; } +.bi-person-fill-x::before { content: "\f8a6"; } +.bi-person-gear::before { content: "\f8a7"; } +.bi-person-lock::before { content: "\f8a8"; } +.bi-person-slash::before { content: "\f8a9"; } +.bi-person-up::before { content: "\f8aa"; } +.bi-scooter::before { content: "\f8ab"; } +.bi-taxi-front-fill::before { content: "\f8ac"; } +.bi-taxi-front::before { content: "\f8ad"; } +.bi-amd::before { content: "\f8ae"; } +.bi-database-add::before { content: "\f8af"; } +.bi-database-check::before { content: "\f8b0"; } +.bi-database-dash::before { content: "\f8b1"; } +.bi-database-down::before { content: "\f8b2"; } +.bi-database-exclamation::before { content: "\f8b3"; } +.bi-database-fill-add::before { content: "\f8b4"; } +.bi-database-fill-check::before { content: "\f8b5"; } +.bi-database-fill-dash::before { content: "\f8b6"; } +.bi-database-fill-down::before { content: "\f8b7"; } +.bi-database-fill-exclamation::before { content: "\f8b8"; } +.bi-database-fill-gear::before { content: "\f8b9"; } +.bi-database-fill-lock::before { content: "\f8ba"; } +.bi-database-fill-slash::before { content: "\f8bb"; } +.bi-database-fill-up::before { content: "\f8bc"; } +.bi-database-fill-x::before { content: "\f8bd"; } +.bi-database-fill::before { content: "\f8be"; } +.bi-database-gear::before { content: "\f8bf"; } +.bi-database-lock::before { content: "\f8c0"; } +.bi-database-slash::before { content: "\f8c1"; } +.bi-database-up::before { content: "\f8c2"; } +.bi-database-x::before { content: "\f8c3"; } +.bi-database::before { content: "\f8c4"; } +.bi-houses-fill::before { content: "\f8c5"; } +.bi-houses::before { content: "\f8c6"; } +.bi-nvidia::before { content: "\f8c7"; } +.bi-person-vcard-fill::before { content: "\f8c8"; } +.bi-person-vcard::before { content: "\f8c9"; } +.bi-sina-weibo::before { content: "\f8ca"; } +.bi-tencent-qq::before { content: "\f8cb"; } +.bi-wikipedia::before { content: "\f8cc"; } +.bi-alphabet-uppercase::before { content: "\f2a5"; } +.bi-alphabet::before { content: "\f68a"; } +.bi-amazon::before { content: "\f68d"; } +.bi-arrows-collapse-vertical::before { content: "\f690"; } +.bi-arrows-expand-vertical::before { content: "\f695"; } +.bi-arrows-vertical::before { content: "\f698"; } +.bi-arrows::before { content: "\f6a2"; } +.bi-ban-fill::before { content: "\f6a3"; } +.bi-ban::before { content: "\f6b6"; } +.bi-bing::before { content: "\f6c2"; } +.bi-cake::before { content: "\f6e0"; } +.bi-cake2::before { content: "\f6ed"; } +.bi-cookie::before { content: "\f6ee"; } +.bi-copy::before { content: "\f759"; } +.bi-crosshair::before { content: "\f769"; } +.bi-crosshair2::before { content: "\f794"; } +.bi-emoji-astonished-fill::before { content: "\f795"; } +.bi-emoji-astonished::before { content: "\f79a"; } +.bi-emoji-grimace-fill::before { content: "\f79b"; } +.bi-emoji-grimace::before { content: "\f7a0"; } +.bi-emoji-grin-fill::before { content: "\f7a1"; } +.bi-emoji-grin::before { content: "\f7a6"; } +.bi-emoji-surprise-fill::before { content: "\f7a7"; } +.bi-emoji-surprise::before { content: "\f7ac"; } +.bi-emoji-tear-fill::before { content: "\f7ad"; } +.bi-emoji-tear::before { content: "\f7b2"; } +.bi-envelope-arrow-down-fill::before { content: "\f7b3"; } +.bi-envelope-arrow-down::before { content: "\f7b8"; } +.bi-envelope-arrow-up-fill::before { content: "\f7b9"; } +.bi-envelope-arrow-up::before { content: "\f7be"; } +.bi-feather::before { content: "\f7bf"; } +.bi-feather2::before { content: "\f7c4"; } +.bi-floppy-fill::before { content: "\f7c5"; } +.bi-floppy::before { content: "\f7d8"; } +.bi-floppy2-fill::before { content: "\f7d9"; } +.bi-floppy2::before { content: "\f7e4"; } +.bi-gitlab::before { content: "\f7e5"; } +.bi-highlighter::before { content: "\f7f8"; } +.bi-marker-tip::before { content: "\f802"; } +.bi-nvme-fill::before { content: "\f803"; } +.bi-nvme::before { content: "\f80c"; } +.bi-opencollective::before { content: "\f80d"; } +.bi-pci-card-network::before { content: "\f8cd"; } +.bi-pci-card-sound::before { content: "\f8ce"; } +.bi-radar::before { content: "\f8cf"; } +.bi-send-arrow-down-fill::before { content: "\f8d0"; } +.bi-send-arrow-down::before { content: "\f8d1"; } +.bi-send-arrow-up-fill::before { content: "\f8d2"; } +.bi-send-arrow-up::before { content: "\f8d3"; } +.bi-sim-slash-fill::before { content: "\f8d4"; } +.bi-sim-slash::before { content: "\f8d5"; } +.bi-sourceforge::before { content: "\f8d6"; } +.bi-substack::before { content: "\f8d7"; } +.bi-threads-fill::before { content: "\f8d8"; } +.bi-threads::before { content: "\f8d9"; } +.bi-transparency::before { content: "\f8da"; } +.bi-twitter-x::before { content: "\f8db"; } +.bi-type-h4::before { content: "\f8dc"; } +.bi-type-h5::before { content: "\f8dd"; } +.bi-type-h6::before { content: "\f8de"; } +.bi-backpack-fill::before { content: "\f8df"; } +.bi-backpack::before { content: "\f8e0"; } +.bi-backpack2-fill::before { content: "\f8e1"; } +.bi-backpack2::before { content: "\f8e2"; } +.bi-backpack3-fill::before { content: "\f8e3"; } +.bi-backpack3::before { content: "\f8e4"; } +.bi-backpack4-fill::before { content: "\f8e5"; } +.bi-backpack4::before { content: "\f8e6"; } +.bi-brilliance::before { content: "\f8e7"; } +.bi-cake-fill::before { content: "\f8e8"; } +.bi-cake2-fill::before { content: "\f8e9"; } +.bi-duffle-fill::before { content: "\f8ea"; } +.bi-duffle::before { content: "\f8eb"; } +.bi-exposure::before { content: "\f8ec"; } +.bi-gender-neuter::before { content: "\f8ed"; } +.bi-highlights::before { content: "\f8ee"; } +.bi-luggage-fill::before { content: "\f8ef"; } +.bi-luggage::before { content: "\f8f0"; } +.bi-mailbox-flag::before { content: "\f8f1"; } +.bi-mailbox2-flag::before { content: "\f8f2"; } +.bi-noise-reduction::before { content: "\f8f3"; } +.bi-passport-fill::before { content: "\f8f4"; } +.bi-passport::before { content: "\f8f5"; } +.bi-person-arms-up::before { content: "\f8f6"; } +.bi-person-raised-hand::before { content: "\f8f7"; } +.bi-person-standing-dress::before { content: "\f8f8"; } +.bi-person-standing::before { content: "\f8f9"; } +.bi-person-walking::before { content: "\f8fa"; } +.bi-person-wheelchair::before { content: "\f8fb"; } +.bi-shadows::before { content: "\f8fc"; } +.bi-suitcase-fill::before { content: "\f8fd"; } +.bi-suitcase-lg-fill::before { content: "\f8fe"; } +.bi-suitcase-lg::before { content: "\f8ff"; } +.bi-suitcase::before { content: "\f900"; } +.bi-suitcase2-fill::before { content: "\f901"; } +.bi-suitcase2::before { content: "\f902"; } +.bi-vignette::before { content: "\f903"; } diff --git a/public/bootstrap.css b/public/bootstrap.css new file mode 100644 index 0000000..b0315e1 --- /dev/null +++ b/public/bootstrap.css @@ -0,0 +1,12111 @@ +@charset "UTF-8"; +/*! + * Bootstrap v5.3.0-alpha3 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +:root, +[data-bs-theme=light] { + --bs-blue: #0d6efd; + --bs-indigo: #6610f2; + --bs-purple: #6f42c1; + --bs-pink: #d63384; + --bs-red: #dc3545; + --bs-orange: #fd7e14; + --bs-yellow: #ffc107; + --bs-green: #198754; + --bs-teal: #20c997; + --bs-cyan: #0dcaf0; + --bs-black: #000; + --bs-white: #fff; + --bs-gray: #6c757d; + --bs-gray-dark: #343a40; + --bs-gray-100: #f8f9fa; + --bs-gray-200: #e9ecef; + --bs-gray-300: #dee2e6; + --bs-gray-400: #ced4da; + --bs-gray-500: #adb5bd; + --bs-gray-600: #6c757d; + --bs-gray-700: #495057; + --bs-gray-800: #343a40; + --bs-gray-900: #212529; + --bs-primary: #0d6efd; + --bs-secondary: #6c757d; + --bs-success: #198754; + --bs-info: #0dcaf0; + --bs-warning: #ffc107; + --bs-danger: #dc3545; + --bs-light: #f8f9fa; + --bs-dark: #212529; + --bs-primary-rgb: 13, 110, 253; + --bs-secondary-rgb: 108, 117, 125; + --bs-success-rgb: 25, 135, 84; + --bs-info-rgb: 13, 202, 240; + --bs-warning-rgb: 255, 193, 7; + --bs-danger-rgb: 220, 53, 69; + --bs-light-rgb: 248, 249, 250; + --bs-dark-rgb: 33, 37, 41; + --bs-primary-text-emphasis: #052c65; + --bs-secondary-text-emphasis: #2b2f32; + --bs-success-text-emphasis: #0a3622; + --bs-info-text-emphasis: #055160; + --bs-warning-text-emphasis: #664d03; + --bs-danger-text-emphasis: #58151c; + --bs-light-text-emphasis: #495057; + --bs-dark-text-emphasis: #495057; + --bs-primary-bg-subtle: #cfe2ff; + --bs-secondary-bg-subtle: #e2e3e5; + --bs-success-bg-subtle: #d1e7dd; + --bs-info-bg-subtle: #cff4fc; + --bs-warning-bg-subtle: #fff3cd; + --bs-danger-bg-subtle: #f8d7da; + --bs-light-bg-subtle: #fcfcfd; + --bs-dark-bg-subtle: #ced4da; + --bs-primary-border-subtle: #9ec5fe; + --bs-secondary-border-subtle: #c4c8cb; + --bs-success-border-subtle: #a3cfbb; + --bs-info-border-subtle: #9eeaf9; + --bs-warning-border-subtle: #ffe69c; + --bs-danger-border-subtle: #f1aeb5; + --bs-light-border-subtle: #e9ecef; + --bs-dark-border-subtle: #adb5bd; + --bs-white-rgb: 255, 255, 255; + --bs-black-rgb: 0, 0, 0; + --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); + --bs-body-font-family: var(--bs-font-sans-serif); + --bs-body-font-size: 1rem; + --bs-body-font-weight: 400; + --bs-body-line-height: 1.5; + --bs-body-color: #212529; + --bs-body-color-rgb: 33, 37, 41; + --bs-body-bg: #fff; + --bs-body-bg-rgb: 255, 255, 255; + --bs-emphasis-color: #000; + --bs-emphasis-color-rgb: 0, 0, 0; + --bs-secondary-color: rgba(33, 37, 41, 0.75); + --bs-secondary-color-rgb: 33, 37, 41; + --bs-secondary-bg: #e9ecef; + --bs-secondary-bg-rgb: 233, 236, 239; + --bs-tertiary-color: rgba(33, 37, 41, 0.5); + --bs-tertiary-color-rgb: 33, 37, 41; + --bs-tertiary-bg: #f8f9fa; + --bs-tertiary-bg-rgb: 248, 249, 250; + --bs-link-color: #0d6efd; + --bs-link-color-rgb: 13, 110, 253; + --bs-link-decoration: underline; + --bs-link-hover-color: #0a58ca; + --bs-link-hover-color-rgb: 10, 88, 202; + --bs-code-color: #d63384; + --bs-highlight-bg: #fff3cd; + --bs-border-width: 1px; + --bs-border-style: solid; + --bs-border-color: #dee2e6; + --bs-border-color-translucent: rgba(0, 0, 0, 0.175); + --bs-border-radius: 0.375rem; + --bs-border-radius-sm: 0.25rem; + --bs-border-radius-lg: 0.5rem; + --bs-border-radius-xl: 1rem; + --bs-border-radius-xxl: 2rem; + --bs-border-radius-2xl: var(--bs-border-radius-xxl); + --bs-border-radius-pill: 50rem; + --bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); + --bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175); + --bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075); + --bs-focus-ring-width: 0.25rem; + --bs-focus-ring-opacity: 0.25; + --bs-focus-ring-color: rgba(13, 110, 253, 0.25); + --bs-form-valid-color: #198754; + --bs-form-valid-border-color: #198754; + --bs-form-invalid-color: #dc3545; + --bs-form-invalid-border-color: #dc3545; +} + +[data-bs-theme=dark] { + color-scheme: dark; + --bs-body-color: #adb5bd; + --bs-body-color-rgb: 173, 181, 189; + --bs-body-bg: #212529; + --bs-body-bg-rgb: 33, 37, 41; + --bs-emphasis-color: #fff; + --bs-emphasis-color-rgb: 255, 255, 255; + --bs-secondary-color: rgba(173, 181, 189, 0.75); + --bs-secondary-color-rgb: 173, 181, 189; + --bs-secondary-bg: #343a40; + --bs-secondary-bg-rgb: 52, 58, 64; + --bs-tertiary-color: rgba(173, 181, 189, 0.5); + --bs-tertiary-color-rgb: 173, 181, 189; + --bs-tertiary-bg: #2b3035; + --bs-tertiary-bg-rgb: 43, 48, 53; + --bs-primary-text-emphasis: #6ea8fe; + --bs-secondary-text-emphasis: #a7acb1; + --bs-success-text-emphasis: #75b798; + --bs-info-text-emphasis: #6edff6; + --bs-warning-text-emphasis: #ffda6a; + --bs-danger-text-emphasis: #ea868f; + --bs-light-text-emphasis: #f8f9fa; + --bs-dark-text-emphasis: #dee2e6; + --bs-primary-bg-subtle: #031633; + --bs-secondary-bg-subtle: #161719; + --bs-success-bg-subtle: #051b11; + --bs-info-bg-subtle: #032830; + --bs-warning-bg-subtle: #332701; + --bs-danger-bg-subtle: #2c0b0e; + --bs-light-bg-subtle: #343a40; + --bs-dark-bg-subtle: #1a1d20; + --bs-primary-border-subtle: #084298; + --bs-secondary-border-subtle: #41464b; + --bs-success-border-subtle: #0f5132; + --bs-info-border-subtle: #087990; + --bs-warning-border-subtle: #997404; + --bs-danger-border-subtle: #842029; + --bs-light-border-subtle: #495057; + --bs-dark-border-subtle: #343a40; + --bs-link-color: #6ea8fe; + --bs-link-hover-color: #8bb9fe; + --bs-link-color-rgb: 110, 168, 254; + --bs-link-hover-color-rgb: 139, 185, 254; + --bs-code-color: #e685b5; + --bs-border-color: #495057; + --bs-border-color-translucent: rgba(255, 255, 255, 0.15); + --bs-form-valid-color: #75b798; + --bs-form-valid-border-color: #75b798; + --bs-form-invalid-color: #ea868f; + --bs-form-invalid-border-color: #ea868f; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +@media (prefers-reduced-motion: no-preference) { + :root { + scroll-behavior: smooth; + } +} + +body { + margin: 0; + font-family: var(--bs-body-font-family); + font-size: var(--bs-body-font-size); + font-weight: var(--bs-body-font-weight); + line-height: var(--bs-body-line-height); + color: var(--bs-body-color); + text-align: var(--bs-body-text-align); + background-color: var(--bs-body-bg); + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +hr { + margin: 1rem 0; + color: inherit; + border: 0; + border-top: var(--bs-border-width) solid; + opacity: 0.25; +} + +h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 { + margin-top: 0; + margin-bottom: 0.5rem; + font-weight: 500; + line-height: 1.2; + color: var(--bs-heading-color, inherit); +} + +h1, .h1 { + font-size: calc(1.375rem + 1.5vw); +} +@media (min-width: 1200px) { + h1, .h1 { + font-size: 2.5rem; + } +} + +h2, .h2 { + font-size: calc(1.325rem + 0.9vw); +} +@media (min-width: 1200px) { + h2, .h2 { + font-size: 2rem; + } +} + +h3, .h3 { + font-size: calc(1.3rem + 0.6vw); +} +@media (min-width: 1200px) { + h3, .h3 { + font-size: 1.75rem; + } +} + +h4, .h4 { + font-size: calc(1.275rem + 0.3vw); +} +@media (min-width: 1200px) { + h4, .h4 { + font-size: 1.5rem; + } +} + +h5, .h5 { + font-size: 1.25rem; +} + +h6, .h6 { + font-size: 1rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title] { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul { + padding-left: 2rem; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: 0.5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +b, +strong { + font-weight: bolder; +} + +small, .small { + font-size: 0.875em; +} + +mark, .mark { + padding: 0.1875em; + background-color: var(--bs-highlight-bg); +} + +sub, +sup { + position: relative; + font-size: 0.75em; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +a { + color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1)); + text-decoration: underline; +} +a:hover { + --bs-link-color-rgb: var(--bs-link-hover-color-rgb); +} + +a:not([href]):not([class]), a:not([href]):not([class]):hover { + color: inherit; + text-decoration: none; +} + +pre, +code, +kbd, +samp { + font-family: var(--bs-font-monospace); + font-size: 1em; +} + +pre { + display: block; + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + font-size: 0.875em; +} +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} + +code { + font-size: 0.875em; + color: var(--bs-code-color); + word-wrap: break-word; +} +a > code { + color: inherit; +} + +kbd { + padding: 0.1875rem 0.375rem; + font-size: 0.875em; + color: var(--bs-body-bg); + background-color: var(--bs-body-color); + border-radius: 0.25rem; +} +kbd kbd { + padding: 0; + font-size: 1em; +} + +figure { + margin: 0 0 1rem; +} + +img, +svg { + vertical-align: middle; +} + +table { + caption-side: bottom; + border-collapse: collapse; +} + +caption { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + color: var(--bs-secondary-color); + text-align: left; +} + +th { + text-align: inherit; + text-align: -webkit-match-parent; +} + +thead, +tbody, +tfoot, +tr, +td, +th { + border-color: inherit; + border-style: solid; + border-width: 0; +} + +label { + display: inline-block; +} + +button { + border-radius: 0; +} + +button:focus:not(:focus-visible) { + outline: 0; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +select { + text-transform: none; +} + +[role=button] { + cursor: pointer; +} + +select { + word-wrap: normal; +} +select:disabled { + opacity: 1; +} + +[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator { + display: none !important; +} + +button, +[type=button], +[type=reset], +[type=submit] { + -webkit-appearance: button; +} +button:not(:disabled), +[type=button]:not(:disabled), +[type=reset]:not(:disabled), +[type=submit]:not(:disabled) { + cursor: pointer; +} + +::-moz-focus-inner { + padding: 0; + border-style: none; +} + +textarea { + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + float: left; + width: 100%; + padding: 0; + margin-bottom: 0.5rem; + font-size: calc(1.275rem + 0.3vw); + line-height: inherit; +} +@media (min-width: 1200px) { + legend { + font-size: 1.5rem; + } +} +legend + * { + clear: left; +} + +::-webkit-datetime-edit-fields-wrapper, +::-webkit-datetime-edit-text, +::-webkit-datetime-edit-minute, +::-webkit-datetime-edit-hour-field, +::-webkit-datetime-edit-day-field, +::-webkit-datetime-edit-month-field, +::-webkit-datetime-edit-year-field { + padding: 0; +} + +::-webkit-inner-spin-button { + height: auto; +} + +[type=search] { + outline-offset: -2px; + -webkit-appearance: textfield; +} + +/* rtl:raw: +[type="tel"], +[type="url"], +[type="email"], +[type="number"] { + direction: ltr; +} +*/ +::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-color-swatch-wrapper { + padding: 0; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +::file-selector-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +iframe { + border: 0; +} + +summary { + display: list-item; + cursor: pointer; +} + +progress { + vertical-align: baseline; +} + +[hidden] { + display: none !important; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: calc(1.625rem + 4.5vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-1 { + font-size: 5rem; + } +} + +.display-2 { + font-size: calc(1.575rem + 3.9vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-2 { + font-size: 4.5rem; + } +} + +.display-3 { + font-size: calc(1.525rem + 3.3vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-3 { + font-size: 4rem; + } +} + +.display-4 { + font-size: calc(1.475rem + 2.7vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-4 { + font-size: 3.5rem; + } +} + +.display-5 { + font-size: calc(1.425rem + 2.1vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-5 { + font-size: 3rem; + } +} + +.display-6 { + font-size: calc(1.375rem + 1.5vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-6 { + font-size: 2.5rem; + } +} + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + +.list-inline-item { + display: inline-block; +} +.list-inline-item:not(:last-child) { + margin-right: 0.5rem; +} + +.initialism { + font-size: 0.875em; + text-transform: uppercase; +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem; +} +.blockquote > :last-child { + margin-bottom: 0; +} + +.blockquote-footer { + margin-top: -1rem; + margin-bottom: 1rem; + font-size: 0.875em; + color: #6c757d; +} +.blockquote-footer::before { + content: "— "; +} + +.img-fluid { + max-width: 100%; + height: auto; +} + +.img-thumbnail { + padding: 0.25rem; + background-color: var(--bs-body-bg); + border: var(--bs-border-width) solid var(--bs-border-color); + border-radius: var(--bs-border-radius); + max-width: 100%; + height: auto; +} + +.figure { + display: inline-block; +} + +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} + +.figure-caption { + font-size: 0.875em; + color: var(--bs-secondary-color); +} + +.container, +.container-fluid, +.container-xxl, +.container-xl, +.container-lg, +.container-md, +.container-sm { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + width: 100%; + padding-right: calc(var(--bs-gutter-x) * 0.5); + padding-left: calc(var(--bs-gutter-x) * 0.5); + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container-sm, .container { + max-width: 540px; + } +} +@media (min-width: 768px) { + .container-md, .container-sm, .container { + max-width: 720px; + } +} +@media (min-width: 992px) { + .container-lg, .container-md, .container-sm, .container { + max-width: 960px; + } +} +@media (min-width: 1200px) { + .container-xl, .container-lg, .container-md, .container-sm, .container { + max-width: 1140px; + } +} +@media (min-width: 1400px) { + .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { + max-width: 1320px; + } +} +:root { + --bs-breakpoint-xs: 0; + --bs-breakpoint-sm: 576px; + --bs-breakpoint-md: 768px; + --bs-breakpoint-lg: 992px; + --bs-breakpoint-xl: 1200px; + --bs-breakpoint-xxl: 1400px; +} + +.row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + display: flex; + flex-wrap: wrap; + margin-top: calc(-1 * var(--bs-gutter-y)); + margin-right: calc(-0.5 * var(--bs-gutter-x)); + margin-left: calc(-0.5 * var(--bs-gutter-x)); +} +.row > * { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x) * 0.5); + padding-left: calc(var(--bs-gutter-x) * 0.5); + margin-top: var(--bs-gutter-y); +} + +.col { + flex: 1 0 0%; +} + +.row-cols-auto > * { + flex: 0 0 auto; + width: auto; +} + +.row-cols-1 > * { + flex: 0 0 auto; + width: 100%; +} + +.row-cols-2 > * { + flex: 0 0 auto; + width: 50%; +} + +.row-cols-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; +} + +.row-cols-4 > * { + flex: 0 0 auto; + width: 25%; +} + +.row-cols-5 > * { + flex: 0 0 auto; + width: 20%; +} + +.row-cols-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; +} + +.col-auto { + flex: 0 0 auto; + width: auto; +} + +.col-1 { + flex: 0 0 auto; + width: 8.33333333%; +} + +.col-2 { + flex: 0 0 auto; + width: 16.66666667%; +} + +.col-3 { + flex: 0 0 auto; + width: 25%; +} + +.col-4 { + flex: 0 0 auto; + width: 33.33333333%; +} + +.col-5 { + flex: 0 0 auto; + width: 41.66666667%; +} + +.col-6 { + flex: 0 0 auto; + width: 50%; +} + +.col-7 { + flex: 0 0 auto; + width: 58.33333333%; +} + +.col-8 { + flex: 0 0 auto; + width: 66.66666667%; +} + +.col-9 { + flex: 0 0 auto; + width: 75%; +} + +.col-10 { + flex: 0 0 auto; + width: 83.33333333%; +} + +.col-11 { + flex: 0 0 auto; + width: 91.66666667%; +} + +.col-12 { + flex: 0 0 auto; + width: 100%; +} + +.offset-1 { + margin-left: 8.33333333%; +} + +.offset-2 { + margin-left: 16.66666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.33333333%; +} + +.offset-5 { + margin-left: 41.66666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.33333333%; +} + +.offset-8 { + margin-left: 66.66666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.33333333%; +} + +.offset-11 { + margin-left: 91.66666667%; +} + +.g-0, +.gx-0 { + --bs-gutter-x: 0; +} + +.g-0, +.gy-0 { + --bs-gutter-y: 0; +} + +.g-1, +.gx-1 { + --bs-gutter-x: 0.25rem; +} + +.g-1, +.gy-1 { + --bs-gutter-y: 0.25rem; +} + +.g-2, +.gx-2 { + --bs-gutter-x: 0.5rem; +} + +.g-2, +.gy-2 { + --bs-gutter-y: 0.5rem; +} + +.g-3, +.gx-3 { + --bs-gutter-x: 1rem; +} + +.g-3, +.gy-3 { + --bs-gutter-y: 1rem; +} + +.g-4, +.gx-4 { + --bs-gutter-x: 1.5rem; +} + +.g-4, +.gy-4 { + --bs-gutter-y: 1.5rem; +} + +.g-5, +.gx-5 { + --bs-gutter-x: 3rem; +} + +.g-5, +.gy-5 { + --bs-gutter-y: 3rem; +} + +@media (min-width: 576px) { + .col-sm { + flex: 1 0 0%; + } + .row-cols-sm-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-sm-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-sm-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-sm-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-sm-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-sm-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-sm-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-sm-auto { + flex: 0 0 auto; + width: auto; + } + .col-sm-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + .col-sm-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + .col-sm-3 { + flex: 0 0 auto; + width: 25%; + } + .col-sm-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + .col-sm-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + .col-sm-6 { + flex: 0 0 auto; + width: 50%; + } + .col-sm-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + .col-sm-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + .col-sm-9 { + flex: 0 0 auto; + width: 75%; + } + .col-sm-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + .col-sm-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + .col-sm-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-sm-0 { + margin-left: 0; + } + .offset-sm-1 { + margin-left: 8.33333333%; + } + .offset-sm-2 { + margin-left: 16.66666667%; + } + .offset-sm-3 { + margin-left: 25%; + } + .offset-sm-4 { + margin-left: 33.33333333%; + } + .offset-sm-5 { + margin-left: 41.66666667%; + } + .offset-sm-6 { + margin-left: 50%; + } + .offset-sm-7 { + margin-left: 58.33333333%; + } + .offset-sm-8 { + margin-left: 66.66666667%; + } + .offset-sm-9 { + margin-left: 75%; + } + .offset-sm-10 { + margin-left: 83.33333333%; + } + .offset-sm-11 { + margin-left: 91.66666667%; + } + .g-sm-0, + .gx-sm-0 { + --bs-gutter-x: 0; + } + .g-sm-0, + .gy-sm-0 { + --bs-gutter-y: 0; + } + .g-sm-1, + .gx-sm-1 { + --bs-gutter-x: 0.25rem; + } + .g-sm-1, + .gy-sm-1 { + --bs-gutter-y: 0.25rem; + } + .g-sm-2, + .gx-sm-2 { + --bs-gutter-x: 0.5rem; + } + .g-sm-2, + .gy-sm-2 { + --bs-gutter-y: 0.5rem; + } + .g-sm-3, + .gx-sm-3 { + --bs-gutter-x: 1rem; + } + .g-sm-3, + .gy-sm-3 { + --bs-gutter-y: 1rem; + } + .g-sm-4, + .gx-sm-4 { + --bs-gutter-x: 1.5rem; + } + .g-sm-4, + .gy-sm-4 { + --bs-gutter-y: 1.5rem; + } + .g-sm-5, + .gx-sm-5 { + --bs-gutter-x: 3rem; + } + .g-sm-5, + .gy-sm-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 768px) { + .col-md { + flex: 1 0 0%; + } + .row-cols-md-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-md-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-md-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-md-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-md-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-md-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-md-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-md-auto { + flex: 0 0 auto; + width: auto; + } + .col-md-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + .col-md-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + .col-md-3 { + flex: 0 0 auto; + width: 25%; + } + .col-md-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + .col-md-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + .col-md-6 { + flex: 0 0 auto; + width: 50%; + } + .col-md-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + .col-md-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + .col-md-9 { + flex: 0 0 auto; + width: 75%; + } + .col-md-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + .col-md-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + .col-md-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-md-0 { + margin-left: 0; + } + .offset-md-1 { + margin-left: 8.33333333%; + } + .offset-md-2 { + margin-left: 16.66666667%; + } + .offset-md-3 { + margin-left: 25%; + } + .offset-md-4 { + margin-left: 33.33333333%; + } + .offset-md-5 { + margin-left: 41.66666667%; + } + .offset-md-6 { + margin-left: 50%; + } + .offset-md-7 { + margin-left: 58.33333333%; + } + .offset-md-8 { + margin-left: 66.66666667%; + } + .offset-md-9 { + margin-left: 75%; + } + .offset-md-10 { + margin-left: 83.33333333%; + } + .offset-md-11 { + margin-left: 91.66666667%; + } + .g-md-0, + .gx-md-0 { + --bs-gutter-x: 0; + } + .g-md-0, + .gy-md-0 { + --bs-gutter-y: 0; + } + .g-md-1, + .gx-md-1 { + --bs-gutter-x: 0.25rem; + } + .g-md-1, + .gy-md-1 { + --bs-gutter-y: 0.25rem; + } + .g-md-2, + .gx-md-2 { + --bs-gutter-x: 0.5rem; + } + .g-md-2, + .gy-md-2 { + --bs-gutter-y: 0.5rem; + } + .g-md-3, + .gx-md-3 { + --bs-gutter-x: 1rem; + } + .g-md-3, + .gy-md-3 { + --bs-gutter-y: 1rem; + } + .g-md-4, + .gx-md-4 { + --bs-gutter-x: 1.5rem; + } + .g-md-4, + .gy-md-4 { + --bs-gutter-y: 1.5rem; + } + .g-md-5, + .gx-md-5 { + --bs-gutter-x: 3rem; + } + .g-md-5, + .gy-md-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 992px) { + .col-lg { + flex: 1 0 0%; + } + .row-cols-lg-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-lg-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-lg-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-lg-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-lg-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-lg-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-lg-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-lg-auto { + flex: 0 0 auto; + width: auto; + } + .col-lg-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + .col-lg-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + .col-lg-3 { + flex: 0 0 auto; + width: 25%; + } + .col-lg-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + .col-lg-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + .col-lg-6 { + flex: 0 0 auto; + width: 50%; + } + .col-lg-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + .col-lg-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + .col-lg-9 { + flex: 0 0 auto; + width: 75%; + } + .col-lg-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + .col-lg-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + .col-lg-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-lg-0 { + margin-left: 0; + } + .offset-lg-1 { + margin-left: 8.33333333%; + } + .offset-lg-2 { + margin-left: 16.66666667%; + } + .offset-lg-3 { + margin-left: 25%; + } + .offset-lg-4 { + margin-left: 33.33333333%; + } + .offset-lg-5 { + margin-left: 41.66666667%; + } + .offset-lg-6 { + margin-left: 50%; + } + .offset-lg-7 { + margin-left: 58.33333333%; + } + .offset-lg-8 { + margin-left: 66.66666667%; + } + .offset-lg-9 { + margin-left: 75%; + } + .offset-lg-10 { + margin-left: 83.33333333%; + } + .offset-lg-11 { + margin-left: 91.66666667%; + } + .g-lg-0, + .gx-lg-0 { + --bs-gutter-x: 0; + } + .g-lg-0, + .gy-lg-0 { + --bs-gutter-y: 0; + } + .g-lg-1, + .gx-lg-1 { + --bs-gutter-x: 0.25rem; + } + .g-lg-1, + .gy-lg-1 { + --bs-gutter-y: 0.25rem; + } + .g-lg-2, + .gx-lg-2 { + --bs-gutter-x: 0.5rem; + } + .g-lg-2, + .gy-lg-2 { + --bs-gutter-y: 0.5rem; + } + .g-lg-3, + .gx-lg-3 { + --bs-gutter-x: 1rem; + } + .g-lg-3, + .gy-lg-3 { + --bs-gutter-y: 1rem; + } + .g-lg-4, + .gx-lg-4 { + --bs-gutter-x: 1.5rem; + } + .g-lg-4, + .gy-lg-4 { + --bs-gutter-y: 1.5rem; + } + .g-lg-5, + .gx-lg-5 { + --bs-gutter-x: 3rem; + } + .g-lg-5, + .gy-lg-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 1200px) { + .col-xl { + flex: 1 0 0%; + } + .row-cols-xl-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-xl-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-xl-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-xl-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-xl-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-xl-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-xl-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-xl-auto { + flex: 0 0 auto; + width: auto; + } + .col-xl-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + .col-xl-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + .col-xl-3 { + flex: 0 0 auto; + width: 25%; + } + .col-xl-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + .col-xl-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + .col-xl-6 { + flex: 0 0 auto; + width: 50%; + } + .col-xl-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + .col-xl-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + .col-xl-9 { + flex: 0 0 auto; + width: 75%; + } + .col-xl-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + .col-xl-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + .col-xl-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-xl-0 { + margin-left: 0; + } + .offset-xl-1 { + margin-left: 8.33333333%; + } + .offset-xl-2 { + margin-left: 16.66666667%; + } + .offset-xl-3 { + margin-left: 25%; + } + .offset-xl-4 { + margin-left: 33.33333333%; + } + .offset-xl-5 { + margin-left: 41.66666667%; + } + .offset-xl-6 { + margin-left: 50%; + } + .offset-xl-7 { + margin-left: 58.33333333%; + } + .offset-xl-8 { + margin-left: 66.66666667%; + } + .offset-xl-9 { + margin-left: 75%; + } + .offset-xl-10 { + margin-left: 83.33333333%; + } + .offset-xl-11 { + margin-left: 91.66666667%; + } + .g-xl-0, + .gx-xl-0 { + --bs-gutter-x: 0; + } + .g-xl-0, + .gy-xl-0 { + --bs-gutter-y: 0; + } + .g-xl-1, + .gx-xl-1 { + --bs-gutter-x: 0.25rem; + } + .g-xl-1, + .gy-xl-1 { + --bs-gutter-y: 0.25rem; + } + .g-xl-2, + .gx-xl-2 { + --bs-gutter-x: 0.5rem; + } + .g-xl-2, + .gy-xl-2 { + --bs-gutter-y: 0.5rem; + } + .g-xl-3, + .gx-xl-3 { + --bs-gutter-x: 1rem; + } + .g-xl-3, + .gy-xl-3 { + --bs-gutter-y: 1rem; + } + .g-xl-4, + .gx-xl-4 { + --bs-gutter-x: 1.5rem; + } + .g-xl-4, + .gy-xl-4 { + --bs-gutter-y: 1.5rem; + } + .g-xl-5, + .gx-xl-5 { + --bs-gutter-x: 3rem; + } + .g-xl-5, + .gy-xl-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 1400px) { + .col-xxl { + flex: 1 0 0%; + } + .row-cols-xxl-auto > * { + flex: 0 0 auto; + width: auto; + } + .row-cols-xxl-1 > * { + flex: 0 0 auto; + width: 100%; + } + .row-cols-xxl-2 > * { + flex: 0 0 auto; + width: 50%; + } + .row-cols-xxl-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + .row-cols-xxl-4 > * { + flex: 0 0 auto; + width: 25%; + } + .row-cols-xxl-5 > * { + flex: 0 0 auto; + width: 20%; + } + .row-cols-xxl-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + .col-xxl-auto { + flex: 0 0 auto; + width: auto; + } + .col-xxl-1 { + flex: 0 0 auto; + width: 8.33333333%; + } + .col-xxl-2 { + flex: 0 0 auto; + width: 16.66666667%; + } + .col-xxl-3 { + flex: 0 0 auto; + width: 25%; + } + .col-xxl-4 { + flex: 0 0 auto; + width: 33.33333333%; + } + .col-xxl-5 { + flex: 0 0 auto; + width: 41.66666667%; + } + .col-xxl-6 { + flex: 0 0 auto; + width: 50%; + } + .col-xxl-7 { + flex: 0 0 auto; + width: 58.33333333%; + } + .col-xxl-8 { + flex: 0 0 auto; + width: 66.66666667%; + } + .col-xxl-9 { + flex: 0 0 auto; + width: 75%; + } + .col-xxl-10 { + flex: 0 0 auto; + width: 83.33333333%; + } + .col-xxl-11 { + flex: 0 0 auto; + width: 91.66666667%; + } + .col-xxl-12 { + flex: 0 0 auto; + width: 100%; + } + .offset-xxl-0 { + margin-left: 0; + } + .offset-xxl-1 { + margin-left: 8.33333333%; + } + .offset-xxl-2 { + margin-left: 16.66666667%; + } + .offset-xxl-3 { + margin-left: 25%; + } + .offset-xxl-4 { + margin-left: 33.33333333%; + } + .offset-xxl-5 { + margin-left: 41.66666667%; + } + .offset-xxl-6 { + margin-left: 50%; + } + .offset-xxl-7 { + margin-left: 58.33333333%; + } + .offset-xxl-8 { + margin-left: 66.66666667%; + } + .offset-xxl-9 { + margin-left: 75%; + } + .offset-xxl-10 { + margin-left: 83.33333333%; + } + .offset-xxl-11 { + margin-left: 91.66666667%; + } + .g-xxl-0, + .gx-xxl-0 { + --bs-gutter-x: 0; + } + .g-xxl-0, + .gy-xxl-0 { + --bs-gutter-y: 0; + } + .g-xxl-1, + .gx-xxl-1 { + --bs-gutter-x: 0.25rem; + } + .g-xxl-1, + .gy-xxl-1 { + --bs-gutter-y: 0.25rem; + } + .g-xxl-2, + .gx-xxl-2 { + --bs-gutter-x: 0.5rem; + } + .g-xxl-2, + .gy-xxl-2 { + --bs-gutter-y: 0.5rem; + } + .g-xxl-3, + .gx-xxl-3 { + --bs-gutter-x: 1rem; + } + .g-xxl-3, + .gy-xxl-3 { + --bs-gutter-y: 1rem; + } + .g-xxl-4, + .gx-xxl-4 { + --bs-gutter-x: 1.5rem; + } + .g-xxl-4, + .gy-xxl-4 { + --bs-gutter-y: 1.5rem; + } + .g-xxl-5, + .gx-xxl-5 { + --bs-gutter-x: 3rem; + } + .g-xxl-5, + .gy-xxl-5 { + --bs-gutter-y: 3rem; + } +} +.table { + --bs-table-color: var(--bs-body-color); + --bs-table-bg: transparent; + --bs-table-border-color: var(--bs-border-color); + --bs-table-accent-bg: transparent; + --bs-table-striped-color: var(--bs-body-color); + --bs-table-striped-bg: rgba(0, 0, 0, 0.05); + --bs-table-active-color: var(--bs-body-color); + --bs-table-active-bg: rgba(0, 0, 0, 0.1); + --bs-table-hover-color: var(--bs-body-color); + --bs-table-hover-bg: rgba(0, 0, 0, 0.075); + width: 100%; + margin-bottom: 1rem; + color: var(--bs-table-color); + vertical-align: top; + border-color: var(--bs-table-border-color); +} +.table > :not(caption) > * > * { + padding: 0.5rem 0.5rem; + background-color: var(--bs-table-bg); + border-bottom-width: var(--bs-border-width); + box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); +} +.table > tbody { + vertical-align: inherit; +} +.table > thead { + vertical-align: bottom; +} + +.table-group-divider { + border-top: calc(var(--bs-border-width) * 2) solid currentcolor; +} + +.caption-top { + caption-side: top; +} + +.table-sm > :not(caption) > * > * { + padding: 0.25rem 0.25rem; +} + +.table-bordered > :not(caption) > * { + border-width: var(--bs-border-width) 0; +} +.table-bordered > :not(caption) > * > * { + border-width: 0 var(--bs-border-width); +} + +.table-borderless > :not(caption) > * > * { + border-bottom-width: 0; +} +.table-borderless > :not(:first-child) { + border-top-width: 0; +} + +.table-striped > tbody > tr:nth-of-type(odd) > * { + --bs-table-accent-bg: var(--bs-table-striped-bg); + color: var(--bs-table-striped-color); +} + +.table-striped-columns > :not(caption) > tr > :nth-child(even) { + --bs-table-accent-bg: var(--bs-table-striped-bg); + color: var(--bs-table-striped-color); +} + +.table-active { + --bs-table-accent-bg: var(--bs-table-active-bg); + color: var(--bs-table-active-color); +} + +.table-hover > tbody > tr:hover > * { + --bs-table-accent-bg: var(--bs-table-hover-bg); + color: var(--bs-table-hover-color); +} + +.table-primary { + --bs-table-color: #000; + --bs-table-bg: #cfe2ff; + --bs-table-border-color: #bacbe6; + --bs-table-striped-bg: #c5d7f2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bacbe6; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfd1ec; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-secondary { + --bs-table-color: #000; + --bs-table-bg: #e2e3e5; + --bs-table-border-color: #cbccce; + --bs-table-striped-bg: #d7d8da; + --bs-table-striped-color: #000; + --bs-table-active-bg: #cbccce; + --bs-table-active-color: #000; + --bs-table-hover-bg: #d1d2d4; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-success { + --bs-table-color: #000; + --bs-table-bg: #d1e7dd; + --bs-table-border-color: #bcd0c7; + --bs-table-striped-bg: #c7dbd2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bcd0c7; + --bs-table-active-color: #000; + --bs-table-hover-bg: #c1d6cc; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-info { + --bs-table-color: #000; + --bs-table-bg: #cff4fc; + --bs-table-border-color: #badce3; + --bs-table-striped-bg: #c5e8ef; + --bs-table-striped-color: #000; + --bs-table-active-bg: #badce3; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfe2e9; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-warning { + --bs-table-color: #000; + --bs-table-bg: #fff3cd; + --bs-table-border-color: #e6dbb9; + --bs-table-striped-bg: #f2e7c3; + --bs-table-striped-color: #000; + --bs-table-active-bg: #e6dbb9; + --bs-table-active-color: #000; + --bs-table-hover-bg: #ece1be; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-danger { + --bs-table-color: #000; + --bs-table-bg: #f8d7da; + --bs-table-border-color: #dfc2c4; + --bs-table-striped-bg: #eccccf; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfc2c4; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5c7ca; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-light { + --bs-table-color: #000; + --bs-table-bg: #f8f9fa; + --bs-table-border-color: #dfe0e1; + --bs-table-striped-bg: #ecedee; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfe0e1; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5e6e7; + --bs-table-hover-color: #000; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-dark { + --bs-table-color: #fff; + --bs-table-bg: #212529; + --bs-table-border-color: #373b3e; + --bs-table-striped-bg: #2c3034; + --bs-table-striped-color: #fff; + --bs-table-active-bg: #373b3e; + --bs-table-active-color: #fff; + --bs-table-hover-bg: #323539; + --bs-table-hover-color: #fff; + color: var(--bs-table-color); + border-color: var(--bs-table-border-color); +} + +.table-responsive { + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 767.98px) { + .table-responsive-md { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 991.98px) { + .table-responsive-lg { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 1199.98px) { + .table-responsive-xl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 1399.98px) { + .table-responsive-xxl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +.form-label { + margin-bottom: 0.5rem; +} + +.col-form-label { + padding-top: calc(0.375rem + var(--bs-border-width)); + padding-bottom: calc(0.375rem + var(--bs-border-width)); + margin-bottom: 0; + font-size: inherit; + line-height: 1.5; +} + +.col-form-label-lg { + padding-top: calc(0.5rem + var(--bs-border-width)); + padding-bottom: calc(0.5rem + var(--bs-border-width)); + font-size: 1.25rem; +} + +.col-form-label-sm { + padding-top: calc(0.25rem + var(--bs-border-width)); + padding-bottom: calc(0.25rem + var(--bs-border-width)); + font-size: 0.875rem; +} + +.form-text { + margin-top: 0.25rem; + font-size: 0.875em; + color: var(--bs-secondary-color); +} + +.form-control { + display: block; + width: 100%; + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: var(--bs-body-color); + background-color: var(--bs-body-bg); + background-clip: padding-box; + border: var(--bs-border-width) solid var(--bs-border-color); + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: var(--bs-border-radius); + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control { + transition: none; + } +} +.form-control[type=file] { + overflow: hidden; +} +.form-control[type=file]:not(:disabled):not([readonly]) { + cursor: pointer; +} +.form-control:focus { + color: var(--bs-body-color); + background-color: var(--bs-body-bg); + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-control::-webkit-date-and-time-value { + min-width: 85px; + height: 1.5em; + margin: 0; +} +.form-control::-webkit-datetime-edit { + display: block; + padding: 0; +} +.form-control::-moz-placeholder { + color: var(--bs-secondary-color); + opacity: 1; +} +.form-control::placeholder { + color: var(--bs-secondary-color); + opacity: 1; +} +.form-control:disabled { + background-color: var(--bs-secondary-bg); + opacity: 1; +} +.form-control::-webkit-file-upload-button { + padding: 0.375rem 0.75rem; + margin: -0.375rem -0.75rem; + -webkit-margin-end: 0.75rem; + margin-inline-end: 0.75rem; + color: var(--bs-body-color); + background-color: var(--bs-tertiary-bg); + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: var(--bs-border-width); + border-radius: 0; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +.form-control::file-selector-button { + padding: 0.375rem 0.75rem; + margin: -0.375rem -0.75rem; + -webkit-margin-end: 0.75rem; + margin-inline-end: 0.75rem; + color: var(--bs-body-color); + background-color: var(--bs-tertiary-bg); + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: var(--bs-border-width); + border-radius: 0; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control::-webkit-file-upload-button { + -webkit-transition: none; + transition: none; + } + .form-control::file-selector-button { + transition: none; + } +} +.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { + background-color: var(--bs-secondary-bg); +} +.form-control:hover:not(:disabled):not([readonly])::file-selector-button { + background-color: var(--bs-secondary-bg); +} + +.form-control-plaintext { + display: block; + width: 100%; + padding: 0.375rem 0; + margin-bottom: 0; + line-height: 1.5; + color: var(--bs-body-color); + background-color: transparent; + border: solid transparent; + border-width: var(--bs-border-width) 0; +} +.form-control-plaintext:focus { + outline: 0; +} +.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { + padding-right: 0; + padding-left: 0; +} + +.form-control-sm { + min-height: calc(1.5em + 0.5rem + calc(var(--bs-border-width) * 2)); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: var(--bs-border-radius-sm); +} +.form-control-sm::-webkit-file-upload-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; +} +.form-control-sm::file-selector-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; +} + +.form-control-lg { + min-height: calc(1.5em + 1rem + calc(var(--bs-border-width) * 2)); + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: var(--bs-border-radius-lg); +} +.form-control-lg::-webkit-file-upload-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem; +} +.form-control-lg::file-selector-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem; +} + +textarea.form-control { + min-height: calc(1.5em + 0.75rem + calc(var(--bs-border-width) * 2)); +} +textarea.form-control-sm { + min-height: calc(1.5em + 0.5rem + calc(var(--bs-border-width) * 2)); +} +textarea.form-control-lg { + min-height: calc(1.5em + 1rem + calc(var(--bs-border-width) * 2)); +} + +.form-control-color { + width: 3rem; + height: calc(1.5em + 0.75rem + calc(var(--bs-border-width) * 2)); + padding: 0.375rem; +} +.form-control-color:not(:disabled):not([readonly]) { + cursor: pointer; +} +.form-control-color::-moz-color-swatch { + border: 0 !important; + border-radius: var(--bs-border-radius); +} +.form-control-color::-webkit-color-swatch { + border: 0 !important; + border-radius: var(--bs-border-radius); +} +.form-control-color.form-control-sm { + height: calc(1.5em + 0.5rem + calc(var(--bs-border-width) * 2)); +} +.form-control-color.form-control-lg { + height: calc(1.5em + 1rem + calc(var(--bs-border-width) * 2)); +} + +.form-select { + --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); + display: block; + width: 100%; + padding: 0.375rem 2.25rem 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: var(--bs-body-color); + background-color: var(--bs-body-bg); + background-image: var(--bs-form-select-bg-img), var(--bs-form-select-bg-icon, none); + background-repeat: no-repeat; + background-position: right 0.75rem center; + background-size: 16px 12px; + border: var(--bs-border-width) solid var(--bs-border-color); + border-radius: var(--bs-border-radius); + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-select { + transition: none; + } +} +.form-select:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-select[multiple], .form-select[size]:not([size="1"]) { + padding-right: 0.75rem; + background-image: none; +} +.form-select:disabled { + background-color: var(--bs-secondary-bg); +} +.form-select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 var(--bs-body-color); +} + +.form-select-sm { + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-left: 0.5rem; + font-size: 0.875rem; + border-radius: var(--bs-border-radius-sm); +} + +.form-select-lg { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + font-size: 1.25rem; + border-radius: var(--bs-border-radius-lg); +} + +[data-bs-theme=dark] .form-select { + --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23adb5bd' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); +} + +.form-check { + display: block; + min-height: 1.5rem; + padding-left: 1.5em; + margin-bottom: 0.125rem; +} +.form-check .form-check-input { + float: left; + margin-left: -1.5em; +} + +.form-check-reverse { + padding-right: 1.5em; + padding-left: 0; + text-align: right; +} +.form-check-reverse .form-check-input { + float: right; + margin-right: -1.5em; + margin-left: 0; +} + +.form-check-input { + --bs-form-check-bg: var(--bs-body-bg); + width: 1em; + height: 1em; + margin-top: 0.25em; + vertical-align: top; + background-color: var(--bs-form-check-bg); + background-image: var(--bs-form-check-bg-image); + background-repeat: no-repeat; + background-position: center; + background-size: contain; + border: var(--bs-border-width) solid var(--bs-border-color); + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-print-color-adjust: exact; + color-adjust: exact; + print-color-adjust: exact; +} +.form-check-input[type=checkbox] { + border-radius: 0.25em; +} +.form-check-input[type=radio] { + border-radius: 50%; +} +.form-check-input:active { + filter: brightness(90%); +} +.form-check-input:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-check-input:checked { + background-color: #0d6efd; + border-color: #0d6efd; +} +.form-check-input:checked[type=checkbox] { + --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e"); +} +.form-check-input:checked[type=radio] { + --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); +} +.form-check-input[type=checkbox]:indeterminate { + background-color: #0d6efd; + border-color: #0d6efd; + --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); +} +.form-check-input:disabled { + pointer-events: none; + filter: none; + opacity: 0.5; +} +.form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { + cursor: default; + opacity: 0.5; +} + +.form-switch { + padding-left: 2.5em; +} +.form-switch .form-check-input { + --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); + width: 2em; + margin-left: -2.5em; + background-image: var(--bs-form-switch-bg); + background-position: left center; + border-radius: 2em; + transition: background-position 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-switch .form-check-input { + transition: none; + } +} +.form-switch .form-check-input:focus { + --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); +} +.form-switch .form-check-input:checked { + background-position: right center; + --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); +} +.form-switch.form-check-reverse { + padding-right: 2.5em; + padding-left: 0; +} +.form-switch.form-check-reverse .form-check-input { + margin-right: -2.5em; + margin-left: 0; +} + +.form-check-inline { + display: inline-block; + margin-right: 1rem; +} + +.btn-check { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.btn-check[disabled] + .btn, .btn-check:disabled + .btn { + pointer-events: none; + filter: none; + opacity: 0.65; +} + +[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus) { + --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e"); +} + +.form-range { + width: 100%; + height: 1.5rem; + padding: 0; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.form-range:focus { + outline: 0; +} +.form-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-range::-moz-focus-outer { + border: 0; +} +.form-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -webkit-appearance: none; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-range::-webkit-slider-thumb { + -webkit-transition: none; + transition: none; + } +} +.form-range::-webkit-slider-thumb:active { + background-color: #b6d4fe; +} +.form-range::-webkit-slider-runnable-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: var(--bs-tertiary-bg); + border-color: transparent; + border-radius: 1rem; +} +.form-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -moz-appearance: none; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-range::-moz-range-thumb { + -moz-transition: none; + transition: none; + } +} +.form-range::-moz-range-thumb:active { + background-color: #b6d4fe; +} +.form-range::-moz-range-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: var(--bs-tertiary-bg); + border-color: transparent; + border-radius: 1rem; +} +.form-range:disabled { + pointer-events: none; +} +.form-range:disabled::-webkit-slider-thumb { + background-color: var(--bs-secondary-color); +} +.form-range:disabled::-moz-range-thumb { + background-color: var(--bs-secondary-color); +} + +.form-floating { + position: relative; +} +.form-floating > .form-control, +.form-floating > .form-control-plaintext, +.form-floating > .form-select { + height: calc(3.5rem + calc(var(--bs-border-width) * 2)); + line-height: 1.25; +} +.form-floating > label { + position: absolute; + top: 0; + left: 0; + z-index: 2; + height: 100%; + padding: 1rem 0.75rem; + overflow: hidden; + text-align: start; + text-overflow: ellipsis; + white-space: nowrap; + pointer-events: none; + border: var(--bs-border-width) solid transparent; + transform-origin: 0 0; + transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-floating > label { + transition: none; + } +} +.form-floating > .form-control, +.form-floating > .form-control-plaintext { + padding: 1rem 0.75rem; +} +.form-floating > .form-control::-moz-placeholder, .form-floating > .form-control-plaintext::-moz-placeholder { + color: transparent; +} +.form-floating > .form-control::placeholder, +.form-floating > .form-control-plaintext::placeholder { + color: transparent; +} +.form-floating > .form-control:not(:-moz-placeholder-shown), .form-floating > .form-control-plaintext:not(:-moz-placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown), +.form-floating > .form-control-plaintext:focus, +.form-floating > .form-control-plaintext:not(:placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:-webkit-autofill, +.form-floating > .form-control-plaintext:-webkit-autofill { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-select { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { + color: rgba(var(--bs-body-color-rgb), 0.65); + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.form-floating > .form-control:focus ~ label, +.form-floating > .form-control:not(:placeholder-shown) ~ label, +.form-floating > .form-control-plaintext ~ label, +.form-floating > .form-select ~ label { + color: rgba(var(--bs-body-color-rgb), 0.65); + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.form-floating > .form-control:not(:-moz-placeholder-shown) ~ label::after { + position: absolute; + inset: 1rem 0.375rem; + z-index: -1; + height: 1.5em; + content: ""; + background-color: var(--bs-body-bg); + border-radius: var(--bs-border-radius); +} +.form-floating > .form-control:focus ~ label::after, +.form-floating > .form-control:not(:placeholder-shown) ~ label::after, +.form-floating > .form-control-plaintext ~ label::after, +.form-floating > .form-select ~ label::after { + position: absolute; + inset: 1rem 0.375rem; + z-index: -1; + height: 1.5em; + content: ""; + background-color: var(--bs-body-bg); + border-radius: var(--bs-border-radius); +} +.form-floating > .form-control:-webkit-autofill ~ label { + color: rgba(var(--bs-body-color-rgb), 0.65); + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.form-floating > .form-control-plaintext ~ label { + border-width: var(--bs-border-width) 0; +} +.form-floating > :disabled ~ label { + color: #6c757d; +} +.form-floating > :disabled ~ label::after { + background-color: var(--bs-secondary-bg); +} + +.input-group { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100%; +} +.input-group > .form-control, +.input-group > .form-select, +.input-group > .form-floating { + position: relative; + flex: 1 1 auto; + width: 1%; + min-width: 0; +} +.input-group > .form-control:focus, +.input-group > .form-select:focus, +.input-group > .form-floating:focus-within { + z-index: 5; +} +.input-group .btn { + position: relative; + z-index: 2; +} +.input-group .btn:focus { + z-index: 5; +} + +.input-group-text { + display: flex; + align-items: center; + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: var(--bs-body-color); + text-align: center; + white-space: nowrap; + background-color: var(--bs-tertiary-bg); + border: var(--bs-border-width) solid var(--bs-border-color); + border-radius: var(--bs-border-radius); +} + +.input-group-lg > .form-control, +.input-group-lg > .form-select, +.input-group-lg > .input-group-text, +.input-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: var(--bs-border-radius-lg); +} + +.input-group-sm > .form-control, +.input-group-sm > .form-select, +.input-group-sm > .input-group-text, +.input-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: var(--bs-border-radius-sm); +} + +.input-group-lg > .form-select, +.input-group-sm > .form-select { + padding-right: 3rem; +} + +.input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), +.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n+3), +.input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-control, +.input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-select { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group.has-validation > :nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), +.input-group.has-validation > .dropdown-toggle:nth-last-child(n+4), +.input-group.has-validation > .form-floating:nth-last-child(n+3) > .form-control, +.input-group.has-validation > .form-floating:nth-last-child(n+3) > .form-select { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { + margin-left: calc(var(--bs-border-width) * -1); + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group > .form-floating:not(:first-child) > .form-control, +.input-group > .form-floating:not(:first-child) > .form-select { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: var(--bs-form-valid-color); +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: var(--bs-success); + border-radius: var(--bs-border-radius); +} + +.was-validated :valid ~ .valid-feedback, +.was-validated :valid ~ .valid-tooltip, +.is-valid ~ .valid-feedback, +.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-control:valid, .form-control.is-valid { + border-color: var(--bs-form-valid-border-color); + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.1875rem) center; + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} +.was-validated .form-control:valid:focus, .form-control.is-valid:focus { + border-color: var(--bs-form-valid-border-color); + box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); +} + +.was-validated textarea.form-control:valid, textarea.form-control.is-valid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .form-select:valid, .form-select.is-valid { + border-color: var(--bs-form-valid-border-color); +} +.was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"] { + --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + padding-right: 4.125rem; + background-position: right 0.75rem center, center right 2.25rem; + background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} +.was-validated .form-select:valid:focus, .form-select.is-valid:focus { + border-color: var(--bs-form-valid-border-color); + box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); +} + +.was-validated .form-control-color:valid, .form-control-color.is-valid { + width: calc(3rem + calc(1.5em + 0.75rem)); +} + +.was-validated .form-check-input:valid, .form-check-input.is-valid { + border-color: var(--bs-form-valid-border-color); +} +.was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked { + background-color: var(--bs-form-valid-color); +} +.was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus { + box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); +} +.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { + color: var(--bs-form-valid-color); +} + +.form-check-inline .form-check-input ~ .valid-feedback { + margin-left: 0.5em; +} + +.was-validated .input-group > .form-control:not(:focus):valid, .input-group > .form-control:not(:focus).is-valid, +.was-validated .input-group > .form-select:not(:focus):valid, +.input-group > .form-select:not(:focus).is-valid, +.was-validated .input-group > .form-floating:not(:focus-within):valid, +.input-group > .form-floating:not(:focus-within).is-valid { + z-index: 3; +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: var(--bs-form-invalid-color); +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: var(--bs-danger); + border-radius: var(--bs-border-radius); +} + +.was-validated :invalid ~ .invalid-feedback, +.was-validated :invalid ~ .invalid-tooltip, +.is-invalid ~ .invalid-feedback, +.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-control:invalid, .form-control.is-invalid { + border-color: var(--bs-form-invalid-border-color); + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.1875rem) center; + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} +.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { + border-color: var(--bs-form-invalid-border-color); + box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); +} + +.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .form-select:invalid, .form-select.is-invalid { + border-color: var(--bs-form-invalid-border-color); +} +.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { + --bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + padding-right: 4.125rem; + background-position: right 0.75rem center, center right 2.25rem; + background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} +.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { + border-color: var(--bs-form-invalid-border-color); + box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); +} + +.was-validated .form-control-color:invalid, .form-control-color.is-invalid { + width: calc(3rem + calc(1.5em + 0.75rem)); +} + +.was-validated .form-check-input:invalid, .form-check-input.is-invalid { + border-color: var(--bs-form-invalid-border-color); +} +.was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked { + background-color: var(--bs-form-invalid-color); +} +.was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus { + box-shadow: 0 0 0 0.25rem rgba(var(--bs-danger-rgb), 0.25); +} +.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { + color: var(--bs-form-invalid-color); +} + +.form-check-inline .form-check-input ~ .invalid-feedback { + margin-left: 0.5em; +} + +.was-validated .input-group > .form-control:not(:focus):invalid, .input-group > .form-control:not(:focus).is-invalid, +.was-validated .input-group > .form-select:not(:focus):invalid, +.input-group > .form-select:not(:focus).is-invalid, +.was-validated .input-group > .form-floating:not(:focus-within):invalid, +.input-group > .form-floating:not(:focus-within).is-invalid { + z-index: 4; +} + +.btn { + --bs-btn-padding-x: 0.75rem; + --bs-btn-padding-y: 0.375rem; + --bs-btn-font-family: ; + --bs-btn-font-size: 1rem; + --bs-btn-font-weight: 400; + --bs-btn-line-height: 1.5; + --bs-btn-color: var(--bs-body-color); + --bs-btn-bg: transparent; + --bs-btn-border-width: var(--bs-border-width); + --bs-btn-border-color: transparent; + --bs-btn-border-radius: var(--bs-border-radius); + --bs-btn-hover-border-color: transparent; + --bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); + --bs-btn-disabled-opacity: 0.65; + --bs-btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5); + display: inline-block; + padding: var(--bs-btn-padding-y) var(--bs-btn-padding-x); + font-family: var(--bs-btn-font-family); + font-size: var(--bs-btn-font-size); + font-weight: var(--bs-btn-font-weight); + line-height: var(--bs-btn-line-height); + color: var(--bs-btn-color); + text-align: center; + text-decoration: none; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + border: var(--bs-btn-border-width) solid var(--bs-btn-border-color); + border-radius: var(--bs-btn-border-radius); + background-color: var(--bs-btn-bg); + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .btn { + transition: none; + } +} +.btn:hover { + color: var(--bs-btn-hover-color); + background-color: var(--bs-btn-hover-bg); + border-color: var(--bs-btn-hover-border-color); +} +.btn-check + .btn:hover { + color: var(--bs-btn-color); + background-color: var(--bs-btn-bg); + border-color: var(--bs-btn-border-color); +} +.btn:focus-visible { + color: var(--bs-btn-hover-color); + background-color: var(--bs-btn-hover-bg); + border-color: var(--bs-btn-hover-border-color); + outline: 0; + box-shadow: var(--bs-btn-focus-box-shadow); +} +.btn-check:focus-visible + .btn { + border-color: var(--bs-btn-hover-border-color); + outline: 0; + box-shadow: var(--bs-btn-focus-box-shadow); +} +.btn-check:checked + .btn, :not(.btn-check) + .btn:active, .btn:first-child:active, .btn.active, .btn.show { + color: var(--bs-btn-active-color); + background-color: var(--bs-btn-active-bg); + border-color: var(--bs-btn-active-border-color); +} +.btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { + box-shadow: var(--bs-btn-focus-box-shadow); +} +.btn:disabled, .btn.disabled, fieldset:disabled .btn { + color: var(--bs-btn-disabled-color); + pointer-events: none; + background-color: var(--bs-btn-disabled-bg); + border-color: var(--bs-btn-disabled-border-color); + opacity: var(--bs-btn-disabled-opacity); +} + +.btn-primary { + --bs-btn-color: #fff; + --bs-btn-bg: #0d6efd; + --bs-btn-border-color: #0d6efd; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #0b5ed7; + --bs-btn-hover-border-color: #0a58ca; + --bs-btn-focus-shadow-rgb: 49, 132, 253; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #0a58ca; + --bs-btn-active-border-color: #0a53be; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #fff; + --bs-btn-disabled-bg: #0d6efd; + --bs-btn-disabled-border-color: #0d6efd; +} + +.btn-secondary { + --bs-btn-color: #fff; + --bs-btn-bg: #6c757d; + --bs-btn-border-color: #6c757d; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #5c636a; + --bs-btn-hover-border-color: #565e64; + --bs-btn-focus-shadow-rgb: 130, 138, 145; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #565e64; + --bs-btn-active-border-color: #51585e; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #fff; + --bs-btn-disabled-bg: #6c757d; + --bs-btn-disabled-border-color: #6c757d; +} + +.btn-success { + --bs-btn-color: #fff; + --bs-btn-bg: #198754; + --bs-btn-border-color: #198754; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #157347; + --bs-btn-hover-border-color: #146c43; + --bs-btn-focus-shadow-rgb: 60, 153, 110; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #146c43; + --bs-btn-active-border-color: #13653f; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #fff; + --bs-btn-disabled-bg: #198754; + --bs-btn-disabled-border-color: #198754; +} + +.btn-info { + --bs-btn-color: #000; + --bs-btn-bg: #0dcaf0; + --bs-btn-border-color: #0dcaf0; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #31d2f2; + --bs-btn-hover-border-color: #25cff2; + --bs-btn-focus-shadow-rgb: 11, 172, 204; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #3dd5f3; + --bs-btn-active-border-color: #25cff2; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #000; + --bs-btn-disabled-bg: #0dcaf0; + --bs-btn-disabled-border-color: #0dcaf0; +} + +.btn-warning { + --bs-btn-color: #000; + --bs-btn-bg: #ffc107; + --bs-btn-border-color: #ffc107; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #ffca2c; + --bs-btn-hover-border-color: #ffc720; + --bs-btn-focus-shadow-rgb: 217, 164, 6; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #ffcd39; + --bs-btn-active-border-color: #ffc720; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #000; + --bs-btn-disabled-bg: #ffc107; + --bs-btn-disabled-border-color: #ffc107; +} + +.btn-danger { + --bs-btn-color: #fff; + --bs-btn-bg: #dc3545; + --bs-btn-border-color: #dc3545; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #bb2d3b; + --bs-btn-hover-border-color: #b02a37; + --bs-btn-focus-shadow-rgb: 225, 83, 97; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #b02a37; + --bs-btn-active-border-color: #a52834; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #fff; + --bs-btn-disabled-bg: #dc3545; + --bs-btn-disabled-border-color: #dc3545; +} + +.btn-light { + --bs-btn-color: #000; + --bs-btn-bg: #f8f9fa; + --bs-btn-border-color: #f8f9fa; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #d3d4d5; + --bs-btn-hover-border-color: #c6c7c8; + --bs-btn-focus-shadow-rgb: 211, 212, 213; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #c6c7c8; + --bs-btn-active-border-color: #babbbc; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #000; + --bs-btn-disabled-bg: #f8f9fa; + --bs-btn-disabled-border-color: #f8f9fa; +} + +.btn-dark { + --bs-btn-color: #fff; + --bs-btn-bg: #212529; + --bs-btn-border-color: #212529; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #424649; + --bs-btn-hover-border-color: #373b3e; + --bs-btn-focus-shadow-rgb: 66, 70, 73; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #4d5154; + --bs-btn-active-border-color: #373b3e; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #fff; + --bs-btn-disabled-bg: #212529; + --bs-btn-disabled-border-color: #212529; +} + +.btn-outline-primary { + --bs-btn-color: #0d6efd; + --bs-btn-border-color: #0d6efd; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #0d6efd; + --bs-btn-hover-border-color: #0d6efd; + --bs-btn-focus-shadow-rgb: 13, 110, 253; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #0d6efd; + --bs-btn-active-border-color: #0d6efd; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #0d6efd; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #0d6efd; + --bs-gradient: none; +} + +.btn-outline-secondary { + --bs-btn-color: #6c757d; + --bs-btn-border-color: #6c757d; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #6c757d; + --bs-btn-hover-border-color: #6c757d; + --bs-btn-focus-shadow-rgb: 108, 117, 125; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #6c757d; + --bs-btn-active-border-color: #6c757d; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #6c757d; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #6c757d; + --bs-gradient: none; +} + +.btn-outline-success { + --bs-btn-color: #198754; + --bs-btn-border-color: #198754; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #198754; + --bs-btn-hover-border-color: #198754; + --bs-btn-focus-shadow-rgb: 25, 135, 84; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #198754; + --bs-btn-active-border-color: #198754; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #198754; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #198754; + --bs-gradient: none; +} + +.btn-outline-info { + --bs-btn-color: #0dcaf0; + --bs-btn-border-color: #0dcaf0; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #0dcaf0; + --bs-btn-hover-border-color: #0dcaf0; + --bs-btn-focus-shadow-rgb: 13, 202, 240; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #0dcaf0; + --bs-btn-active-border-color: #0dcaf0; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #0dcaf0; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #0dcaf0; + --bs-gradient: none; +} + +.btn-outline-warning { + --bs-btn-color: #ffc107; + --bs-btn-border-color: #ffc107; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #ffc107; + --bs-btn-hover-border-color: #ffc107; + --bs-btn-focus-shadow-rgb: 255, 193, 7; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #ffc107; + --bs-btn-active-border-color: #ffc107; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #ffc107; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #ffc107; + --bs-gradient: none; +} + +.btn-outline-danger { + --bs-btn-color: #dc3545; + --bs-btn-border-color: #dc3545; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #dc3545; + --bs-btn-hover-border-color: #dc3545; + --bs-btn-focus-shadow-rgb: 220, 53, 69; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #dc3545; + --bs-btn-active-border-color: #dc3545; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #dc3545; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #dc3545; + --bs-gradient: none; +} + +.btn-outline-light { + --bs-btn-color: #f8f9fa; + --bs-btn-border-color: #f8f9fa; + --bs-btn-hover-color: #000; + --bs-btn-hover-bg: #f8f9fa; + --bs-btn-hover-border-color: #f8f9fa; + --bs-btn-focus-shadow-rgb: 248, 249, 250; + --bs-btn-active-color: #000; + --bs-btn-active-bg: #f8f9fa; + --bs-btn-active-border-color: #f8f9fa; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #f8f9fa; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #f8f9fa; + --bs-gradient: none; +} + +.btn-outline-dark { + --bs-btn-color: #212529; + --bs-btn-border-color: #212529; + --bs-btn-hover-color: #fff; + --bs-btn-hover-bg: #212529; + --bs-btn-hover-border-color: #212529; + --bs-btn-focus-shadow-rgb: 33, 37, 41; + --bs-btn-active-color: #fff; + --bs-btn-active-bg: #212529; + --bs-btn-active-border-color: #212529; + --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + --bs-btn-disabled-color: #212529; + --bs-btn-disabled-bg: transparent; + --bs-btn-disabled-border-color: #212529; + --bs-gradient: none; +} + +.btn-link { + --bs-btn-font-weight: 400; + --bs-btn-color: var(--bs-link-color); + --bs-btn-bg: transparent; + --bs-btn-border-color: transparent; + --bs-btn-hover-color: var(--bs-link-hover-color); + --bs-btn-hover-border-color: transparent; + --bs-btn-active-color: var(--bs-link-hover-color); + --bs-btn-active-border-color: transparent; + --bs-btn-disabled-color: #6c757d; + --bs-btn-disabled-border-color: transparent; + --bs-btn-box-shadow: 0 0 0 #000; + --bs-btn-focus-shadow-rgb: 49, 132, 253; + text-decoration: underline; +} +.btn-link:focus-visible { + color: var(--bs-btn-color); +} +.btn-link:hover { + color: var(--bs-btn-hover-color); +} + +.btn-lg, .btn-group-lg > .btn { + --bs-btn-padding-y: 0.5rem; + --bs-btn-padding-x: 1rem; + --bs-btn-font-size: 1.25rem; + --bs-btn-border-radius: var(--bs-border-radius-lg); +} + +.btn-sm, .btn-group-sm > .btn { + --bs-btn-padding-y: 0.25rem; + --bs-btn-padding-x: 0.5rem; + --bs-btn-font-size: 0.875rem; + --bs-btn-border-radius: var(--bs-border-radius-sm); +} + +.fade { + transition: opacity 0.15s linear; +} +@media (prefers-reduced-motion: reduce) { + .fade { + transition: none; + } +} +.fade:not(.show) { + opacity: 0; +} + +.collapse:not(.show) { + display: none; +} + +.collapsing { + height: 0; + overflow: hidden; + transition: height 0.35s ease; +} +@media (prefers-reduced-motion: reduce) { + .collapsing { + transition: none; + } +} +.collapsing.collapse-horizontal { + width: 0; + height: auto; + transition: width 0.35s ease; +} +@media (prefers-reduced-motion: reduce) { + .collapsing.collapse-horizontal { + transition: none; + } +} + +.dropup, +.dropend, +.dropdown, +.dropstart, +.dropup-center, +.dropdown-center { + position: relative; +} + +.dropdown-toggle { + white-space: nowrap; +} +.dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} +.dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropdown-menu { + --bs-dropdown-zindex: 1000; + --bs-dropdown-min-width: 10rem; + --bs-dropdown-padding-x: 0; + --bs-dropdown-padding-y: 0.5rem; + --bs-dropdown-spacer: 0.125rem; + --bs-dropdown-font-size: 1rem; + --bs-dropdown-color: var(--bs-body-color); + --bs-dropdown-bg: var(--bs-body-bg); + --bs-dropdown-border-color: var(--bs-border-color-translucent); + --bs-dropdown-border-radius: var(--bs-border-radius); + --bs-dropdown-border-width: var(--bs-border-width); + --bs-dropdown-inner-border-radius: calc(var(--bs-border-radius) - var(--bs-border-width)); + --bs-dropdown-divider-bg: var(--bs-border-color-translucent); + --bs-dropdown-divider-margin-y: 0.5rem; + --bs-dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --bs-dropdown-link-color: var(--bs-body-color); + --bs-dropdown-link-hover-color: var(--bs-body-color); + --bs-dropdown-link-hover-bg: var(--bs-tertiary-bg); + --bs-dropdown-link-active-color: #fff; + --bs-dropdown-link-active-bg: #0d6efd; + --bs-dropdown-link-disabled-color: var(--bs-tertiary-color); + --bs-dropdown-item-padding-x: 1rem; + --bs-dropdown-item-padding-y: 0.25rem; + --bs-dropdown-header-color: #6c757d; + --bs-dropdown-header-padding-x: 1rem; + --bs-dropdown-header-padding-y: 0.5rem; + position: absolute; + z-index: var(--bs-dropdown-zindex); + display: none; + min-width: var(--bs-dropdown-min-width); + padding: var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x); + margin: 0; + font-size: var(--bs-dropdown-font-size); + color: var(--bs-dropdown-color); + text-align: left; + list-style: none; + background-color: var(--bs-dropdown-bg); + background-clip: padding-box; + border: var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color); + border-radius: var(--bs-dropdown-border-radius); +} +.dropdown-menu[data-bs-popper] { + top: 100%; + left: 0; + margin-top: var(--bs-dropdown-spacer); +} + +.dropdown-menu-start { + --bs-position: start; +} +.dropdown-menu-start[data-bs-popper] { + right: auto; + left: 0; +} + +.dropdown-menu-end { + --bs-position: end; +} +.dropdown-menu-end[data-bs-popper] { + right: 0; + left: auto; +} + +@media (min-width: 576px) { + .dropdown-menu-sm-start { + --bs-position: start; + } + .dropdown-menu-sm-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-sm-end { + --bs-position: end; + } + .dropdown-menu-sm-end[data-bs-popper] { + right: 0; + left: auto; + } +} +@media (min-width: 768px) { + .dropdown-menu-md-start { + --bs-position: start; + } + .dropdown-menu-md-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-md-end { + --bs-position: end; + } + .dropdown-menu-md-end[data-bs-popper] { + right: 0; + left: auto; + } +} +@media (min-width: 992px) { + .dropdown-menu-lg-start { + --bs-position: start; + } + .dropdown-menu-lg-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-lg-end { + --bs-position: end; + } + .dropdown-menu-lg-end[data-bs-popper] { + right: 0; + left: auto; + } +} +@media (min-width: 1200px) { + .dropdown-menu-xl-start { + --bs-position: start; + } + .dropdown-menu-xl-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-xl-end { + --bs-position: end; + } + .dropdown-menu-xl-end[data-bs-popper] { + right: 0; + left: auto; + } +} +@media (min-width: 1400px) { + .dropdown-menu-xxl-start { + --bs-position: start; + } + .dropdown-menu-xxl-start[data-bs-popper] { + right: auto; + left: 0; + } + .dropdown-menu-xxl-end { + --bs-position: end; + } + .dropdown-menu-xxl-end[data-bs-popper] { + right: 0; + left: auto; + } +} +.dropup .dropdown-menu[data-bs-popper] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: var(--bs-dropdown-spacer); +} +.dropup .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.3em solid transparent; +} +.dropup .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropend .dropdown-menu[data-bs-popper] { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: var(--bs-dropdown-spacer); +} +.dropend .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0; + border-bottom: 0.3em solid transparent; + border-left: 0.3em solid; +} +.dropend .dropdown-toggle:empty::after { + margin-left: 0; +} +.dropend .dropdown-toggle::after { + vertical-align: 0; +} + +.dropstart .dropdown-menu[data-bs-popper] { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: var(--bs-dropdown-spacer); +} +.dropstart .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; +} +.dropstart .dropdown-toggle::after { + display: none; +} +.dropstart .dropdown-toggle::before { + display: inline-block; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} +.dropstart .dropdown-toggle:empty::after { + margin-left: 0; +} +.dropstart .dropdown-toggle::before { + vertical-align: 0; +} + +.dropdown-divider { + height: 0; + margin: var(--bs-dropdown-divider-margin-y) 0; + overflow: hidden; + border-top: 1px solid var(--bs-dropdown-divider-bg); + opacity: 1; +} + +.dropdown-item { + display: block; + width: 100%; + padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); + clear: both; + font-weight: 400; + color: var(--bs-dropdown-link-color); + text-align: inherit; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border: 0; + border-radius: var(--bs-dropdown-item-border-radius, 0); +} +.dropdown-item:hover, .dropdown-item:focus { + color: var(--bs-dropdown-link-hover-color); + background-color: var(--bs-dropdown-link-hover-bg); +} +.dropdown-item.active, .dropdown-item:active { + color: var(--bs-dropdown-link-active-color); + text-decoration: none; + background-color: var(--bs-dropdown-link-active-bg); +} +.dropdown-item.disabled, .dropdown-item:disabled { + color: var(--bs-dropdown-link-disabled-color); + pointer-events: none; + background-color: transparent; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-header { + display: block; + padding: var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x); + margin-bottom: 0; + font-size: 0.875rem; + color: var(--bs-dropdown-header-color); + white-space: nowrap; +} + +.dropdown-item-text { + display: block; + padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); + color: var(--bs-dropdown-link-color); +} + +.dropdown-menu-dark { + --bs-dropdown-color: #dee2e6; + --bs-dropdown-bg: #343a40; + --bs-dropdown-border-color: var(--bs-border-color-translucent); + --bs-dropdown-box-shadow: ; + --bs-dropdown-link-color: #dee2e6; + --bs-dropdown-link-hover-color: #fff; + --bs-dropdown-divider-bg: var(--bs-border-color-translucent); + --bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.15); + --bs-dropdown-link-active-color: #fff; + --bs-dropdown-link-active-bg: #0d6efd; + --bs-dropdown-link-disabled-color: #adb5bd; + --bs-dropdown-header-color: #adb5bd; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + flex: 1 1 auto; +} +.btn-group > .btn-check:checked + .btn, +.btn-group > .btn-check:focus + .btn, +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn-check:checked + .btn, +.btn-group-vertical > .btn-check:focus + .btn, +.btn-group-vertical > .btn:hover, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn.active { + z-index: 1; +} + +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; +} +.btn-toolbar .input-group { + width: auto; +} + +.btn-group { + border-radius: var(--bs-border-radius); +} +.btn-group > :not(.btn-check:first-child) + .btn, +.btn-group > .btn-group:not(:first-child) { + margin-left: calc(var(--bs-border-width) * -1); +} +.btn-group > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group > .btn.dropdown-toggle-split:first-child, +.btn-group > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:nth-child(n+3), +.btn-group > :not(.btn-check) + .btn, +.btn-group > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.dropdown-toggle-split { + padding-right: 0.5625rem; + padding-left: 0.5625rem; +} +.dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropend .dropdown-toggle-split::after { + margin-left: 0; +} +.dropstart .dropdown-toggle-split::before { + margin-right: 0; +} + +.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} + +.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + width: 100%; +} +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) { + margin-top: calc(var(--bs-border-width) * -1); +} +.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group-vertical > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn ~ .btn, +.btn-group-vertical > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav { + --bs-nav-link-padding-x: 1rem; + --bs-nav-link-padding-y: 0.5rem; + --bs-nav-link-font-weight: ; + --bs-nav-link-color: var(--bs-link-color); + --bs-nav-link-hover-color: var(--bs-link-hover-color); + --bs-nav-link-disabled-color: var(--bs-secondary-color); + display: flex; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav-link { + display: block; + padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x); + font-size: var(--bs-nav-link-font-size); + font-weight: var(--bs-nav-link-font-weight); + color: var(--bs-nav-link-color); + text-decoration: none; + background: none; + border: 0; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .nav-link { + transition: none; + } +} +.nav-link:hover, .nav-link:focus { + color: var(--bs-nav-link-hover-color); +} +.nav-link:focus-visible { + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.nav-link.disabled { + color: var(--bs-nav-link-disabled-color); + pointer-events: none; + cursor: default; +} + +.nav-tabs { + --bs-nav-tabs-border-width: var(--bs-border-width); + --bs-nav-tabs-border-color: var(--bs-border-color); + --bs-nav-tabs-border-radius: var(--bs-border-radius); + --bs-nav-tabs-link-hover-border-color: var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color); + --bs-nav-tabs-link-active-color: var(--bs-emphasis-color); + --bs-nav-tabs-link-active-bg: var(--bs-body-bg); + --bs-nav-tabs-link-active-border-color: var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg); + border-bottom: var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color); +} +.nav-tabs .nav-link { + margin-bottom: calc(-1 * var(--bs-nav-tabs-border-width)); + border: var(--bs-nav-tabs-border-width) solid transparent; + border-top-left-radius: var(--bs-nav-tabs-border-radius); + border-top-right-radius: var(--bs-nav-tabs-border-radius); +} +.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { + isolation: isolate; + border-color: var(--bs-nav-tabs-link-hover-border-color); +} +.nav-tabs .nav-link.disabled, .nav-tabs .nav-link:disabled { + color: var(--bs-nav-link-disabled-color); + background-color: transparent; + border-color: transparent; +} +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: var(--bs-nav-tabs-link-active-color); + background-color: var(--bs-nav-tabs-link-active-bg); + border-color: var(--bs-nav-tabs-link-active-border-color); +} +.nav-tabs .dropdown-menu { + margin-top: calc(-1 * var(--bs-nav-tabs-border-width)); + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav-pills { + --bs-nav-pills-border-radius: var(--bs-border-radius); + --bs-nav-pills-link-active-color: #fff; + --bs-nav-pills-link-active-bg: #0d6efd; +} +.nav-pills .nav-link { + border-radius: var(--bs-nav-pills-border-radius); +} +.nav-pills .nav-link:disabled { + color: var(--bs-nav-link-disabled-color); + background-color: transparent; + border-color: transparent; +} +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: var(--bs-nav-pills-link-active-color); + background-color: var(--bs-nav-pills-link-active-bg); +} + +.nav-underline { + --bs-nav-underline-gap: 1rem; + --bs-nav-underline-border-width: 0.125rem; + --bs-nav-underline-link-active-color: var(--bs-emphasis-color); + gap: var(--bs-nav-underline-gap); +} +.nav-underline .nav-link { + padding-right: 0; + padding-left: 0; + border-bottom: var(--bs-nav-underline-border-width) solid transparent; +} +.nav-underline .nav-link:hover, .nav-underline .nav-link:focus { + border-bottom-color: currentcolor; +} +.nav-underline .nav-link.active, +.nav-underline .show > .nav-link { + font-weight: 700; + color: var(--bs-nav-underline-link-active-color); + border-bottom-color: currentcolor; +} + +.nav-fill > .nav-link, +.nav-fill .nav-item { + flex: 1 1 auto; + text-align: center; +} + +.nav-justified > .nav-link, +.nav-justified .nav-item { + flex-basis: 0; + flex-grow: 1; + text-align: center; +} + +.nav-fill .nav-item .nav-link, +.nav-justified .nav-item .nav-link { + width: 100%; +} + +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} + +.navbar { + --bs-navbar-padding-x: 0; + --bs-navbar-padding-y: 0.5rem; + --bs-navbar-color: rgba(var(--bs-emphasis-color-rgb), 0.65); + --bs-navbar-hover-color: rgba(var(--bs-emphasis-color-rgb), 0.8); + --bs-navbar-disabled-color: rgba(var(--bs-emphasis-color-rgb), 0.3); + --bs-navbar-active-color: rgba(var(--bs-emphasis-color-rgb), 1); + --bs-navbar-brand-padding-y: 0.3125rem; + --bs-navbar-brand-margin-end: 1rem; + --bs-navbar-brand-font-size: 1.25rem; + --bs-navbar-brand-color: rgba(var(--bs-emphasis-color-rgb), 1); + --bs-navbar-brand-hover-color: rgba(var(--bs-emphasis-color-rgb), 1); + --bs-navbar-nav-link-padding-x: 0.5rem; + --bs-navbar-toggler-padding-y: 0.25rem; + --bs-navbar-toggler-padding-x: 0.75rem; + --bs-navbar-toggler-font-size: 1.25rem; + --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); + --bs-navbar-toggler-border-color: rgba(var(--bs-emphasis-color-rgb), 0.15); + --bs-navbar-toggler-border-radius: var(--bs-border-radius); + --bs-navbar-toggler-focus-width: 0.25rem; + --bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out; + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + padding: var(--bs-navbar-padding-y) var(--bs-navbar-padding-x); +} +.navbar > .container, +.navbar > .container-fluid, +.navbar > .container-sm, +.navbar > .container-md, +.navbar > .container-lg, +.navbar > .container-xl, +.navbar > .container-xxl { + display: flex; + flex-wrap: inherit; + align-items: center; + justify-content: space-between; +} +.navbar-brand { + padding-top: var(--bs-navbar-brand-padding-y); + padding-bottom: var(--bs-navbar-brand-padding-y); + margin-right: var(--bs-navbar-brand-margin-end); + font-size: var(--bs-navbar-brand-font-size); + color: var(--bs-navbar-brand-color); + text-decoration: none; + white-space: nowrap; +} +.navbar-brand:hover, .navbar-brand:focus { + color: var(--bs-navbar-brand-hover-color); +} + +.navbar-nav { + --bs-nav-link-padding-x: 0; + --bs-nav-link-padding-y: 0.5rem; + --bs-nav-link-font-weight: ; + --bs-nav-link-color: var(--bs-navbar-color); + --bs-nav-link-hover-color: var(--bs-navbar-hover-color); + --bs-nav-link-disabled-color: var(--bs-navbar-disabled-color); + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.navbar-nav .nav-link.active, .navbar-nav .nav-link.show { + color: var(--bs-navbar-active-color); +} +.navbar-nav .dropdown-menu { + position: static; +} + +.navbar-text { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + color: var(--bs-navbar-color); +} +.navbar-text a, +.navbar-text a:hover, +.navbar-text a:focus { + color: var(--bs-navbar-active-color); +} + +.navbar-collapse { + flex-basis: 100%; + flex-grow: 1; + align-items: center; +} + +.navbar-toggler { + padding: var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x); + font-size: var(--bs-navbar-toggler-font-size); + line-height: 1; + color: var(--bs-navbar-color); + background-color: transparent; + border: var(--bs-border-width) solid var(--bs-navbar-toggler-border-color); + border-radius: var(--bs-navbar-toggler-border-radius); + transition: var(--bs-navbar-toggler-transition); +} +@media (prefers-reduced-motion: reduce) { + .navbar-toggler { + transition: none; + } +} +.navbar-toggler:hover { + text-decoration: none; +} +.navbar-toggler:focus { + text-decoration: none; + outline: 0; + box-shadow: 0 0 0 var(--bs-navbar-toggler-focus-width); +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + background-image: var(--bs-navbar-toggler-icon-bg); + background-repeat: no-repeat; + background-position: center; + background-size: 100%; +} + +.navbar-nav-scroll { + max-height: var(--bs-scroll-height, 75vh); + overflow-y: auto; +} + +@media (min-width: 576px) { + .navbar-expand-sm { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-sm .navbar-nav { + flex-direction: row; + } + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-sm .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-sm .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-sm .navbar-toggler { + display: none; + } + .navbar-expand-sm .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-sm .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-sm .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} +@media (min-width: 768px) { + .navbar-expand-md { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-md .navbar-nav { + flex-direction: row; + } + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-md .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-md .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-md .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-md .navbar-toggler { + display: none; + } + .navbar-expand-md .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-md .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-md .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} +@media (min-width: 992px) { + .navbar-expand-lg { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-lg .navbar-nav { + flex-direction: row; + } + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-lg .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-lg .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-lg .navbar-toggler { + display: none; + } + .navbar-expand-lg .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-lg .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-lg .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} +@media (min-width: 1200px) { + .navbar-expand-xl { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-xl .navbar-nav { + flex-direction: row; + } + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-xl .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-xl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-xl .navbar-toggler { + display: none; + } + .navbar-expand-xl .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-xl .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-xl .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} +@media (min-width: 1400px) { + .navbar-expand-xxl { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-xxl .navbar-nav { + flex-direction: row; + } + .navbar-expand-xxl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xxl .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); + } + .navbar-expand-xxl .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-xxl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-xxl .navbar-toggler { + display: none; + } + .navbar-expand-xxl .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; + } + .navbar-expand-xxl .offcanvas .offcanvas-header { + display: none; + } + .navbar-expand-xxl .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + } +} +.navbar-expand { + flex-wrap: nowrap; + justify-content: flex-start; +} +.navbar-expand .navbar-nav { + flex-direction: row; +} +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute; +} +.navbar-expand .navbar-nav .nav-link { + padding-right: var(--bs-navbar-nav-link-padding-x); + padding-left: var(--bs-navbar-nav-link-padding-x); +} +.navbar-expand .navbar-nav-scroll { + overflow: visible; +} +.navbar-expand .navbar-collapse { + display: flex !important; + flex-basis: auto; +} +.navbar-expand .navbar-toggler { + display: none; +} +.navbar-expand .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto !important; + height: auto !important; + visibility: visible !important; + background-color: transparent !important; + border: 0 !important; + transform: none !important; + transition: none; +} +.navbar-expand .offcanvas .offcanvas-header { + display: none; +} +.navbar-expand .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; +} + +.navbar-dark { + --bs-navbar-color: rgba(255, 255, 255, 0.55); + --bs-navbar-hover-color: rgba(255, 255, 255, 0.75); + --bs-navbar-disabled-color: rgba(255, 255, 255, 0.25); + --bs-navbar-active-color: #fff; + --bs-navbar-brand-color: #fff; + --bs-navbar-brand-hover-color: #fff; + --bs-navbar-toggler-border-color: rgba(255, 255, 255, 0.1); + --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +[data-bs-theme=dark] .navbar-toggler-icon { + --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} + +.card { + --bs-card-spacer-y: 1rem; + --bs-card-spacer-x: 1rem; + --bs-card-title-spacer-y: 0.5rem; + --bs-card-title-color: ; + --bs-card-subtitle-color: ; + --bs-card-border-width: var(--bs-border-width); + --bs-card-border-color: var(--bs-border-color-translucent); + --bs-card-border-radius: var(--bs-border-radius); + --bs-card-box-shadow: ; + --bs-card-inner-border-radius: calc(var(--bs-border-radius) - (var(--bs-border-width))); + --bs-card-cap-padding-y: 0.5rem; + --bs-card-cap-padding-x: 1rem; + --bs-card-cap-bg: rgba(var(--bs-body-color-rgb), 0.03); + --bs-card-cap-color: ; + --bs-card-height: ; + --bs-card-color: ; + --bs-card-bg: var(--bs-body-bg); + --bs-card-img-overlay-padding: 1rem; + --bs-card-group-margin: 0.75rem; + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + height: var(--bs-card-height); + color: var(--bs-body-color); + word-wrap: break-word; + background-color: var(--bs-card-bg); + background-clip: border-box; + border: var(--bs-card-border-width) solid var(--bs-card-border-color); + border-radius: var(--bs-card-border-radius); +} +.card > hr { + margin-right: 0; + margin-left: 0; +} +.card > .list-group { + border-top: inherit; + border-bottom: inherit; +} +.card > .list-group:first-child { + border-top-width: 0; + border-top-left-radius: var(--bs-card-inner-border-radius); + border-top-right-radius: var(--bs-card-inner-border-radius); +} +.card > .list-group:last-child { + border-bottom-width: 0; + border-bottom-right-radius: var(--bs-card-inner-border-radius); + border-bottom-left-radius: var(--bs-card-inner-border-radius); +} +.card > .card-header + .list-group, +.card > .list-group + .card-footer { + border-top: 0; +} + +.card-body { + flex: 1 1 auto; + padding: var(--bs-card-spacer-y) var(--bs-card-spacer-x); + color: var(--bs-card-color); +} + +.card-title { + margin-bottom: var(--bs-card-title-spacer-y); + color: var(--bs-card-title-color); +} + +.card-subtitle { + margin-top: calc(-0.5 * var(--bs-card-title-spacer-y)); + margin-bottom: 0; + color: var(--bs-card-subtitle-color); +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link + .card-link { + margin-left: var(--bs-card-spacer-x); +} + +.card-header { + padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); + margin-bottom: 0; + color: var(--bs-card-cap-color); + background-color: var(--bs-card-cap-bg); + border-bottom: var(--bs-card-border-width) solid var(--bs-card-border-color); +} +.card-header:first-child { + border-radius: var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0; +} + +.card-footer { + padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); + color: var(--bs-card-cap-color); + background-color: var(--bs-card-cap-bg); + border-top: var(--bs-card-border-width) solid var(--bs-card-border-color); +} +.card-footer:last-child { + border-radius: 0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius); +} + +.card-header-tabs { + margin-right: calc(-0.5 * var(--bs-card-cap-padding-x)); + margin-bottom: calc(-1 * var(--bs-card-cap-padding-y)); + margin-left: calc(-0.5 * var(--bs-card-cap-padding-x)); + border-bottom: 0; +} +.card-header-tabs .nav-link.active { + background-color: var(--bs-card-bg); + border-bottom-color: var(--bs-card-bg); +} + +.card-header-pills { + margin-right: calc(-0.5 * var(--bs-card-cap-padding-x)); + margin-left: calc(-0.5 * var(--bs-card-cap-padding-x)); +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: var(--bs-card-img-overlay-padding); + border-radius: var(--bs-card-inner-border-radius); +} + +.card-img, +.card-img-top, +.card-img-bottom { + width: 100%; +} + +.card-img, +.card-img-top { + border-top-left-radius: var(--bs-card-inner-border-radius); + border-top-right-radius: var(--bs-card-inner-border-radius); +} + +.card-img, +.card-img-bottom { + border-bottom-right-radius: var(--bs-card-inner-border-radius); + border-bottom-left-radius: var(--bs-card-inner-border-radius); +} + +.card-group > .card { + margin-bottom: var(--bs-card-group-margin); +} +@media (min-width: 576px) { + .card-group { + display: flex; + flex-flow: row wrap; + } + .card-group > .card { + flex: 1 0 0%; + margin-bottom: 0; + } + .card-group > .card + .card { + margin-left: 0; + border-left: 0; + } + .card-group > .card:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-img-top, + .card-group > .card:not(:last-child) .card-header { + border-top-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-img-bottom, + .card-group > .card:not(:last-child) .card-footer { + border-bottom-right-radius: 0; + } + .card-group > .card:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-img-top, + .card-group > .card:not(:first-child) .card-header { + border-top-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-img-bottom, + .card-group > .card:not(:first-child) .card-footer { + border-bottom-left-radius: 0; + } +} + +.accordion { + --bs-accordion-color: var(--bs-body-color); + --bs-accordion-bg: var(--bs-body-bg); + --bs-accordion-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease; + --bs-accordion-border-color: var(--bs-border-color); + --bs-accordion-border-width: var(--bs-border-width); + --bs-accordion-border-radius: var(--bs-border-radius); + --bs-accordion-inner-border-radius: calc(var(--bs-border-radius) - (var(--bs-border-width))); + --bs-accordion-btn-padding-x: 1.25rem; + --bs-accordion-btn-padding-y: 1rem; + --bs-accordion-btn-color: var(--bs-body-color); + --bs-accordion-btn-bg: var(--bs-accordion-bg); + --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + --bs-accordion-btn-icon-width: 1.25rem; + --bs-accordion-btn-icon-transform: rotate(-180deg); + --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; + --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23052c65'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + --bs-accordion-btn-focus-border-color: #86b7fe; + --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + --bs-accordion-body-padding-x: 1.25rem; + --bs-accordion-body-padding-y: 1rem; + --bs-accordion-active-color: var(--bs-primary-text-emphasis); + --bs-accordion-active-bg: var(--bs-primary-bg-subtle); +} + +.accordion-button { + position: relative; + display: flex; + align-items: center; + width: 100%; + padding: var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x); + font-size: 1rem; + color: var(--bs-accordion-btn-color); + text-align: left; + background-color: var(--bs-accordion-btn-bg); + border: 0; + border-radius: 0; + overflow-anchor: none; + transition: var(--bs-accordion-transition); +} +@media (prefers-reduced-motion: reduce) { + .accordion-button { + transition: none; + } +} +.accordion-button:not(.collapsed) { + color: var(--bs-accordion-active-color); + background-color: var(--bs-accordion-active-bg); + box-shadow: inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color); +} +.accordion-button:not(.collapsed)::after { + background-image: var(--bs-accordion-btn-active-icon); + transform: var(--bs-accordion-btn-icon-transform); +} +.accordion-button::after { + flex-shrink: 0; + width: var(--bs-accordion-btn-icon-width); + height: var(--bs-accordion-btn-icon-width); + margin-left: auto; + content: ""; + background-image: var(--bs-accordion-btn-icon); + background-repeat: no-repeat; + background-size: var(--bs-accordion-btn-icon-width); + transition: var(--bs-accordion-btn-icon-transition); +} +@media (prefers-reduced-motion: reduce) { + .accordion-button::after { + transition: none; + } +} +.accordion-button:hover { + z-index: 2; +} +.accordion-button:focus { + z-index: 3; + border-color: var(--bs-accordion-btn-focus-border-color); + outline: 0; + box-shadow: var(--bs-accordion-btn-focus-box-shadow); +} + +.accordion-header { + margin-bottom: 0; +} + +.accordion-item { + color: var(--bs-accordion-color); + background-color: var(--bs-accordion-bg); + border: var(--bs-accordion-border-width) solid var(--bs-accordion-border-color); +} +.accordion-item:first-of-type { + border-top-left-radius: var(--bs-accordion-border-radius); + border-top-right-radius: var(--bs-accordion-border-radius); +} +.accordion-item:first-of-type .accordion-button { + border-top-left-radius: var(--bs-accordion-inner-border-radius); + border-top-right-radius: var(--bs-accordion-inner-border-radius); +} +.accordion-item:not(:first-of-type) { + border-top: 0; +} +.accordion-item:last-of-type { + border-bottom-right-radius: var(--bs-accordion-border-radius); + border-bottom-left-radius: var(--bs-accordion-border-radius); +} +.accordion-item:last-of-type .accordion-button.collapsed { + border-bottom-right-radius: var(--bs-accordion-inner-border-radius); + border-bottom-left-radius: var(--bs-accordion-inner-border-radius); +} +.accordion-item:last-of-type .accordion-collapse { + border-bottom-right-radius: var(--bs-accordion-border-radius); + border-bottom-left-radius: var(--bs-accordion-border-radius); +} + +.accordion-body { + padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); +} + +.accordion-flush .accordion-collapse { + border-width: 0; +} +.accordion-flush .accordion-item { + border-right: 0; + border-left: 0; + border-radius: 0; +} +.accordion-flush .accordion-item:first-child { + border-top: 0; +} +.accordion-flush .accordion-item:last-child { + border-bottom: 0; +} +.accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed { + border-radius: 0; +} + +[data-bs-theme=dark] .accordion-button::after { + --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); +} + +.breadcrumb { + --bs-breadcrumb-padding-x: 0; + --bs-breadcrumb-padding-y: 0; + --bs-breadcrumb-margin-bottom: 1rem; + --bs-breadcrumb-bg: ; + --bs-breadcrumb-border-radius: ; + --bs-breadcrumb-divider-color: var(--bs-secondary-color); + --bs-breadcrumb-item-padding-x: 0.5rem; + --bs-breadcrumb-item-active-color: var(--bs-secondary-color); + display: flex; + flex-wrap: wrap; + padding: var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x); + margin-bottom: var(--bs-breadcrumb-margin-bottom); + font-size: var(--bs-breadcrumb-font-size); + list-style: none; + background-color: var(--bs-breadcrumb-bg); + border-radius: var(--bs-breadcrumb-border-radius); +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: var(--bs-breadcrumb-item-padding-x); +} +.breadcrumb-item + .breadcrumb-item::before { + float: left; + padding-right: var(--bs-breadcrumb-item-padding-x); + color: var(--bs-breadcrumb-divider-color); + content: var(--bs-breadcrumb-divider, "/") /* rtl: var(--bs-breadcrumb-divider, "/") */; +} +.breadcrumb-item.active { + color: var(--bs-breadcrumb-item-active-color); +} + +.pagination { + --bs-pagination-padding-x: 0.75rem; + --bs-pagination-padding-y: 0.375rem; + --bs-pagination-font-size: 1rem; + --bs-pagination-color: var(--bs-link-color); + --bs-pagination-bg: var(--bs-body-bg); + --bs-pagination-border-width: var(--bs-border-width); + --bs-pagination-border-color: var(--bs-border-color); + --bs-pagination-border-radius: var(--bs-border-radius); + --bs-pagination-hover-color: var(--bs-link-hover-color); + --bs-pagination-hover-bg: var(--bs-tertiary-bg); + --bs-pagination-hover-border-color: var(--bs-border-color); + --bs-pagination-focus-color: var(--bs-link-hover-color); + --bs-pagination-focus-bg: var(--bs-secondary-bg); + --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + --bs-pagination-active-color: #fff; + --bs-pagination-active-bg: #0d6efd; + --bs-pagination-active-border-color: #0d6efd; + --bs-pagination-disabled-color: var(--bs-secondary-color); + --bs-pagination-disabled-bg: var(--bs-secondary-bg); + --bs-pagination-disabled-border-color: var(--bs-border-color); + display: flex; + padding-left: 0; + list-style: none; +} + +.page-link { + position: relative; + display: block; + padding: var(--bs-pagination-padding-y) var(--bs-pagination-padding-x); + font-size: var(--bs-pagination-font-size); + color: var(--bs-pagination-color); + text-decoration: none; + background-color: var(--bs-pagination-bg); + border: var(--bs-pagination-border-width) solid var(--bs-pagination-border-color); + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .page-link { + transition: none; + } +} +.page-link:hover { + z-index: 2; + color: var(--bs-pagination-hover-color); + background-color: var(--bs-pagination-hover-bg); + border-color: var(--bs-pagination-hover-border-color); +} +.page-link:focus { + z-index: 3; + color: var(--bs-pagination-focus-color); + background-color: var(--bs-pagination-focus-bg); + outline: 0; + box-shadow: var(--bs-pagination-focus-box-shadow); +} +.page-link.active, .active > .page-link { + z-index: 3; + color: var(--bs-pagination-active-color); + background-color: var(--bs-pagination-active-bg); + border-color: var(--bs-pagination-active-border-color); +} +.page-link.disabled, .disabled > .page-link { + color: var(--bs-pagination-disabled-color); + pointer-events: none; + background-color: var(--bs-pagination-disabled-bg); + border-color: var(--bs-pagination-disabled-border-color); +} + +.page-item:not(:first-child) .page-link { + margin-left: calc(var(--bs-border-width) * -1); +} +.page-item:first-child .page-link { + border-top-left-radius: var(--bs-pagination-border-radius); + border-bottom-left-radius: var(--bs-pagination-border-radius); +} +.page-item:last-child .page-link { + border-top-right-radius: var(--bs-pagination-border-radius); + border-bottom-right-radius: var(--bs-pagination-border-radius); +} + +.pagination-lg { + --bs-pagination-padding-x: 1.5rem; + --bs-pagination-padding-y: 0.75rem; + --bs-pagination-font-size: 1.25rem; + --bs-pagination-border-radius: var(--bs-border-radius-lg); +} + +.pagination-sm { + --bs-pagination-padding-x: 0.5rem; + --bs-pagination-padding-y: 0.25rem; + --bs-pagination-font-size: 0.875rem; + --bs-pagination-border-radius: var(--bs-border-radius-sm); +} + +.badge { + --bs-badge-padding-x: 0.65em; + --bs-badge-padding-y: 0.35em; + --bs-badge-font-size: 0.75em; + --bs-badge-font-weight: 700; + --bs-badge-color: #fff; + --bs-badge-border-radius: var(--bs-border-radius); + display: inline-block; + padding: var(--bs-badge-padding-y) var(--bs-badge-padding-x); + font-size: var(--bs-badge-font-size); + font-weight: var(--bs-badge-font-weight); + line-height: 1; + color: var(--bs-badge-color); + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: var(--bs-badge-border-radius); +} +.badge:empty { + display: none; +} + +.btn .badge { + position: relative; + top: -1px; +} + +.alert { + --bs-alert-bg: transparent; + --bs-alert-padding-x: 1rem; + --bs-alert-padding-y: 1rem; + --bs-alert-margin-bottom: 1rem; + --bs-alert-color: inherit; + --bs-alert-border-color: transparent; + --bs-alert-border: var(--bs-border-width) solid var(--bs-alert-border-color); + --bs-alert-border-radius: var(--bs-border-radius); + --bs-alert-link-color: inherit; + position: relative; + padding: var(--bs-alert-padding-y) var(--bs-alert-padding-x); + margin-bottom: var(--bs-alert-margin-bottom); + color: var(--bs-alert-color); + background-color: var(--bs-alert-bg); + border: var(--bs-alert-border); + border-radius: var(--bs-alert-border-radius); +} + +.alert-heading { + color: inherit; +} + +.alert-link { + font-weight: 700; + color: var(--bs-alert-link-color); +} + +.alert-dismissible { + padding-right: 3rem; +} +.alert-dismissible .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: 2; + padding: 1.25rem 1rem; +} + +.alert-primary { + --bs-alert-color: var(--bs-primary-text-emphasis); + --bs-alert-bg: var(--bs-primary-bg-subtle); + --bs-alert-border-color: var(--bs-primary-border-subtle); + --bs-alert-link-color: var(--bs-primary-text-emphasis); +} + +.alert-secondary { + --bs-alert-color: var(--bs-secondary-text-emphasis); + --bs-alert-bg: var(--bs-secondary-bg-subtle); + --bs-alert-border-color: var(--bs-secondary-border-subtle); + --bs-alert-link-color: var(--bs-secondary-text-emphasis); +} + +.alert-success { + --bs-alert-color: var(--bs-success-text-emphasis); + --bs-alert-bg: var(--bs-success-bg-subtle); + --bs-alert-border-color: var(--bs-success-border-subtle); + --bs-alert-link-color: var(--bs-success-text-emphasis); +} + +.alert-info { + --bs-alert-color: var(--bs-info-text-emphasis); + --bs-alert-bg: var(--bs-info-bg-subtle); + --bs-alert-border-color: var(--bs-info-border-subtle); + --bs-alert-link-color: var(--bs-info-text-emphasis); +} + +.alert-warning { + --bs-alert-color: var(--bs-warning-text-emphasis); + --bs-alert-bg: var(--bs-warning-bg-subtle); + --bs-alert-border-color: var(--bs-warning-border-subtle); + --bs-alert-link-color: var(--bs-warning-text-emphasis); +} + +.alert-danger { + --bs-alert-color: var(--bs-danger-text-emphasis); + --bs-alert-bg: var(--bs-danger-bg-subtle); + --bs-alert-border-color: var(--bs-danger-border-subtle); + --bs-alert-link-color: var(--bs-danger-text-emphasis); +} + +.alert-light { + --bs-alert-color: var(--bs-light-text-emphasis); + --bs-alert-bg: var(--bs-light-bg-subtle); + --bs-alert-border-color: var(--bs-light-border-subtle); + --bs-alert-link-color: var(--bs-light-text-emphasis); +} + +.alert-dark { + --bs-alert-color: var(--bs-dark-text-emphasis); + --bs-alert-bg: var(--bs-dark-bg-subtle); + --bs-alert-border-color: var(--bs-dark-border-subtle); + --bs-alert-link-color: var(--bs-dark-text-emphasis); +} + +@keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem; + } +} +.progress, +.progress-stacked { + --bs-progress-height: 1rem; + --bs-progress-font-size: 0.75rem; + --bs-progress-bg: var(--bs-secondary-bg); + --bs-progress-border-radius: var(--bs-border-radius); + --bs-progress-box-shadow: var(--bs-box-shadow-inset); + --bs-progress-bar-color: #fff; + --bs-progress-bar-bg: #0d6efd; + --bs-progress-bar-transition: width 0.6s ease; + display: flex; + height: var(--bs-progress-height); + overflow: hidden; + font-size: var(--bs-progress-font-size); + background-color: var(--bs-progress-bg); + border-radius: var(--bs-progress-border-radius); +} + +.progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + overflow: hidden; + color: var(--bs-progress-bar-color); + text-align: center; + white-space: nowrap; + background-color: var(--bs-progress-bar-bg); + transition: var(--bs-progress-bar-transition); +} +@media (prefers-reduced-motion: reduce) { + .progress-bar { + transition: none; + } +} + +.progress-bar-striped { + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: var(--bs-progress-height) var(--bs-progress-height); +} + +.progress-stacked > .progress { + overflow: visible; +} + +.progress-stacked > .progress > .progress-bar { + width: 100%; +} + +.progress-bar-animated { + animation: 1s linear infinite progress-bar-stripes; +} +@media (prefers-reduced-motion: reduce) { + .progress-bar-animated { + animation: none; + } +} + +.list-group { + --bs-list-group-color: var(--bs-body-color); + --bs-list-group-bg: var(--bs-body-bg); + --bs-list-group-border-color: var(--bs-border-color); + --bs-list-group-border-width: var(--bs-border-width); + --bs-list-group-border-radius: var(--bs-border-radius); + --bs-list-group-item-padding-x: 1rem; + --bs-list-group-item-padding-y: 0.5rem; + --bs-list-group-action-color: var(--bs-secondary-color); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-tertiary-bg); + --bs-list-group-action-active-color: var(--bs-body-color); + --bs-list-group-action-active-bg: var(--bs-secondary-bg); + --bs-list-group-disabled-color: var(--bs-secondary-color); + --bs-list-group-disabled-bg: var(--bs-body-bg); + --bs-list-group-active-color: #fff; + --bs-list-group-active-bg: #0d6efd; + --bs-list-group-active-border-color: #0d6efd; + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + border-radius: var(--bs-list-group-border-radius); +} + +.list-group-numbered { + list-style-type: none; + counter-reset: section; +} +.list-group-numbered > .list-group-item::before { + content: counters(section, ".") ". "; + counter-increment: section; +} + +.list-group-item-action { + width: 100%; + color: var(--bs-list-group-action-color); + text-align: inherit; +} +.list-group-item-action:hover, .list-group-item-action:focus { + z-index: 1; + color: var(--bs-list-group-action-hover-color); + text-decoration: none; + background-color: var(--bs-list-group-action-hover-bg); +} +.list-group-item-action:active { + color: var(--bs-list-group-action-active-color); + background-color: var(--bs-list-group-action-active-bg); +} + +.list-group-item { + position: relative; + display: block; + padding: var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x); + color: var(--bs-list-group-color); + text-decoration: none; + background-color: var(--bs-list-group-bg); + border: var(--bs-list-group-border-width) solid var(--bs-list-group-border-color); +} +.list-group-item:first-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} +.list-group-item:last-child { + border-bottom-right-radius: inherit; + border-bottom-left-radius: inherit; +} +.list-group-item.disabled, .list-group-item:disabled { + color: var(--bs-list-group-disabled-color); + pointer-events: none; + background-color: var(--bs-list-group-disabled-bg); +} +.list-group-item.active { + z-index: 2; + color: var(--bs-list-group-active-color); + background-color: var(--bs-list-group-active-bg); + border-color: var(--bs-list-group-active-border-color); +} +.list-group-item + .list-group-item { + border-top-width: 0; +} +.list-group-item + .list-group-item.active { + margin-top: calc(-1 * var(--bs-list-group-border-width)); + border-top-width: var(--bs-list-group-border-width); +} + +.list-group-horizontal { + flex-direction: row; +} +.list-group-horizontal > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; +} +.list-group-horizontal > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; +} +.list-group-horizontal > .list-group-item.active { + margin-top: 0; +} +.list-group-horizontal > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; +} +.list-group-horizontal > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); +} + +@media (min-width: 576px) { + .list-group-horizontal-sm { + flex-direction: row; + } + .list-group-horizontal-sm > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-sm > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-sm > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-sm > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-sm > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} +@media (min-width: 768px) { + .list-group-horizontal-md { + flex-direction: row; + } + .list-group-horizontal-md > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-md > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-md > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-md > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-md > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} +@media (min-width: 992px) { + .list-group-horizontal-lg { + flex-direction: row; + } + .list-group-horizontal-lg > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-lg > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-lg > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-lg > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-lg > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} +@media (min-width: 1200px) { + .list-group-horizontal-xl { + flex-direction: row; + } + .list-group-horizontal-xl > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-xl > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-xl > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-xl > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-xl > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} +@media (min-width: 1400px) { + .list-group-horizontal-xxl { + flex-direction: row; + } + .list-group-horizontal-xxl > .list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--bs-list-group-border-radius); + border-top-right-radius: 0; + } + .list-group-horizontal-xxl > .list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--bs-list-group-border-radius); + border-bottom-left-radius: 0; + } + .list-group-horizontal-xxl > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-xxl > .list-group-item + .list-group-item { + border-top-width: var(--bs-list-group-border-width); + border-left-width: 0; + } + .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { + margin-left: calc(-1 * var(--bs-list-group-border-width)); + border-left-width: var(--bs-list-group-border-width); + } +} +.list-group-flush { + border-radius: 0; +} +.list-group-flush > .list-group-item { + border-width: 0 0 var(--bs-list-group-border-width); +} +.list-group-flush > .list-group-item:last-child { + border-bottom-width: 0; +} + +.list-group-item-primary { + --bs-list-group-color: var(--bs-primary-text-emphasis); + --bs-list-group-bg: var(--bs-primary-bg-subtle); + --bs-list-group-border-color: var(--bs-primary-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-primary-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-primary-border-subtle); + --bs-list-group-active-color: var(--bs-primary-bg-subtle); + --bs-list-group-active-bg: var(--bs-primary-text-emphasis); + --bs-list-group-active-border-color: var(--bs-primary-text-emphasis); +} + +.list-group-item-secondary { + --bs-list-group-color: var(--bs-secondary-text-emphasis); + --bs-list-group-bg: var(--bs-secondary-bg-subtle); + --bs-list-group-border-color: var(--bs-secondary-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-secondary-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-secondary-border-subtle); + --bs-list-group-active-color: var(--bs-secondary-bg-subtle); + --bs-list-group-active-bg: var(--bs-secondary-text-emphasis); + --bs-list-group-active-border-color: var(--bs-secondary-text-emphasis); +} + +.list-group-item-success { + --bs-list-group-color: var(--bs-success-text-emphasis); + --bs-list-group-bg: var(--bs-success-bg-subtle); + --bs-list-group-border-color: var(--bs-success-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-success-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-success-border-subtle); + --bs-list-group-active-color: var(--bs-success-bg-subtle); + --bs-list-group-active-bg: var(--bs-success-text-emphasis); + --bs-list-group-active-border-color: var(--bs-success-text-emphasis); +} + +.list-group-item-info { + --bs-list-group-color: var(--bs-info-text-emphasis); + --bs-list-group-bg: var(--bs-info-bg-subtle); + --bs-list-group-border-color: var(--bs-info-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-info-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-info-border-subtle); + --bs-list-group-active-color: var(--bs-info-bg-subtle); + --bs-list-group-active-bg: var(--bs-info-text-emphasis); + --bs-list-group-active-border-color: var(--bs-info-text-emphasis); +} + +.list-group-item-warning { + --bs-list-group-color: var(--bs-warning-text-emphasis); + --bs-list-group-bg: var(--bs-warning-bg-subtle); + --bs-list-group-border-color: var(--bs-warning-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-warning-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-warning-border-subtle); + --bs-list-group-active-color: var(--bs-warning-bg-subtle); + --bs-list-group-active-bg: var(--bs-warning-text-emphasis); + --bs-list-group-active-border-color: var(--bs-warning-text-emphasis); +} + +.list-group-item-danger { + --bs-list-group-color: var(--bs-danger-text-emphasis); + --bs-list-group-bg: var(--bs-danger-bg-subtle); + --bs-list-group-border-color: var(--bs-danger-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-danger-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-danger-border-subtle); + --bs-list-group-active-color: var(--bs-danger-bg-subtle); + --bs-list-group-active-bg: var(--bs-danger-text-emphasis); + --bs-list-group-active-border-color: var(--bs-danger-text-emphasis); +} + +.list-group-item-light { + --bs-list-group-color: var(--bs-light-text-emphasis); + --bs-list-group-bg: var(--bs-light-bg-subtle); + --bs-list-group-border-color: var(--bs-light-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-light-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-light-border-subtle); + --bs-list-group-active-color: var(--bs-light-bg-subtle); + --bs-list-group-active-bg: var(--bs-light-text-emphasis); + --bs-list-group-active-border-color: var(--bs-light-text-emphasis); +} + +.list-group-item-dark { + --bs-list-group-color: var(--bs-dark-text-emphasis); + --bs-list-group-bg: var(--bs-dark-bg-subtle); + --bs-list-group-border-color: var(--bs-dark-border-subtle); + --bs-list-group-action-hover-color: var(--bs-emphasis-color); + --bs-list-group-action-hover-bg: var(--bs-dark-border-subtle); + --bs-list-group-action-active-color: var(--bs-emphasis-color); + --bs-list-group-action-active-bg: var(--bs-dark-border-subtle); + --bs-list-group-active-color: var(--bs-dark-bg-subtle); + --bs-list-group-active-bg: var(--bs-dark-text-emphasis); + --bs-list-group-active-border-color: var(--bs-dark-text-emphasis); +} + +.btn-close { + --bs-btn-close-color: #000; + --bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e"); + --bs-btn-close-opacity: 0.5; + --bs-btn-close-hover-opacity: 0.75; + --bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + --bs-btn-close-focus-opacity: 1; + --bs-btn-close-disabled-opacity: 0.25; + --bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%); + box-sizing: content-box; + width: 1em; + height: 1em; + padding: 0.25em 0.25em; + color: var(--bs-btn-close-color); + background: transparent var(--bs-btn-close-bg) center/1em auto no-repeat; + border: 0; + border-radius: 0.375rem; + opacity: var(--bs-btn-close-opacity); +} +.btn-close:hover { + color: var(--bs-btn-close-color); + text-decoration: none; + opacity: var(--bs-btn-close-hover-opacity); +} +.btn-close:focus { + outline: 0; + box-shadow: var(--bs-btn-close-focus-shadow); + opacity: var(--bs-btn-close-focus-opacity); +} +.btn-close:disabled, .btn-close.disabled { + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + opacity: var(--bs-btn-close-disabled-opacity); +} + +.btn-close-white { + filter: var(--bs-btn-close-white-filter); +} + +[data-bs-theme=dark] .btn-close { + filter: var(--bs-btn-close-white-filter); +} + +.toast { + --bs-toast-zindex: 1090; + --bs-toast-padding-x: 0.75rem; + --bs-toast-padding-y: 0.5rem; + --bs-toast-spacing: 1.5rem; + --bs-toast-max-width: 350px; + --bs-toast-font-size: 0.875rem; + --bs-toast-color: ; + --bs-toast-bg: rgba(var(--bs-body-bg-rgb), 0.85); + --bs-toast-border-width: var(--bs-border-width); + --bs-toast-border-color: var(--bs-border-color-translucent); + --bs-toast-border-radius: var(--bs-border-radius); + --bs-toast-box-shadow: var(--bs-box-shadow); + --bs-toast-header-color: var(--bs-secondary-color); + --bs-toast-header-bg: rgba(var(--bs-body-bg-rgb), 0.85); + --bs-toast-header-border-color: var(--bs-border-color-translucent); + width: var(--bs-toast-max-width); + max-width: 100%; + font-size: var(--bs-toast-font-size); + color: var(--bs-toast-color); + pointer-events: auto; + background-color: var(--bs-toast-bg); + background-clip: padding-box; + border: var(--bs-toast-border-width) solid var(--bs-toast-border-color); + box-shadow: var(--bs-toast-box-shadow); + border-radius: var(--bs-toast-border-radius); +} +.toast.showing { + opacity: 0; +} +.toast:not(.show) { + display: none; +} + +.toast-container { + --bs-toast-zindex: 1090; + position: absolute; + z-index: var(--bs-toast-zindex); + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + max-width: 100%; + pointer-events: none; +} +.toast-container > :not(:last-child) { + margin-bottom: var(--bs-toast-spacing); +} + +.toast-header { + display: flex; + align-items: center; + padding: var(--bs-toast-padding-y) var(--bs-toast-padding-x); + color: var(--bs-toast-header-color); + background-color: var(--bs-toast-header-bg); + background-clip: padding-box; + border-bottom: var(--bs-toast-border-width) solid var(--bs-toast-header-border-color); + border-top-left-radius: calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width)); + border-top-right-radius: calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width)); +} +.toast-header .btn-close { + margin-right: calc(-0.5 * var(--bs-toast-padding-x)); + margin-left: var(--bs-toast-padding-x); +} + +.toast-body { + padding: var(--bs-toast-padding-x); + word-wrap: break-word; +} + +.modal { + --bs-modal-zindex: 1055; + --bs-modal-width: 500px; + --bs-modal-padding: 1rem; + --bs-modal-margin: 0.5rem; + --bs-modal-color: ; + --bs-modal-bg: var(--bs-body-bg); + --bs-modal-border-color: var(--bs-border-color-translucent); + --bs-modal-border-width: var(--bs-border-width); + --bs-modal-border-radius: var(--bs-border-radius-lg); + --bs-modal-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); + --bs-modal-inner-border-radius: calc(var(--bs-border-radius-lg) - (var(--bs-border-width))); + --bs-modal-header-padding-x: 1rem; + --bs-modal-header-padding-y: 1rem; + --bs-modal-header-padding: 1rem 1rem; + --bs-modal-header-border-color: var(--bs-border-color); + --bs-modal-header-border-width: var(--bs-border-width); + --bs-modal-title-line-height: 1.5; + --bs-modal-footer-gap: 0.5rem; + --bs-modal-footer-bg: ; + --bs-modal-footer-border-color: var(--bs-border-color); + --bs-modal-footer-border-width: var(--bs-border-width); + position: fixed; + top: 0; + left: 0; + z-index: var(--bs-modal-zindex); + display: none; + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + outline: 0; +} + +.modal-dialog { + position: relative; + width: auto; + margin: var(--bs-modal-margin); + pointer-events: none; +} +.modal.fade .modal-dialog { + transition: transform 0.3s ease-out; + transform: translate(0, -50px); +} +@media (prefers-reduced-motion: reduce) { + .modal.fade .modal-dialog { + transition: none; + } +} +.modal.show .modal-dialog { + transform: none; +} +.modal.modal-static .modal-dialog { + transform: scale(1.02); +} + +.modal-dialog-scrollable { + height: calc(100% - var(--bs-modal-margin) * 2); +} +.modal-dialog-scrollable .modal-content { + max-height: 100%; + overflow: hidden; +} +.modal-dialog-scrollable .modal-body { + overflow-y: auto; +} + +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - var(--bs-modal-margin) * 2); +} + +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + color: var(--bs-modal-color); + pointer-events: auto; + background-color: var(--bs-modal-bg); + background-clip: padding-box; + border: var(--bs-modal-border-width) solid var(--bs-modal-border-color); + border-radius: var(--bs-modal-border-radius); + outline: 0; +} + +.modal-backdrop { + --bs-backdrop-zindex: 1050; + --bs-backdrop-bg: #000; + --bs-backdrop-opacity: 0.5; + position: fixed; + top: 0; + left: 0; + z-index: var(--bs-backdrop-zindex); + width: 100vw; + height: 100vh; + background-color: var(--bs-backdrop-bg); +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop.show { + opacity: var(--bs-backdrop-opacity); +} + +.modal-header { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: space-between; + padding: var(--bs-modal-header-padding); + border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); + border-top-left-radius: var(--bs-modal-inner-border-radius); + border-top-right-radius: var(--bs-modal-inner-border-radius); +} +.modal-header .btn-close { + padding: calc(var(--bs-modal-header-padding-y) * 0.5) calc(var(--bs-modal-header-padding-x) * 0.5); + margin: calc(-0.5 * var(--bs-modal-header-padding-y)) calc(-0.5 * var(--bs-modal-header-padding-x)) calc(-0.5 * var(--bs-modal-header-padding-y)) auto; +} + +.modal-title { + margin-bottom: 0; + line-height: var(--bs-modal-title-line-height); +} + +.modal-body { + position: relative; + flex: 1 1 auto; + padding: var(--bs-modal-padding); +} + +.modal-footer { + display: flex; + flex-shrink: 0; + flex-wrap: wrap; + align-items: center; + justify-content: flex-end; + padding: calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * 0.5); + background-color: var(--bs-modal-footer-bg); + border-top: var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color); + border-bottom-right-radius: var(--bs-modal-inner-border-radius); + border-bottom-left-radius: var(--bs-modal-inner-border-radius); +} +.modal-footer > * { + margin: calc(var(--bs-modal-footer-gap) * 0.5); +} + +@media (min-width: 576px) { + .modal { + --bs-modal-margin: 1.75rem; + --bs-modal-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + } + .modal-dialog { + max-width: var(--bs-modal-width); + margin-right: auto; + margin-left: auto; + } + .modal-sm { + --bs-modal-width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg, + .modal-xl { + --bs-modal-width: 800px; + } +} +@media (min-width: 1200px) { + .modal-xl { + --bs-modal-width: 1140px; + } +} +.modal-fullscreen { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; +} +.modal-fullscreen .modal-content { + height: 100%; + border: 0; + border-radius: 0; +} +.modal-fullscreen .modal-header, +.modal-fullscreen .modal-footer { + border-radius: 0; +} +.modal-fullscreen .modal-body { + overflow-y: auto; +} + +@media (max-width: 575.98px) { + .modal-fullscreen-sm-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-sm-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-sm-down .modal-header, + .modal-fullscreen-sm-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-sm-down .modal-body { + overflow-y: auto; + } +} +@media (max-width: 767.98px) { + .modal-fullscreen-md-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-md-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-md-down .modal-header, + .modal-fullscreen-md-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-md-down .modal-body { + overflow-y: auto; + } +} +@media (max-width: 991.98px) { + .modal-fullscreen-lg-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-lg-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-lg-down .modal-header, + .modal-fullscreen-lg-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-lg-down .modal-body { + overflow-y: auto; + } +} +@media (max-width: 1199.98px) { + .modal-fullscreen-xl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-xl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-xl-down .modal-header, + .modal-fullscreen-xl-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-xl-down .modal-body { + overflow-y: auto; + } +} +@media (max-width: 1399.98px) { + .modal-fullscreen-xxl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-xxl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-xxl-down .modal-header, + .modal-fullscreen-xxl-down .modal-footer { + border-radius: 0; + } + .modal-fullscreen-xxl-down .modal-body { + overflow-y: auto; + } +} +.tooltip { + --bs-tooltip-zindex: 1080; + --bs-tooltip-max-width: 200px; + --bs-tooltip-padding-x: 0.5rem; + --bs-tooltip-padding-y: 0.25rem; + --bs-tooltip-margin: ; + --bs-tooltip-font-size: 0.875rem; + --bs-tooltip-color: var(--bs-body-bg); + --bs-tooltip-bg: var(--bs-emphasis-color); + --bs-tooltip-border-radius: var(--bs-border-radius); + --bs-tooltip-opacity: 0.9; + --bs-tooltip-arrow-width: 0.8rem; + --bs-tooltip-arrow-height: 0.4rem; + z-index: var(--bs-tooltip-zindex); + display: block; + margin: var(--bs-tooltip-margin); + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + white-space: normal; + word-spacing: normal; + line-break: auto; + font-size: var(--bs-tooltip-font-size); + word-wrap: break-word; + opacity: 0; +} +.tooltip.show { + opacity: var(--bs-tooltip-opacity); +} +.tooltip .tooltip-arrow { + display: block; + width: var(--bs-tooltip-arrow-width); + height: var(--bs-tooltip-arrow-height); +} +.tooltip .tooltip-arrow::before { + position: absolute; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-tooltip-top .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow { + bottom: calc(-1 * var(--bs-tooltip-arrow-height)); +} +.bs-tooltip-top .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before { + top: -1px; + border-width: var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * 0.5) 0; + border-top-color: var(--bs-tooltip-bg); +} + +/* rtl:begin:ignore */ +.bs-tooltip-end .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow { + left: calc(-1 * var(--bs-tooltip-arrow-height)); + width: var(--bs-tooltip-arrow-height); + height: var(--bs-tooltip-arrow-width); +} +.bs-tooltip-end .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before { + right: -1px; + border-width: calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * 0.5) 0; + border-right-color: var(--bs-tooltip-bg); +} + +/* rtl:end:ignore */ +.bs-tooltip-bottom .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow { + top: calc(-1 * var(--bs-tooltip-arrow-height)); +} +.bs-tooltip-bottom .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before { + bottom: -1px; + border-width: 0 calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height); + border-bottom-color: var(--bs-tooltip-bg); +} + +/* rtl:begin:ignore */ +.bs-tooltip-start .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow { + right: calc(-1 * var(--bs-tooltip-arrow-height)); + width: var(--bs-tooltip-arrow-height); + height: var(--bs-tooltip-arrow-width); +} +.bs-tooltip-start .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before { + left: -1px; + border-width: calc(var(--bs-tooltip-arrow-width) * 0.5) 0 calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height); + border-left-color: var(--bs-tooltip-bg); +} + +/* rtl:end:ignore */ +.tooltip-inner { + max-width: var(--bs-tooltip-max-width); + padding: var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x); + color: var(--bs-tooltip-color); + text-align: center; + background-color: var(--bs-tooltip-bg); + border-radius: var(--bs-tooltip-border-radius); +} + +.popover { + --bs-popover-zindex: 1070; + --bs-popover-max-width: 276px; + --bs-popover-font-size: 0.875rem; + --bs-popover-bg: var(--bs-body-bg); + --bs-popover-border-width: var(--bs-border-width); + --bs-popover-border-color: var(--bs-border-color-translucent); + --bs-popover-border-radius: var(--bs-border-radius-lg); + --bs-popover-inner-border-radius: calc(var(--bs-border-radius-lg) - var(--bs-border-width)); + --bs-popover-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --bs-popover-header-padding-x: 1rem; + --bs-popover-header-padding-y: 0.5rem; + --bs-popover-header-font-size: 1rem; + --bs-popover-header-color: ; + --bs-popover-header-bg: var(--bs-secondary-bg); + --bs-popover-body-padding-x: 1rem; + --bs-popover-body-padding-y: 1rem; + --bs-popover-body-color: var(--bs-body-color); + --bs-popover-arrow-width: 1rem; + --bs-popover-arrow-height: 0.5rem; + --bs-popover-arrow-border: var(--bs-popover-border-color); + z-index: var(--bs-popover-zindex); + display: block; + max-width: var(--bs-popover-max-width); + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + white-space: normal; + word-spacing: normal; + line-break: auto; + font-size: var(--bs-popover-font-size); + word-wrap: break-word; + background-color: var(--bs-popover-bg); + background-clip: padding-box; + border: var(--bs-popover-border-width) solid var(--bs-popover-border-color); + border-radius: var(--bs-popover-border-radius); +} +.popover .popover-arrow { + display: block; + width: var(--bs-popover-arrow-width); + height: var(--bs-popover-arrow-height); +} +.popover .popover-arrow::before, .popover .popover-arrow::after { + position: absolute; + display: block; + content: ""; + border-color: transparent; + border-style: solid; + border-width: 0; +} + +.bs-popover-top > .popover-arrow, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow { + bottom: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); +} +.bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before, .bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { + border-width: var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * 0.5) 0; +} +.bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before { + bottom: 0; + border-top-color: var(--bs-popover-arrow-border); +} +.bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { + bottom: var(--bs-popover-border-width); + border-top-color: var(--bs-popover-bg); +} + +/* rtl:begin:ignore */ +.bs-popover-end > .popover-arrow, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow { + left: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); + width: var(--bs-popover-arrow-height); + height: var(--bs-popover-arrow-width); +} +.bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before, .bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { + border-width: calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * 0.5) 0; +} +.bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before { + left: 0; + border-right-color: var(--bs-popover-arrow-border); +} +.bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { + left: var(--bs-popover-border-width); + border-right-color: var(--bs-popover-bg); +} + +/* rtl:end:ignore */ +.bs-popover-bottom > .popover-arrow, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow { + top: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); +} +.bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before, .bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { + border-width: 0 calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height); +} +.bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before { + top: 0; + border-bottom-color: var(--bs-popover-arrow-border); +} +.bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { + top: var(--bs-popover-border-width); + border-bottom-color: var(--bs-popover-bg); +} +.bs-popover-bottom .popover-header::before, .bs-popover-auto[data-popper-placement^=bottom] .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: var(--bs-popover-arrow-width); + margin-left: calc(-0.5 * var(--bs-popover-arrow-width)); + content: ""; + border-bottom: var(--bs-popover-border-width) solid var(--bs-popover-header-bg); +} + +/* rtl:begin:ignore */ +.bs-popover-start > .popover-arrow, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow { + right: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); + width: var(--bs-popover-arrow-height); + height: var(--bs-popover-arrow-width); +} +.bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before, .bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { + border-width: calc(var(--bs-popover-arrow-width) * 0.5) 0 calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height); +} +.bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before { + right: 0; + border-left-color: var(--bs-popover-arrow-border); +} +.bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { + right: var(--bs-popover-border-width); + border-left-color: var(--bs-popover-bg); +} + +/* rtl:end:ignore */ +.popover-header { + padding: var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x); + margin-bottom: 0; + font-size: var(--bs-popover-header-font-size); + color: var(--bs-popover-header-color); + background-color: var(--bs-popover-header-bg); + border-bottom: var(--bs-popover-border-width) solid var(--bs-popover-border-color); + border-top-left-radius: var(--bs-popover-inner-border-radius); + border-top-right-radius: var(--bs-popover-inner-border-radius); +} +.popover-header:empty { + display: none; +} + +.popover-body { + padding: var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x); + color: var(--bs-popover-body-color); +} + +.carousel { + position: relative; +} + +.carousel.pointer-event { + touch-action: pan-y; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner::after { + display: block; + clear: both; + content: ""; +} + +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transition: transform 0.6s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .carousel-item { + transition: none; + } +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +.carousel-item-next:not(.carousel-item-start), +.active.carousel-item-end { + transform: translateX(100%); +} + +.carousel-item-prev:not(.carousel-item-end), +.active.carousel-item-start { + transform: translateX(-100%); +} + +.carousel-fade .carousel-item { + opacity: 0; + transition-property: opacity; + transform: none; +} +.carousel-fade .carousel-item.active, +.carousel-fade .carousel-item-next.carousel-item-start, +.carousel-fade .carousel-item-prev.carousel-item-end { + z-index: 1; + opacity: 1; +} +.carousel-fade .active.carousel-item-start, +.carousel-fade .active.carousel-item-end { + z-index: 0; + opacity: 0; + transition: opacity 0s 0.6s; +} +@media (prefers-reduced-motion: reduce) { + .carousel-fade .active.carousel-item-start, + .carousel-fade .active.carousel-item-end { + transition: none; + } +} + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + width: 15%; + padding: 0; + color: #fff; + text-align: center; + background: none; + border: 0; + opacity: 0.5; + transition: opacity 0.15s ease; +} +@media (prefers-reduced-motion: reduce) { + .carousel-control-prev, + .carousel-control-next { + transition: none; + } +} +.carousel-control-prev:hover, .carousel-control-prev:focus, +.carousel-control-next:hover, +.carousel-control-next:focus { + color: #fff; + text-decoration: none; + outline: 0; + opacity: 0.9; +} + +.carousel-control-prev { + left: 0; +} + +.carousel-control-next { + right: 0; +} + +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: 2rem; + height: 2rem; + background-repeat: no-repeat; + background-position: 50%; + background-size: 100% 100%; +} + +/* rtl:options: { + "autoRename": true, + "stringMap":[ { + "name" : "prev-next", + "search" : "prev", + "replace" : "next" + } ] +} */ +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 2; + display: flex; + justify-content: center; + padding: 0; + margin-right: 15%; + margin-bottom: 1rem; + margin-left: 15%; +} +.carousel-indicators [data-bs-target] { + box-sizing: content-box; + flex: 0 1 auto; + width: 30px; + height: 3px; + padding: 0; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: #fff; + background-clip: padding-box; + border: 0; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + opacity: 0.5; + transition: opacity 0.6s ease; +} +@media (prefers-reduced-motion: reduce) { + .carousel-indicators [data-bs-target] { + transition: none; + } +} +.carousel-indicators .active { + opacity: 1; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 1.25rem; + left: 15%; + padding-top: 1.25rem; + padding-bottom: 1.25rem; + color: #fff; + text-align: center; +} + +.carousel-dark .carousel-control-prev-icon, +.carousel-dark .carousel-control-next-icon { + filter: invert(1) grayscale(100); +} +.carousel-dark .carousel-indicators [data-bs-target] { + background-color: #000; +} +.carousel-dark .carousel-caption { + color: #000; +} + +[data-bs-theme=dark] .carousel .carousel-control-prev-icon, +[data-bs-theme=dark] .carousel .carousel-control-next-icon, [data-bs-theme=dark].carousel .carousel-control-prev-icon, +[data-bs-theme=dark].carousel .carousel-control-next-icon { + filter: invert(1) grayscale(100); +} +[data-bs-theme=dark] .carousel .carousel-indicators [data-bs-target], [data-bs-theme=dark].carousel .carousel-indicators [data-bs-target] { + background-color: #000; +} +[data-bs-theme=dark] .carousel .carousel-caption, [data-bs-theme=dark].carousel .carousel-caption { + color: #000; +} + +.spinner-grow, +.spinner-border { + display: inline-block; + width: var(--bs-spinner-width); + height: var(--bs-spinner-height); + vertical-align: var(--bs-spinner-vertical-align); + border-radius: 50%; + animation: var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name); +} + +@keyframes spinner-border { + to { + transform: rotate(360deg) /* rtl:ignore */; + } +} +.spinner-border { + --bs-spinner-width: 2rem; + --bs-spinner-height: 2rem; + --bs-spinner-vertical-align: -0.125em; + --bs-spinner-border-width: 0.25em; + --bs-spinner-animation-speed: 0.75s; + --bs-spinner-animation-name: spinner-border; + border: var(--bs-spinner-border-width) solid currentcolor; + border-right-color: transparent; +} + +.spinner-border-sm { + --bs-spinner-width: 1rem; + --bs-spinner-height: 1rem; + --bs-spinner-border-width: 0.2em; +} + +@keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} +.spinner-grow { + --bs-spinner-width: 2rem; + --bs-spinner-height: 2rem; + --bs-spinner-vertical-align: -0.125em; + --bs-spinner-animation-speed: 0.75s; + --bs-spinner-animation-name: spinner-grow; + background-color: currentcolor; + opacity: 0; +} + +.spinner-grow-sm { + --bs-spinner-width: 1rem; + --bs-spinner-height: 1rem; +} + +@media (prefers-reduced-motion: reduce) { + .spinner-border, + .spinner-grow { + --bs-spinner-animation-speed: 1.5s; + } +} +.offcanvas, .offcanvas-xxl, .offcanvas-xl, .offcanvas-lg, .offcanvas-md, .offcanvas-sm { + --bs-offcanvas-zindex: 1045; + --bs-offcanvas-width: 400px; + --bs-offcanvas-height: 30vh; + --bs-offcanvas-padding-x: 1rem; + --bs-offcanvas-padding-y: 1rem; + --bs-offcanvas-color: var(--bs-body-color); + --bs-offcanvas-bg: var(--bs-body-bg); + --bs-offcanvas-border-width: var(--bs-border-width); + --bs-offcanvas-border-color: var(--bs-border-color-translucent); + --bs-offcanvas-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); + --bs-offcanvas-transition: transform 0.3s ease-in-out; + --bs-offcanvas-title-line-height: 1.5; +} + +@media (max-width: 575.98px) { + .offcanvas-sm { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 575.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-sm { + transition: none; + } +} +@media (max-width: 575.98px) { + .offcanvas-sm.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } +} +@media (max-width: 575.98px) { + .offcanvas-sm.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(100%); + } +} +@media (max-width: 575.98px) { + .offcanvas-sm.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } +} +@media (max-width: 575.98px) { + .offcanvas-sm.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(100%); + } +} +@media (max-width: 575.98px) { + .offcanvas-sm.showing, .offcanvas-sm.show:not(.hiding) { + transform: none; + } +} +@media (max-width: 575.98px) { + .offcanvas-sm.showing, .offcanvas-sm.hiding, .offcanvas-sm.show { + visibility: visible; + } +} +@media (min-width: 576px) { + .offcanvas-sm { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-sm .offcanvas-header { + display: none; + } + .offcanvas-sm .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +@media (max-width: 767.98px) { + .offcanvas-md { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 767.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-md { + transition: none; + } +} +@media (max-width: 767.98px) { + .offcanvas-md.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } +} +@media (max-width: 767.98px) { + .offcanvas-md.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(100%); + } +} +@media (max-width: 767.98px) { + .offcanvas-md.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } +} +@media (max-width: 767.98px) { + .offcanvas-md.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(100%); + } +} +@media (max-width: 767.98px) { + .offcanvas-md.showing, .offcanvas-md.show:not(.hiding) { + transform: none; + } +} +@media (max-width: 767.98px) { + .offcanvas-md.showing, .offcanvas-md.hiding, .offcanvas-md.show { + visibility: visible; + } +} +@media (min-width: 768px) { + .offcanvas-md { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-md .offcanvas-header { + display: none; + } + .offcanvas-md .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +@media (max-width: 991.98px) { + .offcanvas-lg { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 991.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-lg { + transition: none; + } +} +@media (max-width: 991.98px) { + .offcanvas-lg.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } +} +@media (max-width: 991.98px) { + .offcanvas-lg.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(100%); + } +} +@media (max-width: 991.98px) { + .offcanvas-lg.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } +} +@media (max-width: 991.98px) { + .offcanvas-lg.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(100%); + } +} +@media (max-width: 991.98px) { + .offcanvas-lg.showing, .offcanvas-lg.show:not(.hiding) { + transform: none; + } +} +@media (max-width: 991.98px) { + .offcanvas-lg.showing, .offcanvas-lg.hiding, .offcanvas-lg.show { + visibility: visible; + } +} +@media (min-width: 992px) { + .offcanvas-lg { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-lg .offcanvas-header { + display: none; + } + .offcanvas-lg .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +@media (max-width: 1199.98px) { + .offcanvas-xl { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 1199.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-xl { + transition: none; + } +} +@media (max-width: 1199.98px) { + .offcanvas-xl.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } +} +@media (max-width: 1199.98px) { + .offcanvas-xl.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(100%); + } +} +@media (max-width: 1199.98px) { + .offcanvas-xl.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } +} +@media (max-width: 1199.98px) { + .offcanvas-xl.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(100%); + } +} +@media (max-width: 1199.98px) { + .offcanvas-xl.showing, .offcanvas-xl.show:not(.hiding) { + transform: none; + } +} +@media (max-width: 1199.98px) { + .offcanvas-xl.showing, .offcanvas-xl.hiding, .offcanvas-xl.show { + visibility: visible; + } +} +@media (min-width: 1200px) { + .offcanvas-xl { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-xl .offcanvas-header { + display: none; + } + .offcanvas-xl .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +@media (max-width: 1399.98px) { + .offcanvas-xxl { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); + } +} +@media (max-width: 1399.98px) and (prefers-reduced-motion: reduce) { + .offcanvas-xxl { + transition: none; + } +} +@media (max-width: 1399.98px) { + .offcanvas-xxl.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(-100%); + } +} +@media (max-width: 1399.98px) { + .offcanvas-xxl.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(100%); + } +} +@media (max-width: 1399.98px) { + .offcanvas-xxl.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(-100%); + } +} +@media (max-width: 1399.98px) { + .offcanvas-xxl.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(100%); + } +} +@media (max-width: 1399.98px) { + .offcanvas-xxl.showing, .offcanvas-xxl.show:not(.hiding) { + transform: none; + } +} +@media (max-width: 1399.98px) { + .offcanvas-xxl.showing, .offcanvas-xxl.hiding, .offcanvas-xxl.show { + visibility: visible; + } +} +@media (min-width: 1400px) { + .offcanvas-xxl { + --bs-offcanvas-height: auto; + --bs-offcanvas-border-width: 0; + background-color: transparent !important; + } + .offcanvas-xxl .offcanvas-header { + display: none; + } + .offcanvas-xxl .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible; + background-color: transparent !important; + } +} + +.offcanvas { + position: fixed; + bottom: 0; + z-index: var(--bs-offcanvas-zindex); + display: flex; + flex-direction: column; + max-width: 100%; + color: var(--bs-offcanvas-color); + visibility: hidden; + background-color: var(--bs-offcanvas-bg); + background-clip: padding-box; + outline: 0; + transition: var(--bs-offcanvas-transition); +} +@media (prefers-reduced-motion: reduce) { + .offcanvas { + transition: none; + } +} +.offcanvas.offcanvas-start { + top: 0; + left: 0; + width: var(--bs-offcanvas-width); + border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(-100%); +} +.offcanvas.offcanvas-end { + top: 0; + right: 0; + width: var(--bs-offcanvas-width); + border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateX(100%); +} +.offcanvas.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(-100%); +} +.offcanvas.offcanvas-bottom { + right: 0; + left: 0; + height: var(--bs-offcanvas-height); + max-height: 100%; + border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); + transform: translateY(100%); +} +.offcanvas.showing, .offcanvas.show:not(.hiding) { + transform: none; +} +.offcanvas.showing, .offcanvas.hiding, .offcanvas.show { + visibility: visible; +} + +.offcanvas-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 1040; + width: 100vw; + height: 100vh; + background-color: #000; +} +.offcanvas-backdrop.fade { + opacity: 0; +} +.offcanvas-backdrop.show { + opacity: 0.5; +} + +.offcanvas-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); +} +.offcanvas-header .btn-close { + padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); + margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y)); + margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x)); + margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y)); +} + +.offcanvas-title { + margin-bottom: 0; + line-height: var(--bs-offcanvas-title-line-height); +} + +.offcanvas-body { + flex-grow: 1; + padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); + overflow-y: auto; +} + +.placeholder { + display: inline-block; + min-height: 1em; + vertical-align: middle; + cursor: wait; + background-color: currentcolor; + opacity: 0.5; +} +.placeholder.btn::before { + display: inline-block; + content: ""; +} + +.placeholder-xs { + min-height: 0.6em; +} + +.placeholder-sm { + min-height: 0.8em; +} + +.placeholder-lg { + min-height: 1.2em; +} + +.placeholder-glow .placeholder { + animation: placeholder-glow 2s ease-in-out infinite; +} + +@keyframes placeholder-glow { + 50% { + opacity: 0.2; + } +} +.placeholder-wave { + -webkit-mask-image: linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%); + mask-image: linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%); + -webkit-mask-size: 200% 100%; + mask-size: 200% 100%; + animation: placeholder-wave 2s linear infinite; +} + +@keyframes placeholder-wave { + 100% { + -webkit-mask-position: -200% 0%; + mask-position: -200% 0%; + } +} +.clearfix::after { + display: block; + clear: both; + content: ""; +} + +.text-bg-primary { + color: #fff !important; + background-color: RGBA(13, 110, 253, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-secondary { + color: #fff !important; + background-color: RGBA(108, 117, 125, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-success { + color: #fff !important; + background-color: RGBA(25, 135, 84, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-info { + color: #000 !important; + background-color: RGBA(13, 202, 240, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-warning { + color: #000 !important; + background-color: RGBA(255, 193, 7, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-danger { + color: #fff !important; + background-color: RGBA(220, 53, 69, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-light { + color: #000 !important; + background-color: RGBA(248, 249, 250, var(--bs-bg-opacity, 1)) !important; +} + +.text-bg-dark { + color: #fff !important; + background-color: RGBA(33, 37, 41, var(--bs-bg-opacity, 1)) !important; +} + +.link-primary { + color: RGBA(var(--bs-primary-rgb, var(--bs-link-opacity, 1))); + -webkit-text-decoration-color: RGBA(var(--bs-primary-rgb), var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(var(--bs-primary-rgb), var(--bs-link-underline-opacity, 1)); +} +.link-primary:hover, .link-primary:focus { + color: RGBA(10, 88, 202, var(--bs-link-opacity, 1)); + -webkit-text-decoration-color: RGBA(10, 88, 202, var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(10, 88, 202, var(--bs-link-underline-opacity, 1)); +} + +.link-secondary { + color: RGBA(var(--bs-secondary-rgb, var(--bs-link-opacity, 1))); + -webkit-text-decoration-color: RGBA(var(--bs-secondary-rgb), var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(var(--bs-secondary-rgb), var(--bs-link-underline-opacity, 1)); +} +.link-secondary:hover, .link-secondary:focus { + color: RGBA(86, 94, 100, var(--bs-link-opacity, 1)); + -webkit-text-decoration-color: RGBA(86, 94, 100, var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(86, 94, 100, var(--bs-link-underline-opacity, 1)); +} + +.link-success { + color: RGBA(var(--bs-success-rgb, var(--bs-link-opacity, 1))); + -webkit-text-decoration-color: RGBA(var(--bs-success-rgb), var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(var(--bs-success-rgb), var(--bs-link-underline-opacity, 1)); +} +.link-success:hover, .link-success:focus { + color: RGBA(20, 108, 67, var(--bs-link-opacity, 1)); + -webkit-text-decoration-color: RGBA(20, 108, 67, var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(20, 108, 67, var(--bs-link-underline-opacity, 1)); +} + +.link-info { + color: RGBA(var(--bs-info-rgb, var(--bs-link-opacity, 1))); + -webkit-text-decoration-color: RGBA(var(--bs-info-rgb), var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(var(--bs-info-rgb), var(--bs-link-underline-opacity, 1)); +} +.link-info:hover, .link-info:focus { + color: RGBA(61, 213, 243, var(--bs-link-opacity, 1)); + -webkit-text-decoration-color: RGBA(61, 213, 243, var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(61, 213, 243, var(--bs-link-underline-opacity, 1)); +} + +.link-warning { + color: RGBA(var(--bs-warning-rgb, var(--bs-link-opacity, 1))); + -webkit-text-decoration-color: RGBA(var(--bs-warning-rgb), var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(var(--bs-warning-rgb), var(--bs-link-underline-opacity, 1)); +} +.link-warning:hover, .link-warning:focus { + color: RGBA(255, 205, 57, var(--bs-link-opacity, 1)); + -webkit-text-decoration-color: RGBA(255, 205, 57, var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(255, 205, 57, var(--bs-link-underline-opacity, 1)); +} + +.link-danger { + color: RGBA(var(--bs-danger-rgb, var(--bs-link-opacity, 1))); + -webkit-text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)); +} +.link-danger:hover, .link-danger:focus { + color: RGBA(176, 42, 55, var(--bs-link-opacity, 1)); + -webkit-text-decoration-color: RGBA(176, 42, 55, var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(176, 42, 55, var(--bs-link-underline-opacity, 1)); +} + +.link-light { + color: RGBA(var(--bs-light-rgb, var(--bs-link-opacity, 1))); + -webkit-text-decoration-color: RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)); +} +.link-light:hover, .link-light:focus { + color: RGBA(249, 250, 251, var(--bs-link-opacity, 1)); + -webkit-text-decoration-color: RGBA(249, 250, 251, var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(249, 250, 251, var(--bs-link-underline-opacity, 1)); +} + +.link-dark { + color: RGBA(var(--bs-dark-rgb, var(--bs-link-opacity, 1))); + -webkit-text-decoration-color: RGBA(var(--bs-dark-rgb), var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(var(--bs-dark-rgb), var(--bs-link-underline-opacity, 1)); +} +.link-dark:hover, .link-dark:focus { + color: RGBA(26, 30, 33, var(--bs-link-opacity, 1)); + -webkit-text-decoration-color: RGBA(26, 30, 33, var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(26, 30, 33, var(--bs-link-underline-opacity, 1)); +} + +.link-body-emphasis { + color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 1)); + -webkit-text-decoration-color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 1)); + text-decoration-color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 1)); +} +.link-body-emphasis:hover, .link-body-emphasis:focus { + color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 0.75)); + -webkit-text-decoration-color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 0.75)); + text-decoration-color: RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 0.75)); +} + +.focus-ring:focus { + outline: 0; + box-shadow: var(--bs-focus-ring-x, 0) var(--bs-focus-ring-y, 0) var(--bs-focus-ring-blur, 0) var(--bs-focus-ring-width) var(--bs-focus-ring-color); +} + +.icon-link { + display: inline-flex; + gap: 0.375rem; + align-items: center; + -webkit-text-decoration-color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 0.5)); + text-decoration-color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 0.5)); + text-underline-offset: 0.25em; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} +.icon-link > .bi { + flex-shrink: 0; + width: 1em; + height: 1em; + fill: currentcolor; + transition: 0.2s ease-in-out transform; +} +@media (prefers-reduced-motion: reduce) { + .icon-link > .bi { + transition: none; + } +} + +.icon-link-hover:hover > .bi, .icon-link-hover:focus-visible > .bi { + transform: var(--bs-icon-link-transform, translate3d(0.25em, 0, 0)); +} + +.ratio { + position: relative; + width: 100%; +} +.ratio::before { + display: block; + padding-top: var(--bs-aspect-ratio); + content: ""; +} +.ratio > * { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.ratio-1x1 { + --bs-aspect-ratio: 100%; +} + +.ratio-4x3 { + --bs-aspect-ratio: 75%; +} + +.ratio-16x9 { + --bs-aspect-ratio: 56.25%; +} + +.ratio-21x9 { + --bs-aspect-ratio: 42.8571428571%; +} + +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} + +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} + +.sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; +} + +.sticky-bottom { + position: -webkit-sticky; + position: sticky; + bottom: 0; + z-index: 1020; +} + +@media (min-width: 576px) { + .sticky-sm-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-sm-bottom { + position: -webkit-sticky; + position: sticky; + bottom: 0; + z-index: 1020; + } +} +@media (min-width: 768px) { + .sticky-md-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-md-bottom { + position: -webkit-sticky; + position: sticky; + bottom: 0; + z-index: 1020; + } +} +@media (min-width: 992px) { + .sticky-lg-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-lg-bottom { + position: -webkit-sticky; + position: sticky; + bottom: 0; + z-index: 1020; + } +} +@media (min-width: 1200px) { + .sticky-xl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-xl-bottom { + position: -webkit-sticky; + position: sticky; + bottom: 0; + z-index: 1020; + } +} +@media (min-width: 1400px) { + .sticky-xxl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } + .sticky-xxl-bottom { + position: -webkit-sticky; + position: sticky; + bottom: 0; + z-index: 1020; + } +} +.hstack { + display: flex; + flex-direction: row; + align-items: center; + align-self: stretch; +} + +.vstack { + display: flex; + flex: 1 1 auto; + flex-direction: column; + align-self: stretch; +} + +.visually-hidden, +.visually-hidden-focusable:not(:focus):not(:focus-within) { + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + white-space: nowrap !important; + border: 0 !important; +} +.visually-hidden:not(caption), +.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption) { + position: absolute !important; +} + +.stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + content: ""; +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.vr { + display: inline-block; + align-self: stretch; + width: 1px; + min-height: 1em; + background-color: currentcolor; + opacity: 0.25; +} + +.align-baseline { + vertical-align: baseline !important; +} + +.align-top { + vertical-align: top !important; +} + +.align-middle { + vertical-align: middle !important; +} + +.align-bottom { + vertical-align: bottom !important; +} + +.align-text-bottom { + vertical-align: text-bottom !important; +} + +.align-text-top { + vertical-align: text-top !important; +} + +.float-start { + float: left !important; +} + +.float-end { + float: right !important; +} + +.float-none { + float: none !important; +} + +.object-fit-contain { + -o-object-fit: contain !important; + object-fit: contain !important; +} + +.object-fit-cover { + -o-object-fit: cover !important; + object-fit: cover !important; +} + +.object-fit-fill { + -o-object-fit: fill !important; + object-fit: fill !important; +} + +.object-fit-scale { + -o-object-fit: scale-down !important; + object-fit: scale-down !important; +} + +.object-fit-none { + -o-object-fit: none !important; + object-fit: none !important; +} + +.opacity-0 { + opacity: 0 !important; +} + +.opacity-25 { + opacity: 0.25 !important; +} + +.opacity-50 { + opacity: 0.5 !important; +} + +.opacity-75 { + opacity: 0.75 !important; +} + +.opacity-100 { + opacity: 1 !important; +} + +.overflow-auto { + overflow: auto !important; +} + +.overflow-hidden { + overflow: hidden !important; +} + +.overflow-visible { + overflow: visible !important; +} + +.overflow-scroll { + overflow: scroll !important; +} + +.overflow-x-auto { + overflow-x: auto !important; +} + +.overflow-x-hidden { + overflow-x: hidden !important; +} + +.overflow-x-visible { + overflow-x: visible !important; +} + +.overflow-x-scroll { + overflow-x: scroll !important; +} + +.overflow-y-auto { + overflow-y: auto !important; +} + +.overflow-y-hidden { + overflow-y: hidden !important; +} + +.overflow-y-visible { + overflow-y: visible !important; +} + +.overflow-y-scroll { + overflow-y: scroll !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-grid { + display: grid !important; +} + +.d-inline-grid { + display: inline-grid !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: flex !important; +} + +.d-inline-flex { + display: inline-flex !important; +} + +.d-none { + display: none !important; +} + +.shadow { + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +.shadow-sm { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; +} + +.shadow-none { + box-shadow: none !important; +} + +.focus-ring-primary { + --bs-focus-ring-color: rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity)); +} + +.focus-ring-secondary { + --bs-focus-ring-color: rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity)); +} + +.focus-ring-success { + --bs-focus-ring-color: rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity)); +} + +.focus-ring-info { + --bs-focus-ring-color: rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity)); +} + +.focus-ring-warning { + --bs-focus-ring-color: rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity)); +} + +.focus-ring-danger { + --bs-focus-ring-color: rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity)); +} + +.focus-ring-light { + --bs-focus-ring-color: rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity)); +} + +.focus-ring-dark { + --bs-focus-ring-color: rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity)); +} + +.position-static { + position: static !important; +} + +.position-relative { + position: relative !important; +} + +.position-absolute { + position: absolute !important; +} + +.position-fixed { + position: fixed !important; +} + +.position-sticky { + position: -webkit-sticky !important; + position: sticky !important; +} + +.top-0 { + top: 0 !important; +} + +.top-50 { + top: 50% !important; +} + +.top-100 { + top: 100% !important; +} + +.bottom-0 { + bottom: 0 !important; +} + +.bottom-50 { + bottom: 50% !important; +} + +.bottom-100 { + bottom: 100% !important; +} + +.start-0 { + left: 0 !important; +} + +.start-50 { + left: 50% !important; +} + +.start-100 { + left: 100% !important; +} + +.end-0 { + right: 0 !important; +} + +.end-50 { + right: 50% !important; +} + +.end-100 { + right: 100% !important; +} + +.translate-middle { + transform: translate(-50%, -50%) !important; +} + +.translate-middle-x { + transform: translateX(-50%) !important; +} + +.translate-middle-y { + transform: translateY(-50%) !important; +} + +.border { + border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; +} + +.border-0 { + border: 0 !important; +} + +.border-top { + border-top: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; +} + +.border-top-0 { + border-top: 0 !important; +} + +.border-end { + border-right: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; +} + +.border-end-0 { + border-right: 0 !important; +} + +.border-bottom { + border-bottom: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; +} + +.border-bottom-0 { + border-bottom: 0 !important; +} + +.border-start { + border-left: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; +} + +.border-start-0 { + border-left: 0 !important; +} + +.border-primary { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important; +} + +.border-secondary { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important; +} + +.border-success { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important; +} + +.border-info { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important; +} + +.border-warning { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important; +} + +.border-danger { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important; +} + +.border-light { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important; +} + +.border-dark { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important; +} + +.border-black { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-black-rgb), var(--bs-border-opacity)) !important; +} + +.border-white { + --bs-border-opacity: 1; + border-color: rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important; +} + +.border-primary-subtle { + border-color: var(--bs-primary-border-subtle) !important; +} + +.border-secondary-subtle { + border-color: var(--bs-secondary-border-subtle) !important; +} + +.border-success-subtle { + border-color: var(--bs-success-border-subtle) !important; +} + +.border-info-subtle { + border-color: var(--bs-info-border-subtle) !important; +} + +.border-warning-subtle { + border-color: var(--bs-warning-border-subtle) !important; +} + +.border-danger-subtle { + border-color: var(--bs-danger-border-subtle) !important; +} + +.border-light-subtle { + border-color: var(--bs-light-border-subtle) !important; +} + +.border-dark-subtle { + border-color: var(--bs-dark-border-subtle) !important; +} + +.border-1 { + border-width: 1px !important; +} + +.border-2 { + border-width: 2px !important; +} + +.border-3 { + border-width: 3px !important; +} + +.border-4 { + border-width: 4px !important; +} + +.border-5 { + border-width: 5px !important; +} + +.border-opacity-10 { + --bs-border-opacity: 0.1; +} + +.border-opacity-25 { + --bs-border-opacity: 0.25; +} + +.border-opacity-50 { + --bs-border-opacity: 0.5; +} + +.border-opacity-75 { + --bs-border-opacity: 0.75; +} + +.border-opacity-100 { + --bs-border-opacity: 1; +} + +.w-25 { + width: 25% !important; +} + +.w-50 { + width: 50% !important; +} + +.w-75 { + width: 75% !important; +} + +.w-100 { + width: 100% !important; +} + +.w-auto { + width: auto !important; +} + +.mw-100 { + max-width: 100% !important; +} + +.vw-100 { + width: 100vw !important; +} + +.min-vw-100 { + min-width: 100vw !important; +} + +.h-25 { + height: 25% !important; +} + +.h-50 { + height: 50% !important; +} + +.h-75 { + height: 75% !important; +} + +.h-100 { + height: 100% !important; +} + +.h-auto { + height: auto !important; +} + +.mh-100 { + max-height: 100% !important; +} + +.vh-100 { + height: 100vh !important; +} + +.min-vh-100 { + min-height: 100vh !important; +} + +.flex-fill { + flex: 1 1 auto !important; +} + +.flex-row { + flex-direction: row !important; +} + +.flex-column { + flex-direction: column !important; +} + +.flex-row-reverse { + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + flex-direction: column-reverse !important; +} + +.flex-grow-0 { + flex-grow: 0 !important; +} + +.flex-grow-1 { + flex-grow: 1 !important; +} + +.flex-shrink-0 { + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + flex-shrink: 1 !important; +} + +.flex-wrap { + flex-wrap: wrap !important; +} + +.flex-nowrap { + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + flex-wrap: wrap-reverse !important; +} + +.justify-content-start { + justify-content: flex-start !important; +} + +.justify-content-end { + justify-content: flex-end !important; +} + +.justify-content-center { + justify-content: center !important; +} + +.justify-content-between { + justify-content: space-between !important; +} + +.justify-content-around { + justify-content: space-around !important; +} + +.justify-content-evenly { + justify-content: space-evenly !important; +} + +.align-items-start { + align-items: flex-start !important; +} + +.align-items-end { + align-items: flex-end !important; +} + +.align-items-center { + align-items: center !important; +} + +.align-items-baseline { + align-items: baseline !important; +} + +.align-items-stretch { + align-items: stretch !important; +} + +.align-content-start { + align-content: flex-start !important; +} + +.align-content-end { + align-content: flex-end !important; +} + +.align-content-center { + align-content: center !important; +} + +.align-content-between { + align-content: space-between !important; +} + +.align-content-around { + align-content: space-around !important; +} + +.align-content-stretch { + align-content: stretch !important; +} + +.align-self-auto { + align-self: auto !important; +} + +.align-self-start { + align-self: flex-start !important; +} + +.align-self-end { + align-self: flex-end !important; +} + +.align-self-center { + align-self: center !important; +} + +.align-self-baseline { + align-self: baseline !important; +} + +.align-self-stretch { + align-self: stretch !important; +} + +.order-first { + order: -1 !important; +} + +.order-0 { + order: 0 !important; +} + +.order-1 { + order: 1 !important; +} + +.order-2 { + order: 2 !important; +} + +.order-3 { + order: 3 !important; +} + +.order-4 { + order: 4 !important; +} + +.order-5 { + order: 5 !important; +} + +.order-last { + order: 6 !important; +} + +.m-0 { + margin: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mx-0 { + margin-right: 0 !important; + margin-left: 0 !important; +} + +.mx-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; +} + +.mx-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; +} + +.mx-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; +} + +.mx-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; +} + +.mx-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; +} + +.mx-auto { + margin-right: auto !important; + margin-left: auto !important; +} + +.my-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.my-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; +} + +.my-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; +} + +.my-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; +} + +.my-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; +} + +.my-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; +} + +.my-auto { + margin-top: auto !important; + margin-bottom: auto !important; +} + +.mt-0 { + margin-top: 0 !important; +} + +.mt-1 { + margin-top: 0.25rem !important; +} + +.mt-2 { + margin-top: 0.5rem !important; +} + +.mt-3 { + margin-top: 1rem !important; +} + +.mt-4 { + margin-top: 1.5rem !important; +} + +.mt-5 { + margin-top: 3rem !important; +} + +.mt-auto { + margin-top: auto !important; +} + +.me-0 { + margin-right: 0 !important; +} + +.me-1 { + margin-right: 0.25rem !important; +} + +.me-2 { + margin-right: 0.5rem !important; +} + +.me-3 { + margin-right: 1rem !important; +} + +.me-4 { + margin-right: 1.5rem !important; +} + +.me-5 { + margin-right: 3rem !important; +} + +.me-auto { + margin-right: auto !important; +} + +.mb-0 { + margin-bottom: 0 !important; +} + +.mb-1 { + margin-bottom: 0.25rem !important; +} + +.mb-2 { + margin-bottom: 0.5rem !important; +} + +.mb-3 { + margin-bottom: 1rem !important; +} + +.mb-4 { + margin-bottom: 1.5rem !important; +} + +.mb-5 { + margin-bottom: 3rem !important; +} + +.mb-auto { + margin-bottom: auto !important; +} + +.ms-0 { + margin-left: 0 !important; +} + +.ms-1 { + margin-left: 0.25rem !important; +} + +.ms-2 { + margin-left: 0.5rem !important; +} + +.ms-3 { + margin-left: 1rem !important; +} + +.ms-4 { + margin-left: 1.5rem !important; +} + +.ms-5 { + margin-left: 3rem !important; +} + +.ms-auto { + margin-left: auto !important; +} + +.p-0 { + padding: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.px-0 { + padding-right: 0 !important; + padding-left: 0 !important; +} + +.px-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; +} + +.px-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; +} + +.px-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; +} + +.px-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; +} + +.px-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; +} + +.py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.py-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; +} + +.py-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; +} + +.py-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; +} + +.py-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; +} + +.py-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; +} + +.pt-0 { + padding-top: 0 !important; +} + +.pt-1 { + padding-top: 0.25rem !important; +} + +.pt-2 { + padding-top: 0.5rem !important; +} + +.pt-3 { + padding-top: 1rem !important; +} + +.pt-4 { + padding-top: 1.5rem !important; +} + +.pt-5 { + padding-top: 3rem !important; +} + +.pe-0 { + padding-right: 0 !important; +} + +.pe-1 { + padding-right: 0.25rem !important; +} + +.pe-2 { + padding-right: 0.5rem !important; +} + +.pe-3 { + padding-right: 1rem !important; +} + +.pe-4 { + padding-right: 1.5rem !important; +} + +.pe-5 { + padding-right: 3rem !important; +} + +.pb-0 { + padding-bottom: 0 !important; +} + +.pb-1 { + padding-bottom: 0.25rem !important; +} + +.pb-2 { + padding-bottom: 0.5rem !important; +} + +.pb-3 { + padding-bottom: 1rem !important; +} + +.pb-4 { + padding-bottom: 1.5rem !important; +} + +.pb-5 { + padding-bottom: 3rem !important; +} + +.ps-0 { + padding-left: 0 !important; +} + +.ps-1 { + padding-left: 0.25rem !important; +} + +.ps-2 { + padding-left: 0.5rem !important; +} + +.ps-3 { + padding-left: 1rem !important; +} + +.ps-4 { + padding-left: 1.5rem !important; +} + +.ps-5 { + padding-left: 3rem !important; +} + +.gap-0 { + gap: 0 !important; +} + +.gap-1 { + gap: 0.25rem !important; +} + +.gap-2 { + gap: 0.5rem !important; +} + +.gap-3 { + gap: 1rem !important; +} + +.gap-4 { + gap: 1.5rem !important; +} + +.gap-5 { + gap: 3rem !important; +} + +.row-gap-0 { + row-gap: 0 !important; +} + +.row-gap-1 { + row-gap: 0.25rem !important; +} + +.row-gap-2 { + row-gap: 0.5rem !important; +} + +.row-gap-3 { + row-gap: 1rem !important; +} + +.row-gap-4 { + row-gap: 1.5rem !important; +} + +.row-gap-5 { + row-gap: 3rem !important; +} + +.column-gap-0 { + -moz-column-gap: 0 !important; + column-gap: 0 !important; +} + +.column-gap-1 { + -moz-column-gap: 0.25rem !important; + column-gap: 0.25rem !important; +} + +.column-gap-2 { + -moz-column-gap: 0.5rem !important; + column-gap: 0.5rem !important; +} + +.column-gap-3 { + -moz-column-gap: 1rem !important; + column-gap: 1rem !important; +} + +.column-gap-4 { + -moz-column-gap: 1.5rem !important; + column-gap: 1.5rem !important; +} + +.column-gap-5 { + -moz-column-gap: 3rem !important; + column-gap: 3rem !important; +} + +.font-monospace { + font-family: var(--bs-font-monospace) !important; +} + +.fs-1 { + font-size: calc(1.375rem + 1.5vw) !important; +} + +.fs-2 { + font-size: calc(1.325rem + 0.9vw) !important; +} + +.fs-3 { + font-size: calc(1.3rem + 0.6vw) !important; +} + +.fs-4 { + font-size: calc(1.275rem + 0.3vw) !important; +} + +.fs-5 { + font-size: 1.25rem !important; +} + +.fs-6 { + font-size: 1rem !important; +} + +.fst-italic { + font-style: italic !important; +} + +.fst-normal { + font-style: normal !important; +} + +.fw-lighter { + font-weight: lighter !important; +} + +.fw-light { + font-weight: 300 !important; +} + +.fw-normal { + font-weight: 400 !important; +} + +.fw-medium { + font-weight: 500 !important; +} + +.fw-semibold { + font-weight: 600 !important; +} + +.fw-bold { + font-weight: 700 !important; +} + +.fw-bolder { + font-weight: bolder !important; +} + +.lh-1 { + line-height: 1 !important; +} + +.lh-sm { + line-height: 1.25 !important; +} + +.lh-base { + line-height: 1.5 !important; +} + +.lh-lg { + line-height: 2 !important; +} + +.text-start { + text-align: left !important; +} + +.text-end { + text-align: right !important; +} + +.text-center { + text-align: center !important; +} + +.text-decoration-none { + text-decoration: none !important; +} + +.text-decoration-underline { + text-decoration: underline !important; +} + +.text-decoration-line-through { + text-decoration: line-through !important; +} + +.text-lowercase { + text-transform: lowercase !important; +} + +.text-uppercase { + text-transform: uppercase !important; +} + +.text-capitalize { + text-transform: capitalize !important; +} + +.text-wrap { + white-space: normal !important; +} + +.text-nowrap { + white-space: nowrap !important; +} + +/* rtl:begin:remove */ +.text-break { + word-wrap: break-word !important; + word-break: break-word !important; +} + +/* rtl:end:remove */ +.text-primary { + --bs-text-opacity: 1; + color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; +} + +.text-secondary { + --bs-text-opacity: 1; + color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; +} + +.text-success { + --bs-text-opacity: 1; + color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; +} + +.text-info { + --bs-text-opacity: 1; + color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; +} + +.text-warning { + --bs-text-opacity: 1; + color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; +} + +.text-danger { + --bs-text-opacity: 1; + color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; +} + +.text-light { + --bs-text-opacity: 1; + color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; +} + +.text-dark { + --bs-text-opacity: 1; + color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; +} + +.text-black { + --bs-text-opacity: 1; + color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; +} + +.text-white { + --bs-text-opacity: 1; + color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; +} + +.text-body { + --bs-text-opacity: 1; + color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; +} + +.text-muted { + --bs-text-opacity: 1; + color: var(--bs-secondary-color) !important; +} + +.text-black-50 { + --bs-text-opacity: 1; + color: rgba(0, 0, 0, 0.5) !important; +} + +.text-white-50 { + --bs-text-opacity: 1; + color: rgba(255, 255, 255, 0.5) !important; +} + +.text-body-secondary { + --bs-text-opacity: 1; + color: var(--bs-secondary-color) !important; +} + +.text-body-tertiary { + --bs-text-opacity: 1; + color: var(--bs-tertiary-color) !important; +} + +.text-body-emphasis { + --bs-text-opacity: 1; + color: var(--bs-emphasis-color) !important; +} + +.text-reset { + --bs-text-opacity: 1; + color: inherit !important; +} + +.text-opacity-25 { + --bs-text-opacity: 0.25; +} + +.text-opacity-50 { + --bs-text-opacity: 0.5; +} + +.text-opacity-75 { + --bs-text-opacity: 0.75; +} + +.text-opacity-100 { + --bs-text-opacity: 1; +} + +.text-primary-emphasis { + color: var(--bs-primary-text-emphasis) !important; +} + +.text-secondary-emphasis { + color: var(--bs-secondary-text-emphasis) !important; +} + +.text-success-emphasis { + color: var(--bs-success-text-emphasis) !important; +} + +.text-info-emphasis { + color: var(--bs-info-text-emphasis) !important; +} + +.text-warning-emphasis { + color: var(--bs-warning-text-emphasis) !important; +} + +.text-danger-emphasis { + color: var(--bs-danger-text-emphasis) !important; +} + +.text-light-emphasis { + color: var(--bs-light-text-emphasis) !important; +} + +.text-dark-emphasis { + color: var(--bs-dark-text-emphasis) !important; +} + +.link-opacity-10 { + --bs-link-opacity: 0.1; +} + +.link-opacity-10-hover:hover { + --bs-link-opacity: 0.1; +} + +.link-opacity-25 { + --bs-link-opacity: 0.25; +} + +.link-opacity-25-hover:hover { + --bs-link-opacity: 0.25; +} + +.link-opacity-50 { + --bs-link-opacity: 0.5; +} + +.link-opacity-50-hover:hover { + --bs-link-opacity: 0.5; +} + +.link-opacity-75 { + --bs-link-opacity: 0.75; +} + +.link-opacity-75-hover:hover { + --bs-link-opacity: 0.75; +} + +.link-opacity-100 { + --bs-link-opacity: 1; +} + +.link-opacity-100-hover:hover { + --bs-link-opacity: 1; +} + +.link-offset-1 { + text-underline-offset: 0.125em !important; +} + +.link-offset-1-hover:hover { + text-underline-offset: 0.125em !important; +} + +.link-offset-2 { + text-underline-offset: 0.25em !important; +} + +.link-offset-2-hover:hover { + text-underline-offset: 0.25em !important; +} + +.link-offset-3 { + text-underline-offset: 0.375em !important; +} + +.link-offset-3-hover:hover { + text-underline-offset: 0.375em !important; +} + +.link-underline-primary { + --bs-link-underline-opacity: 1; + -webkit-text-decoration-color: rgba(var(--bs-primary-rgb), var(--bs-link-underline-opacity)) !important; + text-decoration-color: rgba(var(--bs-primary-rgb), var(--bs-link-underline-opacity)) !important; +} + +.link-underline-secondary { + --bs-link-underline-opacity: 1; + -webkit-text-decoration-color: rgba(var(--bs-secondary-rgb), var(--bs-link-underline-opacity)) !important; + text-decoration-color: rgba(var(--bs-secondary-rgb), var(--bs-link-underline-opacity)) !important; +} + +.link-underline-success { + --bs-link-underline-opacity: 1; + -webkit-text-decoration-color: rgba(var(--bs-success-rgb), var(--bs-link-underline-opacity)) !important; + text-decoration-color: rgba(var(--bs-success-rgb), var(--bs-link-underline-opacity)) !important; +} + +.link-underline-info { + --bs-link-underline-opacity: 1; + -webkit-text-decoration-color: rgba(var(--bs-info-rgb), var(--bs-link-underline-opacity)) !important; + text-decoration-color: rgba(var(--bs-info-rgb), var(--bs-link-underline-opacity)) !important; +} + +.link-underline-warning { + --bs-link-underline-opacity: 1; + -webkit-text-decoration-color: rgba(var(--bs-warning-rgb), var(--bs-link-underline-opacity)) !important; + text-decoration-color: rgba(var(--bs-warning-rgb), var(--bs-link-underline-opacity)) !important; +} + +.link-underline-danger { + --bs-link-underline-opacity: 1; + -webkit-text-decoration-color: rgba(var(--bs-danger-rgb), var(--bs-link-underline-opacity)) !important; + text-decoration-color: rgba(var(--bs-danger-rgb), var(--bs-link-underline-opacity)) !important; +} + +.link-underline-light { + --bs-link-underline-opacity: 1; + -webkit-text-decoration-color: rgba(var(--bs-light-rgb), var(--bs-link-underline-opacity)) !important; + text-decoration-color: rgba(var(--bs-light-rgb), var(--bs-link-underline-opacity)) !important; +} + +.link-underline-dark { + --bs-link-underline-opacity: 1; + -webkit-text-decoration-color: rgba(var(--bs-dark-rgb), var(--bs-link-underline-opacity)) !important; + text-decoration-color: rgba(var(--bs-dark-rgb), var(--bs-link-underline-opacity)) !important; +} + +.link-underline { + --bs-link-underline-opacity: 1; + -webkit-text-decoration-color: rgba(var(--bs-link-color-rgb), var(--bs-link-underline-opacity, 1)) !important; + text-decoration-color: rgba(var(--bs-link-color-rgb), var(--bs-link-underline-opacity, 1)) !important; +} + +.link-underline-opacity-0 { + --bs-link-underline-opacity: 0; +} + +.link-underline-opacity-0-hover:hover { + --bs-link-underline-opacity: 0; +} + +.link-underline-opacity-10 { + --bs-link-underline-opacity: 0.1; +} + +.link-underline-opacity-10-hover:hover { + --bs-link-underline-opacity: 0.1; +} + +.link-underline-opacity-25 { + --bs-link-underline-opacity: 0.25; +} + +.link-underline-opacity-25-hover:hover { + --bs-link-underline-opacity: 0.25; +} + +.link-underline-opacity-50 { + --bs-link-underline-opacity: 0.5; +} + +.link-underline-opacity-50-hover:hover { + --bs-link-underline-opacity: 0.5; +} + +.link-underline-opacity-75 { + --bs-link-underline-opacity: 0.75; +} + +.link-underline-opacity-75-hover:hover { + --bs-link-underline-opacity: 0.75; +} + +.link-underline-opacity-100 { + --bs-link-underline-opacity: 1; +} + +.link-underline-opacity-100-hover:hover { + --bs-link-underline-opacity: 1; +} + +.bg-primary { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-secondary { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-success { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-info { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-warning { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-danger { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-light { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-dark { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-black { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-white { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-body { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-transparent { + --bs-bg-opacity: 1; + background-color: transparent !important; +} + +.bg-body-secondary { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-secondary-bg-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-body-tertiary { + --bs-bg-opacity: 1; + background-color: rgba(var(--bs-tertiary-bg-rgb), var(--bs-bg-opacity)) !important; +} + +.bg-opacity-10 { + --bs-bg-opacity: 0.1; +} + +.bg-opacity-25 { + --bs-bg-opacity: 0.25; +} + +.bg-opacity-50 { + --bs-bg-opacity: 0.5; +} + +.bg-opacity-75 { + --bs-bg-opacity: 0.75; +} + +.bg-opacity-100 { + --bs-bg-opacity: 1; +} + +.bg-primary-subtle { + background-color: var(--bs-primary-bg-subtle) !important; +} + +.bg-secondary-subtle { + background-color: var(--bs-secondary-bg-subtle) !important; +} + +.bg-success-subtle { + background-color: var(--bs-success-bg-subtle) !important; +} + +.bg-info-subtle { + background-color: var(--bs-info-bg-subtle) !important; +} + +.bg-warning-subtle { + background-color: var(--bs-warning-bg-subtle) !important; +} + +.bg-danger-subtle { + background-color: var(--bs-danger-bg-subtle) !important; +} + +.bg-light-subtle { + background-color: var(--bs-light-bg-subtle) !important; +} + +.bg-dark-subtle { + background-color: var(--bs-dark-bg-subtle) !important; +} + +.bg-gradient { + background-image: var(--bs-gradient) !important; +} + +.user-select-all { + -webkit-user-select: all !important; + -moz-user-select: all !important; + user-select: all !important; +} + +.user-select-auto { + -webkit-user-select: auto !important; + -moz-user-select: auto !important; + user-select: auto !important; +} + +.user-select-none { + -webkit-user-select: none !important; + -moz-user-select: none !important; + user-select: none !important; +} + +.pe-none { + pointer-events: none !important; +} + +.pe-auto { + pointer-events: auto !important; +} + +.rounded { + border-radius: var(--bs-border-radius) !important; +} + +.rounded-0 { + border-radius: 0 !important; +} + +.rounded-1 { + border-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-2 { + border-radius: var(--bs-border-radius) !important; +} + +.rounded-3 { + border-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-4 { + border-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-5 { + border-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-circle { + border-radius: 50% !important; +} + +.rounded-pill { + border-radius: var(--bs-border-radius-pill) !important; +} + +.rounded-top { + border-top-left-radius: var(--bs-border-radius) !important; + border-top-right-radius: var(--bs-border-radius) !important; +} + +.rounded-top-0 { + border-top-left-radius: 0 !important; + border-top-right-radius: 0 !important; +} + +.rounded-top-1 { + border-top-left-radius: var(--bs-border-radius-sm) !important; + border-top-right-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-top-2 { + border-top-left-radius: var(--bs-border-radius) !important; + border-top-right-radius: var(--bs-border-radius) !important; +} + +.rounded-top-3 { + border-top-left-radius: var(--bs-border-radius-lg) !important; + border-top-right-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-top-4 { + border-top-left-radius: var(--bs-border-radius-xl) !important; + border-top-right-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-top-5 { + border-top-left-radius: var(--bs-border-radius-xxl) !important; + border-top-right-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-top-circle { + border-top-left-radius: 50% !important; + border-top-right-radius: 50% !important; +} + +.rounded-top-pill { + border-top-left-radius: var(--bs-border-radius-pill) !important; + border-top-right-radius: var(--bs-border-radius-pill) !important; +} + +.rounded-end { + border-top-right-radius: var(--bs-border-radius) !important; + border-bottom-right-radius: var(--bs-border-radius) !important; +} + +.rounded-end-0 { + border-top-right-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +.rounded-end-1 { + border-top-right-radius: var(--bs-border-radius-sm) !important; + border-bottom-right-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-end-2 { + border-top-right-radius: var(--bs-border-radius) !important; + border-bottom-right-radius: var(--bs-border-radius) !important; +} + +.rounded-end-3 { + border-top-right-radius: var(--bs-border-radius-lg) !important; + border-bottom-right-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-end-4 { + border-top-right-radius: var(--bs-border-radius-xl) !important; + border-bottom-right-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-end-5 { + border-top-right-radius: var(--bs-border-radius-xxl) !important; + border-bottom-right-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-end-circle { + border-top-right-radius: 50% !important; + border-bottom-right-radius: 50% !important; +} + +.rounded-end-pill { + border-top-right-radius: var(--bs-border-radius-pill) !important; + border-bottom-right-radius: var(--bs-border-radius-pill) !important; +} + +.rounded-bottom { + border-bottom-right-radius: var(--bs-border-radius) !important; + border-bottom-left-radius: var(--bs-border-radius) !important; +} + +.rounded-bottom-0 { + border-bottom-right-radius: 0 !important; + border-bottom-left-radius: 0 !important; +} + +.rounded-bottom-1 { + border-bottom-right-radius: var(--bs-border-radius-sm) !important; + border-bottom-left-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-bottom-2 { + border-bottom-right-radius: var(--bs-border-radius) !important; + border-bottom-left-radius: var(--bs-border-radius) !important; +} + +.rounded-bottom-3 { + border-bottom-right-radius: var(--bs-border-radius-lg) !important; + border-bottom-left-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-bottom-4 { + border-bottom-right-radius: var(--bs-border-radius-xl) !important; + border-bottom-left-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-bottom-5 { + border-bottom-right-radius: var(--bs-border-radius-xxl) !important; + border-bottom-left-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-bottom-circle { + border-bottom-right-radius: 50% !important; + border-bottom-left-radius: 50% !important; +} + +.rounded-bottom-pill { + border-bottom-right-radius: var(--bs-border-radius-pill) !important; + border-bottom-left-radius: var(--bs-border-radius-pill) !important; +} + +.rounded-start { + border-bottom-left-radius: var(--bs-border-radius) !important; + border-top-left-radius: var(--bs-border-radius) !important; +} + +.rounded-start-0 { + border-bottom-left-radius: 0 !important; + border-top-left-radius: 0 !important; +} + +.rounded-start-1 { + border-bottom-left-radius: var(--bs-border-radius-sm) !important; + border-top-left-radius: var(--bs-border-radius-sm) !important; +} + +.rounded-start-2 { + border-bottom-left-radius: var(--bs-border-radius) !important; + border-top-left-radius: var(--bs-border-radius) !important; +} + +.rounded-start-3 { + border-bottom-left-radius: var(--bs-border-radius-lg) !important; + border-top-left-radius: var(--bs-border-radius-lg) !important; +} + +.rounded-start-4 { + border-bottom-left-radius: var(--bs-border-radius-xl) !important; + border-top-left-radius: var(--bs-border-radius-xl) !important; +} + +.rounded-start-5 { + border-bottom-left-radius: var(--bs-border-radius-xxl) !important; + border-top-left-radius: var(--bs-border-radius-xxl) !important; +} + +.rounded-start-circle { + border-bottom-left-radius: 50% !important; + border-top-left-radius: 50% !important; +} + +.rounded-start-pill { + border-bottom-left-radius: var(--bs-border-radius-pill) !important; + border-top-left-radius: var(--bs-border-radius-pill) !important; +} + +.visible { + visibility: visible !important; +} + +.invisible { + visibility: hidden !important; +} + +.z-n1 { + z-index: -1 !important; +} + +.z-0 { + z-index: 0 !important; +} + +.z-1 { + z-index: 1 !important; +} + +.z-2 { + z-index: 2 !important; +} + +.z-3 { + z-index: 3 !important; +} + +@media (min-width: 576px) { + .float-sm-start { + float: left !important; + } + .float-sm-end { + float: right !important; + } + .float-sm-none { + float: none !important; + } + .object-fit-sm-contain { + -o-object-fit: contain !important; + object-fit: contain !important; + } + .object-fit-sm-cover { + -o-object-fit: cover !important; + object-fit: cover !important; + } + .object-fit-sm-fill { + -o-object-fit: fill !important; + object-fit: fill !important; + } + .object-fit-sm-scale { + -o-object-fit: scale-down !important; + object-fit: scale-down !important; + } + .object-fit-sm-none { + -o-object-fit: none !important; + object-fit: none !important; + } + .d-sm-inline { + display: inline !important; + } + .d-sm-inline-block { + display: inline-block !important; + } + .d-sm-block { + display: block !important; + } + .d-sm-grid { + display: grid !important; + } + .d-sm-inline-grid { + display: inline-grid !important; + } + .d-sm-table { + display: table !important; + } + .d-sm-table-row { + display: table-row !important; + } + .d-sm-table-cell { + display: table-cell !important; + } + .d-sm-flex { + display: flex !important; + } + .d-sm-inline-flex { + display: inline-flex !important; + } + .d-sm-none { + display: none !important; + } + .flex-sm-fill { + flex: 1 1 auto !important; + } + .flex-sm-row { + flex-direction: row !important; + } + .flex-sm-column { + flex-direction: column !important; + } + .flex-sm-row-reverse { + flex-direction: row-reverse !important; + } + .flex-sm-column-reverse { + flex-direction: column-reverse !important; + } + .flex-sm-grow-0 { + flex-grow: 0 !important; + } + .flex-sm-grow-1 { + flex-grow: 1 !important; + } + .flex-sm-shrink-0 { + flex-shrink: 0 !important; + } + .flex-sm-shrink-1 { + flex-shrink: 1 !important; + } + .flex-sm-wrap { + flex-wrap: wrap !important; + } + .flex-sm-nowrap { + flex-wrap: nowrap !important; + } + .flex-sm-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-sm-start { + justify-content: flex-start !important; + } + .justify-content-sm-end { + justify-content: flex-end !important; + } + .justify-content-sm-center { + justify-content: center !important; + } + .justify-content-sm-between { + justify-content: space-between !important; + } + .justify-content-sm-around { + justify-content: space-around !important; + } + .justify-content-sm-evenly { + justify-content: space-evenly !important; + } + .align-items-sm-start { + align-items: flex-start !important; + } + .align-items-sm-end { + align-items: flex-end !important; + } + .align-items-sm-center { + align-items: center !important; + } + .align-items-sm-baseline { + align-items: baseline !important; + } + .align-items-sm-stretch { + align-items: stretch !important; + } + .align-content-sm-start { + align-content: flex-start !important; + } + .align-content-sm-end { + align-content: flex-end !important; + } + .align-content-sm-center { + align-content: center !important; + } + .align-content-sm-between { + align-content: space-between !important; + } + .align-content-sm-around { + align-content: space-around !important; + } + .align-content-sm-stretch { + align-content: stretch !important; + } + .align-self-sm-auto { + align-self: auto !important; + } + .align-self-sm-start { + align-self: flex-start !important; + } + .align-self-sm-end { + align-self: flex-end !important; + } + .align-self-sm-center { + align-self: center !important; + } + .align-self-sm-baseline { + align-self: baseline !important; + } + .align-self-sm-stretch { + align-self: stretch !important; + } + .order-sm-first { + order: -1 !important; + } + .order-sm-0 { + order: 0 !important; + } + .order-sm-1 { + order: 1 !important; + } + .order-sm-2 { + order: 2 !important; + } + .order-sm-3 { + order: 3 !important; + } + .order-sm-4 { + order: 4 !important; + } + .order-sm-5 { + order: 5 !important; + } + .order-sm-last { + order: 6 !important; + } + .m-sm-0 { + margin: 0 !important; + } + .m-sm-1 { + margin: 0.25rem !important; + } + .m-sm-2 { + margin: 0.5rem !important; + } + .m-sm-3 { + margin: 1rem !important; + } + .m-sm-4 { + margin: 1.5rem !important; + } + .m-sm-5 { + margin: 3rem !important; + } + .m-sm-auto { + margin: auto !important; + } + .mx-sm-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-sm-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-sm-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-sm-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-sm-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-sm-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-sm-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-sm-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-sm-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-sm-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-sm-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-sm-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-sm-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-sm-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-sm-0 { + margin-top: 0 !important; + } + .mt-sm-1 { + margin-top: 0.25rem !important; + } + .mt-sm-2 { + margin-top: 0.5rem !important; + } + .mt-sm-3 { + margin-top: 1rem !important; + } + .mt-sm-4 { + margin-top: 1.5rem !important; + } + .mt-sm-5 { + margin-top: 3rem !important; + } + .mt-sm-auto { + margin-top: auto !important; + } + .me-sm-0 { + margin-right: 0 !important; + } + .me-sm-1 { + margin-right: 0.25rem !important; + } + .me-sm-2 { + margin-right: 0.5rem !important; + } + .me-sm-3 { + margin-right: 1rem !important; + } + .me-sm-4 { + margin-right: 1.5rem !important; + } + .me-sm-5 { + margin-right: 3rem !important; + } + .me-sm-auto { + margin-right: auto !important; + } + .mb-sm-0 { + margin-bottom: 0 !important; + } + .mb-sm-1 { + margin-bottom: 0.25rem !important; + } + .mb-sm-2 { + margin-bottom: 0.5rem !important; + } + .mb-sm-3 { + margin-bottom: 1rem !important; + } + .mb-sm-4 { + margin-bottom: 1.5rem !important; + } + .mb-sm-5 { + margin-bottom: 3rem !important; + } + .mb-sm-auto { + margin-bottom: auto !important; + } + .ms-sm-0 { + margin-left: 0 !important; + } + .ms-sm-1 { + margin-left: 0.25rem !important; + } + .ms-sm-2 { + margin-left: 0.5rem !important; + } + .ms-sm-3 { + margin-left: 1rem !important; + } + .ms-sm-4 { + margin-left: 1.5rem !important; + } + .ms-sm-5 { + margin-left: 3rem !important; + } + .ms-sm-auto { + margin-left: auto !important; + } + .p-sm-0 { + padding: 0 !important; + } + .p-sm-1 { + padding: 0.25rem !important; + } + .p-sm-2 { + padding: 0.5rem !important; + } + .p-sm-3 { + padding: 1rem !important; + } + .p-sm-4 { + padding: 1.5rem !important; + } + .p-sm-5 { + padding: 3rem !important; + } + .px-sm-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-sm-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-sm-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-sm-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-sm-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-sm-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-sm-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-sm-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-sm-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-sm-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-sm-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-sm-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-sm-0 { + padding-top: 0 !important; + } + .pt-sm-1 { + padding-top: 0.25rem !important; + } + .pt-sm-2 { + padding-top: 0.5rem !important; + } + .pt-sm-3 { + padding-top: 1rem !important; + } + .pt-sm-4 { + padding-top: 1.5rem !important; + } + .pt-sm-5 { + padding-top: 3rem !important; + } + .pe-sm-0 { + padding-right: 0 !important; + } + .pe-sm-1 { + padding-right: 0.25rem !important; + } + .pe-sm-2 { + padding-right: 0.5rem !important; + } + .pe-sm-3 { + padding-right: 1rem !important; + } + .pe-sm-4 { + padding-right: 1.5rem !important; + } + .pe-sm-5 { + padding-right: 3rem !important; + } + .pb-sm-0 { + padding-bottom: 0 !important; + } + .pb-sm-1 { + padding-bottom: 0.25rem !important; + } + .pb-sm-2 { + padding-bottom: 0.5rem !important; + } + .pb-sm-3 { + padding-bottom: 1rem !important; + } + .pb-sm-4 { + padding-bottom: 1.5rem !important; + } + .pb-sm-5 { + padding-bottom: 3rem !important; + } + .ps-sm-0 { + padding-left: 0 !important; + } + .ps-sm-1 { + padding-left: 0.25rem !important; + } + .ps-sm-2 { + padding-left: 0.5rem !important; + } + .ps-sm-3 { + padding-left: 1rem !important; + } + .ps-sm-4 { + padding-left: 1.5rem !important; + } + .ps-sm-5 { + padding-left: 3rem !important; + } + .gap-sm-0 { + gap: 0 !important; + } + .gap-sm-1 { + gap: 0.25rem !important; + } + .gap-sm-2 { + gap: 0.5rem !important; + } + .gap-sm-3 { + gap: 1rem !important; + } + .gap-sm-4 { + gap: 1.5rem !important; + } + .gap-sm-5 { + gap: 3rem !important; + } + .row-gap-sm-0 { + row-gap: 0 !important; + } + .row-gap-sm-1 { + row-gap: 0.25rem !important; + } + .row-gap-sm-2 { + row-gap: 0.5rem !important; + } + .row-gap-sm-3 { + row-gap: 1rem !important; + } + .row-gap-sm-4 { + row-gap: 1.5rem !important; + } + .row-gap-sm-5 { + row-gap: 3rem !important; + } + .column-gap-sm-0 { + -moz-column-gap: 0 !important; + column-gap: 0 !important; + } + .column-gap-sm-1 { + -moz-column-gap: 0.25rem !important; + column-gap: 0.25rem !important; + } + .column-gap-sm-2 { + -moz-column-gap: 0.5rem !important; + column-gap: 0.5rem !important; + } + .column-gap-sm-3 { + -moz-column-gap: 1rem !important; + column-gap: 1rem !important; + } + .column-gap-sm-4 { + -moz-column-gap: 1.5rem !important; + column-gap: 1.5rem !important; + } + .column-gap-sm-5 { + -moz-column-gap: 3rem !important; + column-gap: 3rem !important; + } + .text-sm-start { + text-align: left !important; + } + .text-sm-end { + text-align: right !important; + } + .text-sm-center { + text-align: center !important; + } +} +@media (min-width: 768px) { + .float-md-start { + float: left !important; + } + .float-md-end { + float: right !important; + } + .float-md-none { + float: none !important; + } + .object-fit-md-contain { + -o-object-fit: contain !important; + object-fit: contain !important; + } + .object-fit-md-cover { + -o-object-fit: cover !important; + object-fit: cover !important; + } + .object-fit-md-fill { + -o-object-fit: fill !important; + object-fit: fill !important; + } + .object-fit-md-scale { + -o-object-fit: scale-down !important; + object-fit: scale-down !important; + } + .object-fit-md-none { + -o-object-fit: none !important; + object-fit: none !important; + } + .d-md-inline { + display: inline !important; + } + .d-md-inline-block { + display: inline-block !important; + } + .d-md-block { + display: block !important; + } + .d-md-grid { + display: grid !important; + } + .d-md-inline-grid { + display: inline-grid !important; + } + .d-md-table { + display: table !important; + } + .d-md-table-row { + display: table-row !important; + } + .d-md-table-cell { + display: table-cell !important; + } + .d-md-flex { + display: flex !important; + } + .d-md-inline-flex { + display: inline-flex !important; + } + .d-md-none { + display: none !important; + } + .flex-md-fill { + flex: 1 1 auto !important; + } + .flex-md-row { + flex-direction: row !important; + } + .flex-md-column { + flex-direction: column !important; + } + .flex-md-row-reverse { + flex-direction: row-reverse !important; + } + .flex-md-column-reverse { + flex-direction: column-reverse !important; + } + .flex-md-grow-0 { + flex-grow: 0 !important; + } + .flex-md-grow-1 { + flex-grow: 1 !important; + } + .flex-md-shrink-0 { + flex-shrink: 0 !important; + } + .flex-md-shrink-1 { + flex-shrink: 1 !important; + } + .flex-md-wrap { + flex-wrap: wrap !important; + } + .flex-md-nowrap { + flex-wrap: nowrap !important; + } + .flex-md-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-md-start { + justify-content: flex-start !important; + } + .justify-content-md-end { + justify-content: flex-end !important; + } + .justify-content-md-center { + justify-content: center !important; + } + .justify-content-md-between { + justify-content: space-between !important; + } + .justify-content-md-around { + justify-content: space-around !important; + } + .justify-content-md-evenly { + justify-content: space-evenly !important; + } + .align-items-md-start { + align-items: flex-start !important; + } + .align-items-md-end { + align-items: flex-end !important; + } + .align-items-md-center { + align-items: center !important; + } + .align-items-md-baseline { + align-items: baseline !important; + } + .align-items-md-stretch { + align-items: stretch !important; + } + .align-content-md-start { + align-content: flex-start !important; + } + .align-content-md-end { + align-content: flex-end !important; + } + .align-content-md-center { + align-content: center !important; + } + .align-content-md-between { + align-content: space-between !important; + } + .align-content-md-around { + align-content: space-around !important; + } + .align-content-md-stretch { + align-content: stretch !important; + } + .align-self-md-auto { + align-self: auto !important; + } + .align-self-md-start { + align-self: flex-start !important; + } + .align-self-md-end { + align-self: flex-end !important; + } + .align-self-md-center { + align-self: center !important; + } + .align-self-md-baseline { + align-self: baseline !important; + } + .align-self-md-stretch { + align-self: stretch !important; + } + .order-md-first { + order: -1 !important; + } + .order-md-0 { + order: 0 !important; + } + .order-md-1 { + order: 1 !important; + } + .order-md-2 { + order: 2 !important; + } + .order-md-3 { + order: 3 !important; + } + .order-md-4 { + order: 4 !important; + } + .order-md-5 { + order: 5 !important; + } + .order-md-last { + order: 6 !important; + } + .m-md-0 { + margin: 0 !important; + } + .m-md-1 { + margin: 0.25rem !important; + } + .m-md-2 { + margin: 0.5rem !important; + } + .m-md-3 { + margin: 1rem !important; + } + .m-md-4 { + margin: 1.5rem !important; + } + .m-md-5 { + margin: 3rem !important; + } + .m-md-auto { + margin: auto !important; + } + .mx-md-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-md-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-md-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-md-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-md-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-md-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-md-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-md-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-md-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-md-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-md-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-md-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-md-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-md-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-md-0 { + margin-top: 0 !important; + } + .mt-md-1 { + margin-top: 0.25rem !important; + } + .mt-md-2 { + margin-top: 0.5rem !important; + } + .mt-md-3 { + margin-top: 1rem !important; + } + .mt-md-4 { + margin-top: 1.5rem !important; + } + .mt-md-5 { + margin-top: 3rem !important; + } + .mt-md-auto { + margin-top: auto !important; + } + .me-md-0 { + margin-right: 0 !important; + } + .me-md-1 { + margin-right: 0.25rem !important; + } + .me-md-2 { + margin-right: 0.5rem !important; + } + .me-md-3 { + margin-right: 1rem !important; + } + .me-md-4 { + margin-right: 1.5rem !important; + } + .me-md-5 { + margin-right: 3rem !important; + } + .me-md-auto { + margin-right: auto !important; + } + .mb-md-0 { + margin-bottom: 0 !important; + } + .mb-md-1 { + margin-bottom: 0.25rem !important; + } + .mb-md-2 { + margin-bottom: 0.5rem !important; + } + .mb-md-3 { + margin-bottom: 1rem !important; + } + .mb-md-4 { + margin-bottom: 1.5rem !important; + } + .mb-md-5 { + margin-bottom: 3rem !important; + } + .mb-md-auto { + margin-bottom: auto !important; + } + .ms-md-0 { + margin-left: 0 !important; + } + .ms-md-1 { + margin-left: 0.25rem !important; + } + .ms-md-2 { + margin-left: 0.5rem !important; + } + .ms-md-3 { + margin-left: 1rem !important; + } + .ms-md-4 { + margin-left: 1.5rem !important; + } + .ms-md-5 { + margin-left: 3rem !important; + } + .ms-md-auto { + margin-left: auto !important; + } + .p-md-0 { + padding: 0 !important; + } + .p-md-1 { + padding: 0.25rem !important; + } + .p-md-2 { + padding: 0.5rem !important; + } + .p-md-3 { + padding: 1rem !important; + } + .p-md-4 { + padding: 1.5rem !important; + } + .p-md-5 { + padding: 3rem !important; + } + .px-md-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-md-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-md-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-md-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-md-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-md-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-md-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-md-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-md-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-md-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-md-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-md-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-md-0 { + padding-top: 0 !important; + } + .pt-md-1 { + padding-top: 0.25rem !important; + } + .pt-md-2 { + padding-top: 0.5rem !important; + } + .pt-md-3 { + padding-top: 1rem !important; + } + .pt-md-4 { + padding-top: 1.5rem !important; + } + .pt-md-5 { + padding-top: 3rem !important; + } + .pe-md-0 { + padding-right: 0 !important; + } + .pe-md-1 { + padding-right: 0.25rem !important; + } + .pe-md-2 { + padding-right: 0.5rem !important; + } + .pe-md-3 { + padding-right: 1rem !important; + } + .pe-md-4 { + padding-right: 1.5rem !important; + } + .pe-md-5 { + padding-right: 3rem !important; + } + .pb-md-0 { + padding-bottom: 0 !important; + } + .pb-md-1 { + padding-bottom: 0.25rem !important; + } + .pb-md-2 { + padding-bottom: 0.5rem !important; + } + .pb-md-3 { + padding-bottom: 1rem !important; + } + .pb-md-4 { + padding-bottom: 1.5rem !important; + } + .pb-md-5 { + padding-bottom: 3rem !important; + } + .ps-md-0 { + padding-left: 0 !important; + } + .ps-md-1 { + padding-left: 0.25rem !important; + } + .ps-md-2 { + padding-left: 0.5rem !important; + } + .ps-md-3 { + padding-left: 1rem !important; + } + .ps-md-4 { + padding-left: 1.5rem !important; + } + .ps-md-5 { + padding-left: 3rem !important; + } + .gap-md-0 { + gap: 0 !important; + } + .gap-md-1 { + gap: 0.25rem !important; + } + .gap-md-2 { + gap: 0.5rem !important; + } + .gap-md-3 { + gap: 1rem !important; + } + .gap-md-4 { + gap: 1.5rem !important; + } + .gap-md-5 { + gap: 3rem !important; + } + .row-gap-md-0 { + row-gap: 0 !important; + } + .row-gap-md-1 { + row-gap: 0.25rem !important; + } + .row-gap-md-2 { + row-gap: 0.5rem !important; + } + .row-gap-md-3 { + row-gap: 1rem !important; + } + .row-gap-md-4 { + row-gap: 1.5rem !important; + } + .row-gap-md-5 { + row-gap: 3rem !important; + } + .column-gap-md-0 { + -moz-column-gap: 0 !important; + column-gap: 0 !important; + } + .column-gap-md-1 { + -moz-column-gap: 0.25rem !important; + column-gap: 0.25rem !important; + } + .column-gap-md-2 { + -moz-column-gap: 0.5rem !important; + column-gap: 0.5rem !important; + } + .column-gap-md-3 { + -moz-column-gap: 1rem !important; + column-gap: 1rem !important; + } + .column-gap-md-4 { + -moz-column-gap: 1.5rem !important; + column-gap: 1.5rem !important; + } + .column-gap-md-5 { + -moz-column-gap: 3rem !important; + column-gap: 3rem !important; + } + .text-md-start { + text-align: left !important; + } + .text-md-end { + text-align: right !important; + } + .text-md-center { + text-align: center !important; + } +} +@media (min-width: 992px) { + .float-lg-start { + float: left !important; + } + .float-lg-end { + float: right !important; + } + .float-lg-none { + float: none !important; + } + .object-fit-lg-contain { + -o-object-fit: contain !important; + object-fit: contain !important; + } + .object-fit-lg-cover { + -o-object-fit: cover !important; + object-fit: cover !important; + } + .object-fit-lg-fill { + -o-object-fit: fill !important; + object-fit: fill !important; + } + .object-fit-lg-scale { + -o-object-fit: scale-down !important; + object-fit: scale-down !important; + } + .object-fit-lg-none { + -o-object-fit: none !important; + object-fit: none !important; + } + .d-lg-inline { + display: inline !important; + } + .d-lg-inline-block { + display: inline-block !important; + } + .d-lg-block { + display: block !important; + } + .d-lg-grid { + display: grid !important; + } + .d-lg-inline-grid { + display: inline-grid !important; + } + .d-lg-table { + display: table !important; + } + .d-lg-table-row { + display: table-row !important; + } + .d-lg-table-cell { + display: table-cell !important; + } + .d-lg-flex { + display: flex !important; + } + .d-lg-inline-flex { + display: inline-flex !important; + } + .d-lg-none { + display: none !important; + } + .flex-lg-fill { + flex: 1 1 auto !important; + } + .flex-lg-row { + flex-direction: row !important; + } + .flex-lg-column { + flex-direction: column !important; + } + .flex-lg-row-reverse { + flex-direction: row-reverse !important; + } + .flex-lg-column-reverse { + flex-direction: column-reverse !important; + } + .flex-lg-grow-0 { + flex-grow: 0 !important; + } + .flex-lg-grow-1 { + flex-grow: 1 !important; + } + .flex-lg-shrink-0 { + flex-shrink: 0 !important; + } + .flex-lg-shrink-1 { + flex-shrink: 1 !important; + } + .flex-lg-wrap { + flex-wrap: wrap !important; + } + .flex-lg-nowrap { + flex-wrap: nowrap !important; + } + .flex-lg-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-lg-start { + justify-content: flex-start !important; + } + .justify-content-lg-end { + justify-content: flex-end !important; + } + .justify-content-lg-center { + justify-content: center !important; + } + .justify-content-lg-between { + justify-content: space-between !important; + } + .justify-content-lg-around { + justify-content: space-around !important; + } + .justify-content-lg-evenly { + justify-content: space-evenly !important; + } + .align-items-lg-start { + align-items: flex-start !important; + } + .align-items-lg-end { + align-items: flex-end !important; + } + .align-items-lg-center { + align-items: center !important; + } + .align-items-lg-baseline { + align-items: baseline !important; + } + .align-items-lg-stretch { + align-items: stretch !important; + } + .align-content-lg-start { + align-content: flex-start !important; + } + .align-content-lg-end { + align-content: flex-end !important; + } + .align-content-lg-center { + align-content: center !important; + } + .align-content-lg-between { + align-content: space-between !important; + } + .align-content-lg-around { + align-content: space-around !important; + } + .align-content-lg-stretch { + align-content: stretch !important; + } + .align-self-lg-auto { + align-self: auto !important; + } + .align-self-lg-start { + align-self: flex-start !important; + } + .align-self-lg-end { + align-self: flex-end !important; + } + .align-self-lg-center { + align-self: center !important; + } + .align-self-lg-baseline { + align-self: baseline !important; + } + .align-self-lg-stretch { + align-self: stretch !important; + } + .order-lg-first { + order: -1 !important; + } + .order-lg-0 { + order: 0 !important; + } + .order-lg-1 { + order: 1 !important; + } + .order-lg-2 { + order: 2 !important; + } + .order-lg-3 { + order: 3 !important; + } + .order-lg-4 { + order: 4 !important; + } + .order-lg-5 { + order: 5 !important; + } + .order-lg-last { + order: 6 !important; + } + .m-lg-0 { + margin: 0 !important; + } + .m-lg-1 { + margin: 0.25rem !important; + } + .m-lg-2 { + margin: 0.5rem !important; + } + .m-lg-3 { + margin: 1rem !important; + } + .m-lg-4 { + margin: 1.5rem !important; + } + .m-lg-5 { + margin: 3rem !important; + } + .m-lg-auto { + margin: auto !important; + } + .mx-lg-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-lg-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-lg-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-lg-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-lg-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-lg-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-lg-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-lg-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-lg-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-lg-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-lg-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-lg-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-lg-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-lg-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-lg-0 { + margin-top: 0 !important; + } + .mt-lg-1 { + margin-top: 0.25rem !important; + } + .mt-lg-2 { + margin-top: 0.5rem !important; + } + .mt-lg-3 { + margin-top: 1rem !important; + } + .mt-lg-4 { + margin-top: 1.5rem !important; + } + .mt-lg-5 { + margin-top: 3rem !important; + } + .mt-lg-auto { + margin-top: auto !important; + } + .me-lg-0 { + margin-right: 0 !important; + } + .me-lg-1 { + margin-right: 0.25rem !important; + } + .me-lg-2 { + margin-right: 0.5rem !important; + } + .me-lg-3 { + margin-right: 1rem !important; + } + .me-lg-4 { + margin-right: 1.5rem !important; + } + .me-lg-5 { + margin-right: 3rem !important; + } + .me-lg-auto { + margin-right: auto !important; + } + .mb-lg-0 { + margin-bottom: 0 !important; + } + .mb-lg-1 { + margin-bottom: 0.25rem !important; + } + .mb-lg-2 { + margin-bottom: 0.5rem !important; + } + .mb-lg-3 { + margin-bottom: 1rem !important; + } + .mb-lg-4 { + margin-bottom: 1.5rem !important; + } + .mb-lg-5 { + margin-bottom: 3rem !important; + } + .mb-lg-auto { + margin-bottom: auto !important; + } + .ms-lg-0 { + margin-left: 0 !important; + } + .ms-lg-1 { + margin-left: 0.25rem !important; + } + .ms-lg-2 { + margin-left: 0.5rem !important; + } + .ms-lg-3 { + margin-left: 1rem !important; + } + .ms-lg-4 { + margin-left: 1.5rem !important; + } + .ms-lg-5 { + margin-left: 3rem !important; + } + .ms-lg-auto { + margin-left: auto !important; + } + .p-lg-0 { + padding: 0 !important; + } + .p-lg-1 { + padding: 0.25rem !important; + } + .p-lg-2 { + padding: 0.5rem !important; + } + .p-lg-3 { + padding: 1rem !important; + } + .p-lg-4 { + padding: 1.5rem !important; + } + .p-lg-5 { + padding: 3rem !important; + } + .px-lg-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-lg-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-lg-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-lg-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-lg-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-lg-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-lg-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-lg-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-lg-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-lg-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-lg-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-lg-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-lg-0 { + padding-top: 0 !important; + } + .pt-lg-1 { + padding-top: 0.25rem !important; + } + .pt-lg-2 { + padding-top: 0.5rem !important; + } + .pt-lg-3 { + padding-top: 1rem !important; + } + .pt-lg-4 { + padding-top: 1.5rem !important; + } + .pt-lg-5 { + padding-top: 3rem !important; + } + .pe-lg-0 { + padding-right: 0 !important; + } + .pe-lg-1 { + padding-right: 0.25rem !important; + } + .pe-lg-2 { + padding-right: 0.5rem !important; + } + .pe-lg-3 { + padding-right: 1rem !important; + } + .pe-lg-4 { + padding-right: 1.5rem !important; + } + .pe-lg-5 { + padding-right: 3rem !important; + } + .pb-lg-0 { + padding-bottom: 0 !important; + } + .pb-lg-1 { + padding-bottom: 0.25rem !important; + } + .pb-lg-2 { + padding-bottom: 0.5rem !important; + } + .pb-lg-3 { + padding-bottom: 1rem !important; + } + .pb-lg-4 { + padding-bottom: 1.5rem !important; + } + .pb-lg-5 { + padding-bottom: 3rem !important; + } + .ps-lg-0 { + padding-left: 0 !important; + } + .ps-lg-1 { + padding-left: 0.25rem !important; + } + .ps-lg-2 { + padding-left: 0.5rem !important; + } + .ps-lg-3 { + padding-left: 1rem !important; + } + .ps-lg-4 { + padding-left: 1.5rem !important; + } + .ps-lg-5 { + padding-left: 3rem !important; + } + .gap-lg-0 { + gap: 0 !important; + } + .gap-lg-1 { + gap: 0.25rem !important; + } + .gap-lg-2 { + gap: 0.5rem !important; + } + .gap-lg-3 { + gap: 1rem !important; + } + .gap-lg-4 { + gap: 1.5rem !important; + } + .gap-lg-5 { + gap: 3rem !important; + } + .row-gap-lg-0 { + row-gap: 0 !important; + } + .row-gap-lg-1 { + row-gap: 0.25rem !important; + } + .row-gap-lg-2 { + row-gap: 0.5rem !important; + } + .row-gap-lg-3 { + row-gap: 1rem !important; + } + .row-gap-lg-4 { + row-gap: 1.5rem !important; + } + .row-gap-lg-5 { + row-gap: 3rem !important; + } + .column-gap-lg-0 { + -moz-column-gap: 0 !important; + column-gap: 0 !important; + } + .column-gap-lg-1 { + -moz-column-gap: 0.25rem !important; + column-gap: 0.25rem !important; + } + .column-gap-lg-2 { + -moz-column-gap: 0.5rem !important; + column-gap: 0.5rem !important; + } + .column-gap-lg-3 { + -moz-column-gap: 1rem !important; + column-gap: 1rem !important; + } + .column-gap-lg-4 { + -moz-column-gap: 1.5rem !important; + column-gap: 1.5rem !important; + } + .column-gap-lg-5 { + -moz-column-gap: 3rem !important; + column-gap: 3rem !important; + } + .text-lg-start { + text-align: left !important; + } + .text-lg-end { + text-align: right !important; + } + .text-lg-center { + text-align: center !important; + } +} +@media (min-width: 1200px) { + .float-xl-start { + float: left !important; + } + .float-xl-end { + float: right !important; + } + .float-xl-none { + float: none !important; + } + .object-fit-xl-contain { + -o-object-fit: contain !important; + object-fit: contain !important; + } + .object-fit-xl-cover { + -o-object-fit: cover !important; + object-fit: cover !important; + } + .object-fit-xl-fill { + -o-object-fit: fill !important; + object-fit: fill !important; + } + .object-fit-xl-scale { + -o-object-fit: scale-down !important; + object-fit: scale-down !important; + } + .object-fit-xl-none { + -o-object-fit: none !important; + object-fit: none !important; + } + .d-xl-inline { + display: inline !important; + } + .d-xl-inline-block { + display: inline-block !important; + } + .d-xl-block { + display: block !important; + } + .d-xl-grid { + display: grid !important; + } + .d-xl-inline-grid { + display: inline-grid !important; + } + .d-xl-table { + display: table !important; + } + .d-xl-table-row { + display: table-row !important; + } + .d-xl-table-cell { + display: table-cell !important; + } + .d-xl-flex { + display: flex !important; + } + .d-xl-inline-flex { + display: inline-flex !important; + } + .d-xl-none { + display: none !important; + } + .flex-xl-fill { + flex: 1 1 auto !important; + } + .flex-xl-row { + flex-direction: row !important; + } + .flex-xl-column { + flex-direction: column !important; + } + .flex-xl-row-reverse { + flex-direction: row-reverse !important; + } + .flex-xl-column-reverse { + flex-direction: column-reverse !important; + } + .flex-xl-grow-0 { + flex-grow: 0 !important; + } + .flex-xl-grow-1 { + flex-grow: 1 !important; + } + .flex-xl-shrink-0 { + flex-shrink: 0 !important; + } + .flex-xl-shrink-1 { + flex-shrink: 1 !important; + } + .flex-xl-wrap { + flex-wrap: wrap !important; + } + .flex-xl-nowrap { + flex-wrap: nowrap !important; + } + .flex-xl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-xl-start { + justify-content: flex-start !important; + } + .justify-content-xl-end { + justify-content: flex-end !important; + } + .justify-content-xl-center { + justify-content: center !important; + } + .justify-content-xl-between { + justify-content: space-between !important; + } + .justify-content-xl-around { + justify-content: space-around !important; + } + .justify-content-xl-evenly { + justify-content: space-evenly !important; + } + .align-items-xl-start { + align-items: flex-start !important; + } + .align-items-xl-end { + align-items: flex-end !important; + } + .align-items-xl-center { + align-items: center !important; + } + .align-items-xl-baseline { + align-items: baseline !important; + } + .align-items-xl-stretch { + align-items: stretch !important; + } + .align-content-xl-start { + align-content: flex-start !important; + } + .align-content-xl-end { + align-content: flex-end !important; + } + .align-content-xl-center { + align-content: center !important; + } + .align-content-xl-between { + align-content: space-between !important; + } + .align-content-xl-around { + align-content: space-around !important; + } + .align-content-xl-stretch { + align-content: stretch !important; + } + .align-self-xl-auto { + align-self: auto !important; + } + .align-self-xl-start { + align-self: flex-start !important; + } + .align-self-xl-end { + align-self: flex-end !important; + } + .align-self-xl-center { + align-self: center !important; + } + .align-self-xl-baseline { + align-self: baseline !important; + } + .align-self-xl-stretch { + align-self: stretch !important; + } + .order-xl-first { + order: -1 !important; + } + .order-xl-0 { + order: 0 !important; + } + .order-xl-1 { + order: 1 !important; + } + .order-xl-2 { + order: 2 !important; + } + .order-xl-3 { + order: 3 !important; + } + .order-xl-4 { + order: 4 !important; + } + .order-xl-5 { + order: 5 !important; + } + .order-xl-last { + order: 6 !important; + } + .m-xl-0 { + margin: 0 !important; + } + .m-xl-1 { + margin: 0.25rem !important; + } + .m-xl-2 { + margin: 0.5rem !important; + } + .m-xl-3 { + margin: 1rem !important; + } + .m-xl-4 { + margin: 1.5rem !important; + } + .m-xl-5 { + margin: 3rem !important; + } + .m-xl-auto { + margin: auto !important; + } + .mx-xl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-xl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-xl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-xl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-xl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-xl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-xl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-xl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-xl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-xl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-xl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-xl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-xl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-xl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-xl-0 { + margin-top: 0 !important; + } + .mt-xl-1 { + margin-top: 0.25rem !important; + } + .mt-xl-2 { + margin-top: 0.5rem !important; + } + .mt-xl-3 { + margin-top: 1rem !important; + } + .mt-xl-4 { + margin-top: 1.5rem !important; + } + .mt-xl-5 { + margin-top: 3rem !important; + } + .mt-xl-auto { + margin-top: auto !important; + } + .me-xl-0 { + margin-right: 0 !important; + } + .me-xl-1 { + margin-right: 0.25rem !important; + } + .me-xl-2 { + margin-right: 0.5rem !important; + } + .me-xl-3 { + margin-right: 1rem !important; + } + .me-xl-4 { + margin-right: 1.5rem !important; + } + .me-xl-5 { + margin-right: 3rem !important; + } + .me-xl-auto { + margin-right: auto !important; + } + .mb-xl-0 { + margin-bottom: 0 !important; + } + .mb-xl-1 { + margin-bottom: 0.25rem !important; + } + .mb-xl-2 { + margin-bottom: 0.5rem !important; + } + .mb-xl-3 { + margin-bottom: 1rem !important; + } + .mb-xl-4 { + margin-bottom: 1.5rem !important; + } + .mb-xl-5 { + margin-bottom: 3rem !important; + } + .mb-xl-auto { + margin-bottom: auto !important; + } + .ms-xl-0 { + margin-left: 0 !important; + } + .ms-xl-1 { + margin-left: 0.25rem !important; + } + .ms-xl-2 { + margin-left: 0.5rem !important; + } + .ms-xl-3 { + margin-left: 1rem !important; + } + .ms-xl-4 { + margin-left: 1.5rem !important; + } + .ms-xl-5 { + margin-left: 3rem !important; + } + .ms-xl-auto { + margin-left: auto !important; + } + .p-xl-0 { + padding: 0 !important; + } + .p-xl-1 { + padding: 0.25rem !important; + } + .p-xl-2 { + padding: 0.5rem !important; + } + .p-xl-3 { + padding: 1rem !important; + } + .p-xl-4 { + padding: 1.5rem !important; + } + .p-xl-5 { + padding: 3rem !important; + } + .px-xl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-xl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-xl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-xl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-xl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-xl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-xl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-xl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-xl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-xl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-xl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-xl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-xl-0 { + padding-top: 0 !important; + } + .pt-xl-1 { + padding-top: 0.25rem !important; + } + .pt-xl-2 { + padding-top: 0.5rem !important; + } + .pt-xl-3 { + padding-top: 1rem !important; + } + .pt-xl-4 { + padding-top: 1.5rem !important; + } + .pt-xl-5 { + padding-top: 3rem !important; + } + .pe-xl-0 { + padding-right: 0 !important; + } + .pe-xl-1 { + padding-right: 0.25rem !important; + } + .pe-xl-2 { + padding-right: 0.5rem !important; + } + .pe-xl-3 { + padding-right: 1rem !important; + } + .pe-xl-4 { + padding-right: 1.5rem !important; + } + .pe-xl-5 { + padding-right: 3rem !important; + } + .pb-xl-0 { + padding-bottom: 0 !important; + } + .pb-xl-1 { + padding-bottom: 0.25rem !important; + } + .pb-xl-2 { + padding-bottom: 0.5rem !important; + } + .pb-xl-3 { + padding-bottom: 1rem !important; + } + .pb-xl-4 { + padding-bottom: 1.5rem !important; + } + .pb-xl-5 { + padding-bottom: 3rem !important; + } + .ps-xl-0 { + padding-left: 0 !important; + } + .ps-xl-1 { + padding-left: 0.25rem !important; + } + .ps-xl-2 { + padding-left: 0.5rem !important; + } + .ps-xl-3 { + padding-left: 1rem !important; + } + .ps-xl-4 { + padding-left: 1.5rem !important; + } + .ps-xl-5 { + padding-left: 3rem !important; + } + .gap-xl-0 { + gap: 0 !important; + } + .gap-xl-1 { + gap: 0.25rem !important; + } + .gap-xl-2 { + gap: 0.5rem !important; + } + .gap-xl-3 { + gap: 1rem !important; + } + .gap-xl-4 { + gap: 1.5rem !important; + } + .gap-xl-5 { + gap: 3rem !important; + } + .row-gap-xl-0 { + row-gap: 0 !important; + } + .row-gap-xl-1 { + row-gap: 0.25rem !important; + } + .row-gap-xl-2 { + row-gap: 0.5rem !important; + } + .row-gap-xl-3 { + row-gap: 1rem !important; + } + .row-gap-xl-4 { + row-gap: 1.5rem !important; + } + .row-gap-xl-5 { + row-gap: 3rem !important; + } + .column-gap-xl-0 { + -moz-column-gap: 0 !important; + column-gap: 0 !important; + } + .column-gap-xl-1 { + -moz-column-gap: 0.25rem !important; + column-gap: 0.25rem !important; + } + .column-gap-xl-2 { + -moz-column-gap: 0.5rem !important; + column-gap: 0.5rem !important; + } + .column-gap-xl-3 { + -moz-column-gap: 1rem !important; + column-gap: 1rem !important; + } + .column-gap-xl-4 { + -moz-column-gap: 1.5rem !important; + column-gap: 1.5rem !important; + } + .column-gap-xl-5 { + -moz-column-gap: 3rem !important; + column-gap: 3rem !important; + } + .text-xl-start { + text-align: left !important; + } + .text-xl-end { + text-align: right !important; + } + .text-xl-center { + text-align: center !important; + } +} +@media (min-width: 1400px) { + .float-xxl-start { + float: left !important; + } + .float-xxl-end { + float: right !important; + } + .float-xxl-none { + float: none !important; + } + .object-fit-xxl-contain { + -o-object-fit: contain !important; + object-fit: contain !important; + } + .object-fit-xxl-cover { + -o-object-fit: cover !important; + object-fit: cover !important; + } + .object-fit-xxl-fill { + -o-object-fit: fill !important; + object-fit: fill !important; + } + .object-fit-xxl-scale { + -o-object-fit: scale-down !important; + object-fit: scale-down !important; + } + .object-fit-xxl-none { + -o-object-fit: none !important; + object-fit: none !important; + } + .d-xxl-inline { + display: inline !important; + } + .d-xxl-inline-block { + display: inline-block !important; + } + .d-xxl-block { + display: block !important; + } + .d-xxl-grid { + display: grid !important; + } + .d-xxl-inline-grid { + display: inline-grid !important; + } + .d-xxl-table { + display: table !important; + } + .d-xxl-table-row { + display: table-row !important; + } + .d-xxl-table-cell { + display: table-cell !important; + } + .d-xxl-flex { + display: flex !important; + } + .d-xxl-inline-flex { + display: inline-flex !important; + } + .d-xxl-none { + display: none !important; + } + .flex-xxl-fill { + flex: 1 1 auto !important; + } + .flex-xxl-row { + flex-direction: row !important; + } + .flex-xxl-column { + flex-direction: column !important; + } + .flex-xxl-row-reverse { + flex-direction: row-reverse !important; + } + .flex-xxl-column-reverse { + flex-direction: column-reverse !important; + } + .flex-xxl-grow-0 { + flex-grow: 0 !important; + } + .flex-xxl-grow-1 { + flex-grow: 1 !important; + } + .flex-xxl-shrink-0 { + flex-shrink: 0 !important; + } + .flex-xxl-shrink-1 { + flex-shrink: 1 !important; + } + .flex-xxl-wrap { + flex-wrap: wrap !important; + } + .flex-xxl-nowrap { + flex-wrap: nowrap !important; + } + .flex-xxl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + .justify-content-xxl-start { + justify-content: flex-start !important; + } + .justify-content-xxl-end { + justify-content: flex-end !important; + } + .justify-content-xxl-center { + justify-content: center !important; + } + .justify-content-xxl-between { + justify-content: space-between !important; + } + .justify-content-xxl-around { + justify-content: space-around !important; + } + .justify-content-xxl-evenly { + justify-content: space-evenly !important; + } + .align-items-xxl-start { + align-items: flex-start !important; + } + .align-items-xxl-end { + align-items: flex-end !important; + } + .align-items-xxl-center { + align-items: center !important; + } + .align-items-xxl-baseline { + align-items: baseline !important; + } + .align-items-xxl-stretch { + align-items: stretch !important; + } + .align-content-xxl-start { + align-content: flex-start !important; + } + .align-content-xxl-end { + align-content: flex-end !important; + } + .align-content-xxl-center { + align-content: center !important; + } + .align-content-xxl-between { + align-content: space-between !important; + } + .align-content-xxl-around { + align-content: space-around !important; + } + .align-content-xxl-stretch { + align-content: stretch !important; + } + .align-self-xxl-auto { + align-self: auto !important; + } + .align-self-xxl-start { + align-self: flex-start !important; + } + .align-self-xxl-end { + align-self: flex-end !important; + } + .align-self-xxl-center { + align-self: center !important; + } + .align-self-xxl-baseline { + align-self: baseline !important; + } + .align-self-xxl-stretch { + align-self: stretch !important; + } + .order-xxl-first { + order: -1 !important; + } + .order-xxl-0 { + order: 0 !important; + } + .order-xxl-1 { + order: 1 !important; + } + .order-xxl-2 { + order: 2 !important; + } + .order-xxl-3 { + order: 3 !important; + } + .order-xxl-4 { + order: 4 !important; + } + .order-xxl-5 { + order: 5 !important; + } + .order-xxl-last { + order: 6 !important; + } + .m-xxl-0 { + margin: 0 !important; + } + .m-xxl-1 { + margin: 0.25rem !important; + } + .m-xxl-2 { + margin: 0.5rem !important; + } + .m-xxl-3 { + margin: 1rem !important; + } + .m-xxl-4 { + margin: 1.5rem !important; + } + .m-xxl-5 { + margin: 3rem !important; + } + .m-xxl-auto { + margin: auto !important; + } + .mx-xxl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + .mx-xxl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + .mx-xxl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + .mx-xxl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + .mx-xxl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + .mx-xxl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + .mx-xxl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + .my-xxl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + .my-xxl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + .my-xxl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + .my-xxl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + .my-xxl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + .my-xxl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + .my-xxl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + .mt-xxl-0 { + margin-top: 0 !important; + } + .mt-xxl-1 { + margin-top: 0.25rem !important; + } + .mt-xxl-2 { + margin-top: 0.5rem !important; + } + .mt-xxl-3 { + margin-top: 1rem !important; + } + .mt-xxl-4 { + margin-top: 1.5rem !important; + } + .mt-xxl-5 { + margin-top: 3rem !important; + } + .mt-xxl-auto { + margin-top: auto !important; + } + .me-xxl-0 { + margin-right: 0 !important; + } + .me-xxl-1 { + margin-right: 0.25rem !important; + } + .me-xxl-2 { + margin-right: 0.5rem !important; + } + .me-xxl-3 { + margin-right: 1rem !important; + } + .me-xxl-4 { + margin-right: 1.5rem !important; + } + .me-xxl-5 { + margin-right: 3rem !important; + } + .me-xxl-auto { + margin-right: auto !important; + } + .mb-xxl-0 { + margin-bottom: 0 !important; + } + .mb-xxl-1 { + margin-bottom: 0.25rem !important; + } + .mb-xxl-2 { + margin-bottom: 0.5rem !important; + } + .mb-xxl-3 { + margin-bottom: 1rem !important; + } + .mb-xxl-4 { + margin-bottom: 1.5rem !important; + } + .mb-xxl-5 { + margin-bottom: 3rem !important; + } + .mb-xxl-auto { + margin-bottom: auto !important; + } + .ms-xxl-0 { + margin-left: 0 !important; + } + .ms-xxl-1 { + margin-left: 0.25rem !important; + } + .ms-xxl-2 { + margin-left: 0.5rem !important; + } + .ms-xxl-3 { + margin-left: 1rem !important; + } + .ms-xxl-4 { + margin-left: 1.5rem !important; + } + .ms-xxl-5 { + margin-left: 3rem !important; + } + .ms-xxl-auto { + margin-left: auto !important; + } + .p-xxl-0 { + padding: 0 !important; + } + .p-xxl-1 { + padding: 0.25rem !important; + } + .p-xxl-2 { + padding: 0.5rem !important; + } + .p-xxl-3 { + padding: 1rem !important; + } + .p-xxl-4 { + padding: 1.5rem !important; + } + .p-xxl-5 { + padding: 3rem !important; + } + .px-xxl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + .px-xxl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + .px-xxl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + .px-xxl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + .px-xxl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + .px-xxl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + .py-xxl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + .py-xxl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + .py-xxl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + .py-xxl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + .py-xxl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + .py-xxl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + .pt-xxl-0 { + padding-top: 0 !important; + } + .pt-xxl-1 { + padding-top: 0.25rem !important; + } + .pt-xxl-2 { + padding-top: 0.5rem !important; + } + .pt-xxl-3 { + padding-top: 1rem !important; + } + .pt-xxl-4 { + padding-top: 1.5rem !important; + } + .pt-xxl-5 { + padding-top: 3rem !important; + } + .pe-xxl-0 { + padding-right: 0 !important; + } + .pe-xxl-1 { + padding-right: 0.25rem !important; + } + .pe-xxl-2 { + padding-right: 0.5rem !important; + } + .pe-xxl-3 { + padding-right: 1rem !important; + } + .pe-xxl-4 { + padding-right: 1.5rem !important; + } + .pe-xxl-5 { + padding-right: 3rem !important; + } + .pb-xxl-0 { + padding-bottom: 0 !important; + } + .pb-xxl-1 { + padding-bottom: 0.25rem !important; + } + .pb-xxl-2 { + padding-bottom: 0.5rem !important; + } + .pb-xxl-3 { + padding-bottom: 1rem !important; + } + .pb-xxl-4 { + padding-bottom: 1.5rem !important; + } + .pb-xxl-5 { + padding-bottom: 3rem !important; + } + .ps-xxl-0 { + padding-left: 0 !important; + } + .ps-xxl-1 { + padding-left: 0.25rem !important; + } + .ps-xxl-2 { + padding-left: 0.5rem !important; + } + .ps-xxl-3 { + padding-left: 1rem !important; + } + .ps-xxl-4 { + padding-left: 1.5rem !important; + } + .ps-xxl-5 { + padding-left: 3rem !important; + } + .gap-xxl-0 { + gap: 0 !important; + } + .gap-xxl-1 { + gap: 0.25rem !important; + } + .gap-xxl-2 { + gap: 0.5rem !important; + } + .gap-xxl-3 { + gap: 1rem !important; + } + .gap-xxl-4 { + gap: 1.5rem !important; + } + .gap-xxl-5 { + gap: 3rem !important; + } + .row-gap-xxl-0 { + row-gap: 0 !important; + } + .row-gap-xxl-1 { + row-gap: 0.25rem !important; + } + .row-gap-xxl-2 { + row-gap: 0.5rem !important; + } + .row-gap-xxl-3 { + row-gap: 1rem !important; + } + .row-gap-xxl-4 { + row-gap: 1.5rem !important; + } + .row-gap-xxl-5 { + row-gap: 3rem !important; + } + .column-gap-xxl-0 { + -moz-column-gap: 0 !important; + column-gap: 0 !important; + } + .column-gap-xxl-1 { + -moz-column-gap: 0.25rem !important; + column-gap: 0.25rem !important; + } + .column-gap-xxl-2 { + -moz-column-gap: 0.5rem !important; + column-gap: 0.5rem !important; + } + .column-gap-xxl-3 { + -moz-column-gap: 1rem !important; + column-gap: 1rem !important; + } + .column-gap-xxl-4 { + -moz-column-gap: 1.5rem !important; + column-gap: 1.5rem !important; + } + .column-gap-xxl-5 { + -moz-column-gap: 3rem !important; + column-gap: 3rem !important; + } + .text-xxl-start { + text-align: left !important; + } + .text-xxl-end { + text-align: right !important; + } + .text-xxl-center { + text-align: center !important; + } +} +@media (min-width: 1200px) { + .fs-1 { + font-size: 2.5rem !important; + } + .fs-2 { + font-size: 2rem !important; + } + .fs-3 { + font-size: 1.75rem !important; + } + .fs-4 { + font-size: 1.5rem !important; + } +} +@media print { + .d-print-inline { + display: inline !important; + } + .d-print-inline-block { + display: inline-block !important; + } + .d-print-block { + display: block !important; + } + .d-print-grid { + display: grid !important; + } + .d-print-inline-grid { + display: inline-grid !important; + } + .d-print-table { + display: table !important; + } + .d-print-table-row { + display: table-row !important; + } + .d-print-table-cell { + display: table-cell !important; + } + .d-print-flex { + display: flex !important; + } + .d-print-inline-flex { + display: inline-flex !important; + } + .d-print-none { + display: none !important; + } +} diff --git a/public/fonts/bootstrap-icons.woff b/public/fonts/bootstrap-icons.woff new file mode 100644 index 0000000000000000000000000000000000000000..51204d27de92c7bb0f8bed6165b9dc888f38ff38 GIT binary patch literal 176032 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 literal 0 HcmV?d00001 diff --git a/public/fonts/bootstrap-icons.woff2 b/public/fonts/bootstrap-icons.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..92c4830216044ba21db9f4294b887312e80da38e GIT binary patch literal 130396 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Ã=hYmg-7dH4?&*NqqtUL18qtx> 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 z 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
c8|p^C*A74_3(S}?}tv`LlY$l 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 + + + + + + + + + diff --git a/public/heatmap.wasm b/public/heatmap.wasm new file mode 100755 index 0000000000000000000000000000000000000000..d68cb83894d5c93b33e83ac7501307d3e4349244 GIT binary patch literal 2702031 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�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 WQo5mcZ#05gxpgY0rf|c<&DMIa%Y}eWx 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%0DU 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

q>3Vzq(_f-6{b+Q@YJ>A0*EIB-*g8J}zY+hG z+)r03N5L%klb6a+`8y;JS3Wv}DdKdZ`?JA2EDs|HdivbOcMf5Pdtt-SIS@F@ONM(O zxTE0C<*Sd*F}(44oxu*kzewRS@NJmZsocbC`Sja@-); z-E;4OTSC6?PDAoaR0i_xY*2i#TJc`(>X0p7>`t zC*$w<4uU7(pSe%-@b|)hrOKSi%)Q)m@9V{Vis$adoyliE+!;Tr*H10L6<|l3 z+X@MP8t{o}x=+WQ$!CAhe-%9Fqr5)@e|_Yh^!%TR|G`#{j_yJ){vzBu$0~hLn*G36 z7!3#a0oPNS3GR%CG29t%2jD&+#W@gnCjUKi9-O^Ah_Fo87UN!=@>C_=g9|WQ8Joh_ zK+DHJs{ro-?9vU*Uel!yI#T+w--mjz(mNacEL`w81(@rB>?2t+1Z%?G9bA1B#`e!V zzk{AXTOo6QwiV`Xwq~U|!2FfxzbkRaQkqA4I7fNzqdoWIJbbE1PM@sgZp>z$)^VQu z`JVd)p8JKK`$eAn#kfnxTNvEBrZad+0e&g4uQSI3XSVNl@J}d&p9ow_^Lmo!J{h;4 z&e8(>GGL$XzQ_R8HQl|IjGt1#KeYfeglmfb6yopX#UCf!=@9qI72+-{#62C@&+{1t z{N=z|9#`Pb>Yw^UD+}->us+hKi{VKhxnJeE*)H5fV>Pg|&FDKcUk$DgpGml1uPKH+ z{;l9&QouipaNT(zJ0N;h!ZX;QF%oEpR=>eL1*J#&(@oPGc?p zj(!l_o#Tf=Oga8OhnZjV(p~4d-v&;}(r|6S9}4h#aP^TK-%40!%ct<4pZcGN+o$o$ z0{r#@%|8|3|Bt;l53H*y+rD?wQlOMcQATxBh;5}w(^96=Leq4FPP8dyG@K--NoaBs z&PiyCpjFDCBBG+Af--}M3^Is{P-Rp>K~YgqQBhD)QBYA)-ru!`eeUe0fbaLm^ZGq( zSj}}0>t6G`_CBYZFg}G$kHWjq;0;FSBKR>LXTXnr;h9F~)5h;-48FwRvyA@5hCdY? z%S`jl%bhupRSSae2w;Yn}0a&$m46_ zYp$*Q{=C6o0LOauFR+gj?+oB~R`7c+IQsn{_{?DEJY)Yu;22+}=N4>P`oq!<{;orI zMzDPocpMQ>ylw+G2mY;K>;H>6`XksI8FX()wjtnug7C*No1^cCZg=|Jnajy8!d9$D-$HhG(EBue zpB`U7A3%173G<$mY2^ZOEc z!;|v+QgF=I%fPmNJd7Vpe=kQr0^Jn&c7mf1K0*Q>LFJSEJh&!u>2*-*Aj$&!5q| zE6|#gUW0tEp!+%F?^v;B&#YOg@~W zZ#6caGX9=6_>1WH@}N%x`#Bi*n+^Ul_{mVOj|_gbZ=;%b0(Id@&{xoDn3U~YOo}@f z4PBL_ST6UKlki&uvj$hKDwflMzP_~5%S(w9`6+_-zCpbwUhGKQ`+9o|rH*ukHpw;A!vX4oBCrJLSKtt2%b4kl(J?5$BZ9?f`uKki3{mY*Lxx+YOsJeHF^4y`C{(MGP%kD23 z&zId_gB|7n-@y4ay%2b+Lw^UW1ehwgy76`T4O>_KVQl>qJdzY_kA~)tFXsII%h1|G z|93|F{LuLP61-SudWFh{Rby!RuQjyl;ElPsjmYFx`y&HS`Tbx{e+y(W>`}w`-O~8o zDwF$s*&150-4Um~)6q`u>(DmfT5?ZqUBAgOBb*|HaJa^}zL zX`gjU@T<1FZzlJ3aB7a;&(XdP?w^w#U}Oj8WCt19w18tDcCe#|_PNu8f92B*a4h3P z0*?89XwZv&)l5hG_%#I_!yWHjI6?rZ1!G9~xv|6>imt*>L9Y#tYQns4dM=WfdKu)tHB zU1ad_1}_1(BbUzG4S%WOAD;1RlKY9*LL*xaj`Mbfc|?wG6-~yt{RQMF&Wu`M0_ zVh{JbME|o&Um$%x?KjG++8U0D<)5!zn!&-1L;6d<7OdjQLJ>i@TJ@DB6j_!wE z2fgO8TWg}-Pvz(fjlROY$kB&n;l3AIkHS3-+(ntm)(zM`HAi5%gNGIHm(k~)Q+93p}*|@&MvMh4E79+pKx&US)+qd z=kXfD^ZqIWef|0XR-v=t;)6$?&lx@EH$)G+kf-572T`+2bPT7A!T z4*PNI`hYcV>74$Cpcluu8*}s*pecU0-n+RkWaI|}?p{4spM~`rG zzuUn2b*Z?PRG;%DC-?Dv2CPTpSjVxWlHcd(KNz~@=uycZ4c!6#tf9|8W>oU0K>NE1 zwaE`MT4Nh)N_4Uvgoc$(%NO~34}V5ab65G>4!wIae~O(X{@%iK@bARMx_x`lQ+@lT z!S@=S`@nl5m(KG>=T`>*CBys%8Ex;c8O^?j!CyA`*9QL$9QRK)f>n-c$4c)5(7tW? zefJlj?+SA5!+!&M??9h`{@f@4UXrxHxSO#&|{s<&v_ro$-keYUo!L#l-F;eeHpX2i#;lQW?%9j=JX%U(KYDn zQ9NtGdjcJTiDy%UFwW`h4fXyuKKC< z)T^Fkr-h|rM&Q7K^TXhY#i{okkf_qh9 z<&oy0KO(>4+Ilyq<8AH^RtTem4b{m#jQmXjYb?-u^3Bk?@1CvsiN{;u#c+OZ!bzQO zbq&7}+xG`u^^_O$fv;~s>rsB)P#Bdg3$*5*x6Gbz3~vv34;%V&>4ZhmcMZRX_FYto)WJ|GQQ%>cPbYbdd2^K#;-{R(Eov<<^P8nog|MM{3C;ZZ15++DvMaJA2YH> z_>Wr}#!mvR{8qUhM;d;b>C_~rLjNq&QQ6ldPZ)W6{HWyT8O>bR&z!U>sT2od!Hf^= ziRolkHowU9xo?L5UuN`>x!9|ogLSV;{hX{J%!6D8YZBDZ-d7sn3$&H-;jhiqbETS}tO4F*5)x~wqeI3Pg&l%~yQ-&&SGVxl|UFzst)3E8p3nK_h zLzi{AWn1t(?6PfG|11li40+|ti{FtY|9)liZ(5>?nZAR0D@m_kRp{;RSvM^$l)DQ( z2cOnZ&4rLN9DktO%L0<`^rnqzVQ`@DU?!A&6tuq3!^aq>rR~fpi{&An2fBNUn}ktW z$C|UZey|(=F7QhCDaC2&C=|f>nSNDL^a31Q*g^upQ$}|emndzsH=&A|3 ze{DL&^V$c?75VJ%>-K3(er@t{KA&0TYs7xyN833RS!`Q6pO^)$F-dJr^Z~)IUpH@= zTuj>;g@>o$7mREdwCBH_xkTV;tUL(Z&R^l*fEAABHq!eov>!JqZ|L7;{x}bXKG?{2 zfu3pTt)OS*=x2=o7pOnKH?;Ks0NobCm%ItONJ15#r=kA{-4)i>=RrRU{hK#>xz?;Fu?WG5pzv|5wAGWB6AZ{@=hcKkp{KFF>o@l%D4a z{|ck~cZ07s_#fcr5XXNS{31BcX|6K*|1$XB;CSch5yF27`rP$Ce9?2E&nALyE(@(g zEKAQv9`AKYzXtia@2Tq7=I9YQ`Y`-2YO3mwM6O5SZEPKt9F9EJFVR~dkNI^2^e980 z2fbzHpL7}7#mE+6Yp-Biez!Jq`5m33m!hvnak-qac$>_&r^i5_737aoH@7wP1JK*$ z=%g%r??5l+!FuBTdSj;_dM87l0R09-FNJ=i zp=UzxZ0JVlT@0NJTpC#RUK*xB$39Lu$=V;>H9`KtD{}{u6i{T$@ z_!olpxV$0E6unq4jv~xEkz4vW=$J>69}hhu_!qsW3Fic4F*! zt_=A0A%6A@_V&&6eLpibM}HaJu};^^_d~8naan^b=5c)%k0jaO=&Ut52N?c3!#~jQ zPci&`GMhEYbkaJ}$PO}o-eLH4nIGQgFnGMd;|!i;@Y@WYU~q%M(@eOh!jI`c*zl)k z*pI9Gq383PeL>ppX~y4-OgBm1W%!4{_qM&CLk+FD!c60Dz46y%`0qCS{lPX4vy45( zsoBu7KRdJI(=avXe~!_Y|G9>i|9P4JBzcdC$9%&--S964>ro%EzMb!I8`%Qm=QEie zZN})FW$qRn?`)&@S+H-b%sbhCy)4t^eWeVu{=?tlCam`w8=uSc zc%Q-OywB)dV{{f7o%b7^YmLt54ZhCc8w|eD;Oh;($>7B%taISUI{XErbF;xq(2xDQ z*2Nz{X6bWt^iuR=e~%nY#K;xDV~l(v^s$EC1Nt~a zkAXfuN54Hsw;K9I!aKpx&p_XkdqEbCr#}Jh?RmP0U$4)36u36{T}m7~b97gZ?l$yH^iPD2@%R+sM7$cl zExR6QUssZ3d5Evpp<@XB2t#iN?S6wNEM}`a0RC5Q{Jv*#ZK1cnr&yWP#gezT&_5|^ zv;S$fai+23$u?Ve2RkPf4z`l^uEEmk%92%V5(uSQx2L^>+>UH3vZ$_f4|JbgOvak{ zXisl|P&$ZfFKN)DbF+ai&RY%L7jWF?c#`>OW8*aUzxJ{EjczCQnO1~7uiE6KA%1J! zT(6w*{2taoUuS1e(dR)WvsIIHF%P>pi?8k_@%<0N9%kbt8OZ!Gx5zN(0`!k38+r%I zwd!AcC(I!-Ip@b2W=@6Qb%sud`1RW)BsDoD)8T!W4DZ4V@555#bjl%BWdXxOy-umljVhhWcgqzS#SK`#+>@yhQ1qn zM;UuM?9lpE?+?8PJ$?hGsLLj&XMU*5Y~hKwVF-_(1mZaZp4wL2+l;w!rqMks!~8CD zk@3yY6QR2%^X^l|;|@lKYm$Y?-*4#SpgX!xPR_}A+>gjGd!xwDHS{^qA2f77X+6)- z*CMYBtaJOpAIkVi^5G0~&la7J82WMO^9_9)cVj*p=$H>5gH~U#1McGiOGS0}0!RDv z*iV3Ue&EkoYu)?TpA7o)`>71qBs&oI3yt54z&fARy-2OoKW%iihw_;meX*e*q5WK9 z=zjXtOQBVkufyIR-OM$hm5Lqt_i~48lbyg3rF*BII7GR)eH^jsTg{c8vURKD#j>NWGOm3wXXCa&D=!|UEq)1F>5q5xy679eJPhwE#-Gyl zRcJl&Okn(~QOO;Kr#k}Avo5*Q@N{;t1A4ayp2kl3Tf^B|YoXt@-;K!b!meZsk$p4M z<-7&l=48BU10EajJ>We9e%R=L+u-jS{2hbu2hR$Azi0U0GWZdLA29g)20v)<55WHX z+^6A(8O`|&IJUzd8T?~|A2axIgMVW1y$^++`sp+L z|J3+bU$W5jQ91Fbxfd?uH}e`Dm*|9wXD{g@0huR`_* zL(Be?(0XG2{S!LINBQ$&j{aAs&o^YiDrotA2-`0~`}*!_U3fp; z$ZMcSVqE$O?Y!2|%HI*t*8j+yd<*D!Uqkw%pksR$y(P4sSk_xXD=q4el-8{ct+b6c zw90!M=vwqOChS1`#u&Nuw>7l%w}Vz6tuaYuyS?$R^xbaitLndOEH*sNji12Z4#7?w zPj`maqrILtg0nov|BgBO4Vf-;H^O{y120_d1|9QA{&#n@#t6y~ z{Z`_uJW<>{^4~An1HCl(RenE%-#v5mSVKRGd@n=a54|_EY|Fpsx}2OhnlD`W{1inm zIncyIeZgBZ-6WX+)}#D-o56ZFQ=VmCWBzzUk73N;$LLNBGS!u{(XEG$bwPd`j9m1j z9NidbeLqfRE&E?JaTf0@IohUg3jXyd4f_VHb;(qNH|Zm%nI5&LuYGkx_NLj2mS)${ zhQIty6?T*!)z_!_A+BlAK5y7J1n&u7VILU66P{so{)4bx$d&$Ld&8pD8OB_42=){Q z-4)kejzfcepJ%nqb=hAFI*MlpKMK}0B+qKOyFfZyxoxZnq0@xE9^K#A@NT{}5@^*| z%@YnVwB`t{fmWTkf$&a%j&)FU!P2~}JP$hNQ(NYjy&I!9u$q0i9DQU)^KBup@25x; z*q=S}dre?H%Io>yj(}HyM+CeOyf+b$PSNNeW$-F+jAN(acNu(~!N(f?Zo@wY?DK-( zWitE|4L;iFECsiRcphQ!YNNj(VBddifwu3%d*JsPnc8#-TItXbqx#X8(f)484U|W} z;YsIi%Iu`TQ`=Qpl#Pz;K8j8Sp7NCHMEhh9Ak*>nWH7VA?-Lok1{~|G{H@K=>xR%Z z$ti)>ou_x?WT!$aeOl|BX7D?WpLc=v#IfKkJSco$pII|y@{lK_?cEvAuN@ZW=(p$S zMnxjn)EfJA`g1FFUe%nQde3o4K_9Q-Vm_r;rZ+_+?dhq3xH$a_j&N$v=Q~uUjWbJ@}uze zM*k-8W$?tm+2~&do*n#NXZW8p_*#QEjkT$(+3?>&-3!Yt)nV4ZtkI_V?NNSvJ0Umgz)fp<7B+RxHkwWX~0$=tgP zbCM+8b<1ST#Y!DzdkNoxME@(e+i_pT-GRFkw-NU>+}Ck;;qJ!WgS!`ZAMSqKH*nv? zeGB&h?m^tQao@o`gnJnGUEKF@kKn$K`vLBUxJPk6!u=Tc818Z0PjElQ{S5a6?&r8) z;C_jF689_IuW?V|p2qzK_gmcWaL?d=kNX4ekGN-Xf5QD4_Z;qd++T2i#r+NU0`Bj) zf8hR!dlC09+`n-z;WR<3!PVkM;6~!Mz>UIfiQ5XdHEuL+8{8P&wz%zZS^gimiVqs- zuH2>tF`sfchx{K;S={x$2R7i&x$7GKUh}{?N#SHJIqTADx_HH+CNAC4eX&iOc30A3 zZ~wqL%>XNd<>G=4O12w%cCn{8Ko?i&FSK>{h~s~s+;V1jSDZj!viZe7BK&3&iT_Y^w|?c~GS^pF`TU|GxZbWH)qV7W|e$*oS+dhT47;Zh2H?S+B9 zGM|ocjI{^u-@5i)c1 z^;gu}yuvUN%W^oWw09LdTB$Yz+*++0Ox&wfzRxZ)oE1ANR0;RN5FK+(x+d2zLKexcH(+tLZIp1Jz3c*v`J+rc#eSO0x0poR7K z6NRL$(2;T)I7nlnk=568KexBBmhZ6&&<+{?JqUSBL1m^HR@iJCT-ESR)}%gm)h zCsVBs|Mp$d)ImmM{fZj5p>zVZ%)K{jxvodaX>HQasaxE%uX9}f=^+70K}l{VC)GvL zgnNtBm&%gzf+fqn!s3``zJubbHKmu#Rp(T%jIXDO(FQ9?-zpUy@0|1&*138@2Q}zB z)xi=cx9Sn8L9w~B?M?xgR#Q)W`BChdE%gxgDT$!;>V5I0^O|jJ(xP4|tR&WlaK-(j zHZ#~mZf{1bQ(73*hjd&Y9Q0yUi^W?>2Kzf`c?MBty?PK{MU*jpS z(}``Rp|icU;%V1jD~TG26D0~SK5M#ZK4esdcSICXH&QgDEy^kWAFLEt4fg2fzgk78 zE^$;z=uW%3y(J>sG1$(4GlM=QXt}06w7=Y3H&|wYQ|?InN+>L|5{$&Fd zH3Qzi>MIwS7C7sCut_N((|UU9E4-aR_I6RVsDPCj>xxEJ>>4V_auvVrtLq0?jupL^ zHD%r!ple%OuR?WJG~N#7X#R0hEPxhjOX%E`yFJ~#-DEd69q3;Bs3fdQF_0EkX~Bnx z)E1Fe5-*^hwy$1M;++O91N2^l)`@+Con2{#-r9Gk;r)Kszq;b5d#$hbdTL7b6@O_X z86wf>ok?OVE0#{~rqg%Rl9Tl=2o;rlW>!KqpnoKP{p5{9CSM;~X<|OQm4xQ&s%eFq zT4A`?VBc_1#sA9*U%BMotI%h(=zG^`z$&iQfQ52}wQpZHi5gc|85ahM?!NlaN6#3o zy!0BHA5kTh#yY~B-&~JpkeaqD{Dpm;b19*fDlgvIXfKq;QEgaRNo%m=#|&z&2GiKB zFpx{;rdm$mCp3=j-rjRPb6%p6O;(JuADZggLphs)iJ2!+(90>z0+}Scp{vMhkC5vs z)9O50)JK!7+H{FcJN&e`qd~eWV?HkEEcKQ3QXzRDAF;qvtZ&wWdxyzYP)so%^PWv< z&RR8FsvD)fl$Y8n1Jt>4axz_kzJX>QKQX4CV6v^g!u4rxKv~7~fzf?@7w_#9sm+zN zLZ#&+6%Cq)4=9@IJiXcwo65XiW))0CduZlVXkNs^vTqh`MR^Uas7MYhA8f1ejWtc2 zdkZHLzxm2B+EfR)h4N$#5~x{B%$a(4QE8B_zzr%reVz5LF_$+}XOg(&P2B=H4bvf; zr|!MZazYndCK~0{#d0!BePARso-d-s6DRecTZoZz!Y>FQ^eTp;H=i>=BYjlS*7Uk6LsV!zliiCxD68fjQ5rm~XO zb)+-XI=xJVw;=hCJZ96&G)Cb+^1eJ5DGI-8QIVp-_Hzv0v2JCtuv*h$-!reA({wnZ zj)@Yha~e{~{WQ)mN6idM_Uajz>MLuC#s0LjP;R56jpMMEq&M0SjWKl~7fAUDFn89Km8gBZ5`LdVZyNM)a_EzOv*uEZa$cL98M zX8MeDZ7KGvVP3=1krO00C1nB7Q&?B*sPC)P`>v(lk7w!-sVwaU20I45Y?H7>%j>Yb zpa&?gBdgqJ7&R-?0Khn#G}9r}>t)2Uo2*4PL-VYxD_icCJ?fF#icE$0Sfemm$@GO8 zMzKKi%9Vyp&(oZXX;|DdNwezg_O6mSZY@=cjatRa3c1wI26TxeyXeg-@(QK8(5R(h zGpD0z-1O2RF1nkW#;N2reIUB+ef{gyO=4Hc*kodt(6^UeA6%`_noBlS zH1*xAhPuBJlTSBAXK%9NGGu-;9jwQys7u@eQm@5M^V8=_SKnYyheqHox4W5?N{7to zaFt`mj1*8R;OIwsi&N6+X(?&YO`xQ0-GJZQcC%w5>ZV9c#aZ{bRV6VcwG^0U#ja;A zX;|&`!vS;N0eaWoI3Q%S9}+T>d}dL|l$>WNW2u(D^5^m-EwpLEsT@@RtOBaT9o?Z; zzzGIccTd-3*X%dB8dvDSr<>mqNd^WtAs!zW50h6OJ-I!BOfG_`j^%%G+zjlCF}+_;)aWTkiCDXn3q z)~azT@Uo3E$II6<0fJ~%(PQhk_F9GvX8aW=<3v>ROr2hwJx4+IqD+ELf#F! zSgSuKvp1WU#M#YbPEsTRsxp3w$|{oPQepL?)~*AAw8D_x-j&F@nm%L+uK%%_cr4z~FWm~RYmjm%DJKkLJ8Enzi*39q`#it4=mX(Ia>$x5xRRkeqjO;du^KP1Z4C#Gn8ih{aKm&iqZ$;?x~Rzw)nm3-qzJB(#` z>wJax{!3IT%+P(UTs~Wqc{kfj0YG&=4CmSj^SHO0t~L^E;0cE<5>IS0qWalXKXc(? zen_^WP5im>dRT8p;?^75Ct`Wo&d2o>OSkG6!t(>o5EfOTtHoy$5bF`k_R)dqUGN*}jzux;+ia14u&=8A zU1NUI)vqPB`xc4M`c>VhoWce5%}>buro+o9w7GduP*X+D1{B{*rNfDaj5Tgs!_RHh zXS)`u7OZtp@T>{hW<+jIw25$hTen8`eol!BJrkmtVRfq^vz228#6(+het-R7%1uf0 zJz_C&%f_&(bfb_)ZIz`~ac%*ZP)mA_)!b&aILukc$Ot61t$#m#Z44Sns}>Gw+N)4hfY-}9Q|l+Nj@ zpSD?FPBFk`W2I!6gC^^OKj_MG*_vxL<%eK zKq#A{fRVq|#Y@w{*yAx(tY5|USJoR=QWn!iEn;Hv%p$8+>r*URc=&xFlPZ;w^Wk!U z6Bv!=Iw6piYCks3O(@*%TXZWwx52o! z*gnXLNjP?DW#2&i!eR2;eTuS70ch^*2kA=J z;DB;iLy$I9?>uXaLC9mY-oN26VTDEw>;(6?|5+s{| zll%yaF~4uhP_LwZp|)p-s|mDZR`7wh$j?I}8B~HW?lrYCPIG}L zY$AoCs_RI!!sleLu&%jKYA^P{e^#l4)JEYmA)AE27=arQ)feEGQJziv9HSTaVV zcyghAkWp+?Vc3vNqQ-b1&V;+$5r6P&@`N$qV6>65h8zlP~+KWk_- z-H!iBWl-;6t9Jh#uC(=cPZo(@x%DKZ+#Z+|qcq92IHpvAU+JAhC#eI#z~HtOXhoPL zG30VD)pynPeRb`0w0`#FimiGyMj&enNpraSRqtmpIq{p-9SeqW3r2JXrk4(naRmSSrnE#JWmM>!Z*}7;&OKa1z zWvxqFmMw3cyqh)HhX!}ykzn6mSsuH{1uB2Z(TlTA@N+YESbNw zxn;poWD1`SZd#TsZCaYNEMJl=UXm=E)6zPt+5erpVzKt->9Pfj5>qqc&fwwuPGRfx@ckycKL;*K7B;t1xGtK`u1{Ig zvTROsYqJuWG%ami-qO^3c%m^dXI$Et>4C&EM2o*a3CLG<4guaS>*so%vIy_7a`>*jcc6ZYZqQ#Y>u- z<|eZiE@?iTiC60pE9R`2lQcKAG|z9Pc$OXAI(J#qqB%)Z%aTP4n#qmGSh0BaoMm$t zE?F5AmbWZf8ld;Ryk*f4+S^&NbaqqAoFJGrXWoLvt;?GhEnPS#nX{NHYaY&8NS4lD z0(0g31ub(N^0jF00+>rz&L#!3lcj9*vM)xfz&FsZT1JmIckRK6(O=k-yBZ zI@~oFHs*TLdCf`Wg;Qbf#EI*7DFE5QhK6QMbIW~wY&B|ED(hb5VbRNrm&X$n+0IUD ziVRbI{q?lgdiFVcI%Fsd5S-hFZl(wqEp2LUX==BCNoL1sSh z$CyLSh+i(&lY4Ha%sEJ5Rk3GXgU<7p7Rwy2FndqOY2T0WK<84riR0DArT!E~ON4Rq zH||i@&vfY1(&_3z4@sx90Y=w-)+Te^b;;k53yK8p4v^a}uaHYSa%s zTbMDuQf#jrqQ=B|0|VbMN0igKh;wSG&nxB59*4-(4OXw&WTNR|q;UooF$}a9XRy`k z!>nE%nXV12Lz1kphre|=BQdv4vf(+Os>Fwq^l&kfF}Yr|`WgO$R&i}tfe)H+8&hjk zB4Hl3df1MQyE#Yd+Q3KOnsJ}4?5aSY=9WM!n)iBMiqpw(TCnf#_FJ(2D zgaeI})6D3U)qK|EULYnOeJ7AOGbYnK3C-$wEy>N)Lu<6VYGkQFgB}W^T1y6h)43dO9T`yDe<@3wC`g!lPV3a=`c%7 zNnCkcC7n0e&ABV582q*fsvWu+)q|Sb;O6dTd%3$`m#*sA<7UiYpWEN3Q5EuQ#&mpR zJ+BE&Xc)bWZ68;cLY8NfOQNGAI*wq&m56RaV6@YbwYy~)&$!s(36pnMEKH@{_Ev*! z2d;#v1&SeY@b?afXt*+_euS#TCSr+}O4RKRy7gJ#?1z#xZT5$#+?CNGD%F9ZkYzJ~ z)Y74L5OH^5i_3v&GrOVO`s8SfJ62>g)mbmO$X8#=_V#M7eYnBXUGmkwmiAM-`vxm) zM{23DrpQ$uz8s{=tSu|gQeY~f{Tn7XHcWAe;i^Hg>`k#B%vi;Kcow!2%9f#8xni+t z946{sfd=upe&lW-l_8%SSQP~>xAF*CC-v?)BkB%O@YQG7o|h3v`>pOOI2l12$gUH^ zkJ-2iF;iW6PifFn@>_%)qf#96`5O;z>Qe}t@Sruu~?Ip8d8)_uf zekpEpQ$?Ef^w|DUBbVB+iBc^OHcTsONEU9|uTbPHF0~DbhhE=##62(VZncIEh*u}_ zsv#!+4->6!-k()T>O7On6h66OF`r!{;-!RcHsh7kzK#yffV71)+3h|8r4|fTYD`IA ziEF~)Y=r&$0w=5^?SOjyHOU3Q0xa0VSq{+Vu72ZB^JLm4bEOjAmMYL7IdKD_x zZRMZd7WG^$t;0~2jz5K4pcCRweRi-!$IW)W9lQ!X755gDJ|y51Jy?kyez=%A+^yoF zi6sLXLjuF9l~$)J8xQ;&l6qP^EwM=a^~Ms7lPq&5s-a;FwK&_q)WN6f8ycsmf7rZu zvKOmRv_{~}tW!CWH38iq_E*qj19Cf}zMCVdqr-g?_ZEdaTi1aA)@^OziLTIhv-rOHr0~R=65j-ToF??ytX50avlVG#(YV^`zy6UhN21yJXQkOTvqB zSqt(v*GaVAw8*YI5n0D@@d=j%u+r?WpRlY{1`aT*<7Rz2o|>;0Qj|&EC0)&R5iuHt zcCD``WaaDf&u=vNyTR(7l_RbxrM+%b7=06QWq~t0o_SZ#pgX13H4Y8c?gb-dwmYXD z>MdR1mwV*CUb|rW;$OQkNoC!a^J9jU?EJ8pvVq`kXt7H@=x$mt5z;H1xk1N9I_rY9 zTpv0Hy=(;HZqBqcM6Q0|SYIiQPnU3x&SbTiF9qG0b1gCLV@eylBu#yFecqMi^32F= zH+f@7$Q9+QFjC2kgm;_Vi&Cbv$G-|AT_Km|>!Jk>jY_VGm#^nsyR+5YZ3?(Cy{q3P z1=(b%8~9N_nZ=1zf+nJ%6m~qi()O8tVW*1hU!%yt?h>{FrwoJ<3rh_4YI=)9gH~P)x_|V>L@eo|Z#TYGhe08s%r!yFxB>59=?hmeOjR#)3zsd=Gc=srKX`Kqk=*JprLSk#gkkYMR-8Lcn zTy1!Xl7ii@v94~k?+?{I(-3TJqRP2iv}Du96SjZ-_~b8}4!!x8Rfu%*q6x{Sqx1NB zwuv=#_EKgV_UUDLFT~udwO4BEn}!xfxE@$gU!-c_e?W;MtX3t}6!%VG-hDn;2`crgxKvCN5e}r#3VWFCknnsxQT&sWwrcZ?+tnIK_Dr zlg=#e7+)4%J>(W{g^RKSksj}o)f;nRQ79MJDY}u^e}f=?|2Uf(WI2=WTQ@Z7^@}nY zzf;sG>9OO-sxdMOkDZu~J$laau@l(C&fi!bwxU!9J3IZ$n`T~6KYzk#E~vV<1U9X3 zbQQz;qL<*E{-Kd|)4?!|hjka7oo2h$You(4j;nO`502aHpF+{NiRb$4<-VEYq1;I=6}Qk=fJO zF<^dK#|!yxrcpOII@wzPsMm9qQ=qx8UyDjT3w3*44^7zoNn4hL$)f{H+2c>=_6$^H zh<8`gx+&g!-F|xKzo&=r1l6ymY2E$}`>x_`?f6%$eH*5V6;a*}M&fS8L}_JDv=RRz zcqLnki1yQo)3DFWnrg1TrpTlh&+R)4*ne+dS(lce-~4 zy|)62qZ8iaDGfB0I-2!si*wZExksR@VY~z6){B1A#CHZcm?M&@ik`@cN5XY9s`Tc99SRBg?s-tzIJ(u=4bjYq{#;bY_qg%2awC;h4`g8%el-pT(Qruj^;_Eaz z5DS(VD^&U1{ysB8w);97MsuIk@7!p18D9k-y@2~2)H{C%I#gQjrn1Z>V)05e;V}Vr zH-i;$7j4zOv*p%;uC{Vqp~1yZ=qg9_dRGaE;wYy5+)7R%tg;n&- zp)&6=a0)Jt`3<8NtV-AQ4Q4-Bz$W0D0;3v14~bZaO584wru>eTB5C$1>fIIX>gguS z&xX;9^!A2*6OAm^?ybKZ74k`Ie0S|b$)eL^8<0V0|H)IxY~K@2OX>0aE?Vpw=&&Rv~DWjxDNcXsdR(be|=4jo3Qyrm*bWP1HLnhe*sjIT_P9nFE< zLdc@<>WbYZG|3P z`R#alKbs4WX+AU0T=BT{wCbg(yriF(7|4#!f-6@4B7|lHc|E1ktB`4%NLktIzTeAe zu%2tJ8zf2D>v1lGtO5nO&#KMnFr#-NP;Lq=jD|z)xKBLrjS-&(nR$6-pdG3k@~ILl zF?}L0Sy6rX)?90Q|6nU^O|OMJU#p@P-!Iv$Y>0(5(KCf2M1gP zh81R)R>CW$m(H*iF5nv~(Yxa3yxdoYobZ-H!ER57Se3i7+r@6=KTBy+g*O%2-A%Gw_bqe4$C} zGyjq>Lp&p+vz5}sQw{sxh|^qZx&cZ`R!@u&N{91Q!d|E_i;$`HhlRR~M!uelDcsg;;BP z@1md0oJJ?%`>Xm^Y7@^ao@SoeJac&F^33Cz&$EE%FrLGC7V<3OSE!9+>E=0+XEjd`PcKi2r;n$f=Omso zPlacIXOQP)9#)rY*7B_5IfbW@XEM(eo_%?y^6ba6KhFU?2l5=mQ_s`N^S?Fy`|wQS zX`0nMd(PZ>^A{X;_`*etmn=PE+47bZN3J~T=wk|P?QC3jc6Fb)x~I3)*MAbVEqlaNt4pt^d3I@ALmL|NiIwzZ9RDGhgEWO`ajFLtc8xm;1DXr_Ttg zNlopDkz0(~a;vRJZ!>1w?Y7@x$Jf1nr#HND=UsM{!l5tiw)-A$dh=V-J;&~~cimgZ zji2zgeJ0j7Oi~rvB&`2Y#w(|v)W3A-f0+K4{tMDyL%RN}+zX6bG0qQxAHh9}dmQ%! z?n&I!xMy(B;-1Gv{o(#1PV}vPebRgkPT%g=@5Aka+XI*4_Qs9JO~f_grs597O~=i| z&Bo2gEyOLwwcw7z9fvys*MZB2{bJyC@wW%pj~l?P#hr>b?gre=xZ7~I<2K^%#@&y50GAK{HTu7+-v4heuNQK4SncN_+#|S0agXDk zz&(k38utwDS={rum&-fE|0C@`#;J?&dvN`@0o+>LskrsH4Y;#$=itu6osYW!cOmX# z+~v5dao6H*z}<|y4R7zTyAXI$+zq;;8oX-`xIV zKEKxfUu$!*F1+^lmFq&X{rYS!%a2&|164C|>v0?X56x`{y&d#+(EMIovi;0Vf4KZb zgJ&jgJ#Hg|FMr%14y{4i4a76~3#~!c4Xn^3pf$l5nc$#DuE%ZkKX|vrO#VV|0X-_g zZ5oGU`;9JM$td(jZR7{I65LGOdK~mt&|5)o1-%utemrw)=&hl*hSu+SjfNf#JsO(d z=t{PM-UfOb=rPb^pvORu@nH>@{?~Y~T<2cPqyPClvh7~wq4x9N-2P*odaeEc&)2P3 z7O(yNf4?mFwef5`_dD_XG0^RgI{>F`A<95OAx=9?8|1atZcp4;++Mi7ado)2;>O{|<0jzVhT8`>5m%3Ez)ixj=ual& zrr`G7B>ds>;x*p?`}O~SYZ=*guRKuu`EPFju^f}v+W&vm`Ex9{|3CcwD8raWK8-jZ z(~!oa-$XyEcU1CmL-#;mkm=SW_d|aoM}IP-ljKvz@5mCrA8+Vgpf57IpEk0I$UbA} zna~$Qx4C#F$tB?SfG-7WWK`TQGx&0YuK>sNT?y8s^vx#zR~fny`fBJH&Swq2#^7BU z{$rSX!jEy;8GgiXf&ZinhmjwC#3}sf_jBMFuWP}26tAs_$L9^b2lQ^(SoYXtC%+ha zPv{%pwM#}{hkh4R68V?>dgx^@RrPPk$!~=2W=azE_r;#2CqY|#Ut33}9ss{j4b zxAe`(f6LS(+P@{||5oU6Os%5);9PiL%<12jqra4+zYJ~T|CJnldyYONm)@@;-;$|Z zjL%HumcAqB|4!%|Upg?;Z$|&dcU9?)$j394i}t<-ZS(W%IeK<3{dXa^`MC)Bd{e%6 zBmagezr&DQ`X1!JG4gpi`Mo*+Q*-kBa`MGF`TaThH=u3$zL}%H1#QcF8TKr_2lTR^ z9pLioJnHWQ=-c|fLh{G<&E!Wy5A@!ZjXYb(5UYoO5)n5Qz z?ya_;cIZF-yV~9!!rq@u`9BPOHj!KKbE5(hqmSYlN|k1Xj{JTAUsR|47qJzry;lW z6FL7shra&M?XvW*NB{b_ROw$Jx9#nh(6)S@%+c@8rT+YHS!_d$DxGl^7Kca8xXC3{EO#Y{wy+1=Qd+AUoKeaq6`Ixg`ZGRUy z`&IvA(7&?Q*LUeZ2kpm4<`wAP<;Kb+`6T#CH;%9}N9R6h%>|wpW~nax7sLNF^2i?r z|7@3Mlr4C!8_$yDVsy?5Ha`R2n&r6c{1u)1T^nRK0K8|2!`9%-1HJ_Pi2nv3lg{rp z;AsC+WB(%Xtf2D(Ix%j47se^v%h8GaH^aLp=>G%U5%4wW#5u<23?7Tl-9hJC_-8QT zkj=f|$9c%-;YYl;;a_L?|Aence(Q|Q8_>BT*nF$u-)O@6E;y#~3kKg}@WTe*Wbk(k zzS-c14BnP-V>xaIj`{pWbYeN)3XbLYB08}gw+F{^+yNZR?l$xz{ulgMjyr;*{Vy5& zUk1m#-3gtT=WhVVy!{F~5x)_B4ENvQXn&*8c?tf#A#d-1e=pln%71M+MgHwZzXrY@ z>FkW(Gedpe#e`LhP7G^T_%WVe!%mF<2xDhAbYh&pZo;|}9Lw}>gRe699)mw?@Vy3K zZLr#Iw7I*9|45VG`_YN{u!Z422tUU2n+A_EX?c@L@3+v2>D>cn6S15>rt5=Wa2XoZ2QOU zjNYTzx-0nkAvpGr2jizX@V7@lrg=L2t8kiI+}}Sc*}>TQG5%wj>}dSF&fwRBZ~S+) zZ*R)Q?J*OFos8|rO+0@FUKQ&18_ELY^WaDQzvDORFMxk{$g6+CKcmLCvBTiU{C^RC#D^REOgr79HkpEBS^o?D zCxe|mjZO{u7VW%bY>qWL3$cGs@Vm%_Rg2$PPxeB8M2PcZbRvHVINBd!!rI%|{}tiR z3VydR<@mJWk23sU8~&Dt|CHfxW%zX_tfeL`Z-pQ8XIu1RJhw4;YjDgr&0+N@Z^wgU zdY75>ZijwM`w{SCxj$#(Ru8{9*qLDBu#*YvZ6>UJ3~n^>pDY~gG#Hx`jeb42Bj~(Q z_5-d-I^5HtC&?{{4oYkNkeOcJleL0NRE>6Mak1 zkbk3JpR;#Z&fct?{^2?KLWPHm`8h}78G2Dpe=)Qz&jskm_OsYv?ZZX>5e6?Y_%MT) z8hp6HE#R@C?JXf}J?i(4pViqZLPHT)9{e!IcTjQ(2^hW~DZTaC`!4PI|_PB8p448LIb?=k!h2DclXHiJ($Ivs|8Cj7fY z85QBjdCQTMm#y1-Bh#LM>i!1$vX#gq-2r_RbT_tQ+c+9}9@iKm-Hm@sACuGXMQ;5c zo0A`xv)3bgrf(}jf0HW@F}&k*{@03zbZe=`LEI^BDe8b4gHN7Re4WN-kYP}k3Fkj z%K7ih(I3p|_vhs2BDe853Hdc#{fYVcZ{(e({=HlF>Z|e(L0kQ@{J*0r-;neF5$Fd@ z{=QRmsj6SWzm@NW{Jt>Oo=^Kb8~VY=tK~C*zNJ5oJdO?L8$5_!?CbZV{YIS&jLymE z=+Rg*6`eRvtTFt{(U1N3Ck?*D;7=KRk-?W5e4)XY8GJQ3#_iJvuQhSl-^6X5;kUq# z^ScjkrbrJHcnUIbD*x z3+(G;lB@^EynVO9MeM|~cn|!0LcQuR_B9T~eEyn=&nm|C>g?Wcc4Q{652f!0`JG|3SmAz<)C2 z=eOZUd^-8OSKxmDomh_N7`(ygoMFoAT%+>?6V{Ine#GF%4gS8tKQj0+gMVo72MH_I zjWbQ%_z3)1A3kL8PmSN77<``5`I+H=*zlh){EY_x+~BVo{0oDhH24mKe`)ZY2LImR z-x>UCgMVf4Zw-FR;Aaee+Ta4|iurby$+xcKH@Rtp~&EP*7{H(zPgd6Mj zpW#QWy|q}!-fQstz;}nf;{67n1HPixk1roE_*|p&L4(f&-{yIA37!Cxk?eEVOqXpFH)Tr6hsjqT-5!Gu)x<-@8f zHDKSxix0PjpShTpCVYq8eJ!4E|8pCh`KF%jSc8pWr%CteUPm5Tp6+_R-tb1EtNUKZ z8lL=WKkhiglb-hEN_?|ZUpnQpzvK}y;CY=1S9-d)_anp8-FDsG>!3|tPT`C-GKHnP zdV3k3Z0Nq;O2d<$?&%$6c+%5dy*C@4^mMQ8ErusO-My>Nc#2U?a)l}ie|3xgN`tR* zxYpgMzuNG3z<&+1maX_#;V4a?HS%kWzt0)|wFZCQ;OmV3^@e|g!8ZmS6~zd`{X&ku zDM#OI{N7^ltwB$334GD;Z!`Ey27lS;f5q@`2ah24^mfAbpszyLx;*jp9ndxWr#BMr zbTaN22HlNLR-4gZgC4;Skltqay3tt2Cce?sowfjA%TaEW4&^FvFa{AwQ_Nrn1!1?#__@R?k!+Id+ z_fe-?4eLia`p3{V?8kES<2m{#IsZS+$$yrkpUCO|JV$>!7vEnXucZuP{rRP{SF0h& zmC2KiuIA;ha`dlr`rEs)q^kc^PX08s>X+11#=ptYzlBzORJVWUWYuzb#?jTh{XMjA z2mU<#574&m|Iz9D`l$2rXQ69(Pe^S;^q-&=8}(yHeqFujb2(IsgBHw)yaH=f9c{FF~tMR37Ue zn};>fHjio@T@7mlbWHQefMZ#1;dHBg%P1$W`rQ)R#!LG=HKuRc%IR0rxwW(B`?=8$ zS8Z+MbbXr~6L5^jwobPikL{ei>UVobSNo|Q99<1}#~l4SXvH*^(H*y;$&?x*LHVv@@l-s&?zq zHLSNd-D;ksIsGegVeRSsSK~4^M=#3h@0GK+EGOR^x#kRNs{_nc>KyIk{#Jv>0l@Kc|09#>&Fae8@EGp^r1O=W{z%xt}*#HD<^Nx z(X*YtkIS5#-?>Jnvkz-`KD3SZqq%ZjVEi7I(>)y8rt$Wi--S-D-jVaqrrKn=Is_iA z8+IlqbvC`o>G-vj`q-CQI1RJTVqNIM^fq^)taP6K3D@pDPjk4vKTHh9?6UXt6I#ZM z8PhnQf2vR7Al(jscX4=^@K;3SIDz5sJ!WrMa{9N59mA*cfAHU$+_QD=+42>ht+uLt z*=O_!^NbuZVw+K;Ms2ZG^&#ntDc86su*Be3w^r7AwS8dLV0RBc9opb2Er$aK`%AH@ zadivu^Gj=!BTPNgJm~;aFSezIpWiboS%yv<`Z_;Y%>ITRhIVRAO|l#rTR&jFKX^oK z;(uR~CG~*~{6tP%QTuiMEPhG7yslyC;6TIDLU(yNUXnKFUoELN`QY-}q&=fKtAOr+ zW?Aam+6mC#$->vXqBd!%j7m;GM~~vP1=@c3?gN`w9N0{plH{wIE%{a|{Qa6D_TC)du$%+zVEEwMVnZM%MEgog{r=J(69^n(Nq1 z#{LfZP{`zbqAn+U73D%!HO%Fg#x|2*L&{LPOZjQs?!v29pWRm~`d{3$`zfxJs(UxS zicFGu_EXrt$dzRSKhcCxzdFY66m`2_M@x<)ttvg0e=Ns#&`I#iPUgo`)s2eFms;u$ z?*}>T-_##8_+*3EI4u2|KH zo1;G%Xnon?Jh1XeL#A}sL9^BB=4~2JKNM*GBp>D<*_FSKfK|Sl-^t(k(6XbiM0^x1 z8~jQ3L|It=#-v_TJtlP8r`0yWrr|)0tkw48_?#Oh!9hV_Nt~`4w zv+MQWYWyp%<8t))96cdN|ImcDGxlE`LXSwU3E`=pf7alqz)}_eW8kp?zb)7o|KsrQ z3jAMZerpot`vsYdcWrhgXv*FQ3ooB>6p9d9N@(0d5cYZ-)O# z!@m?f8)MS{i_!TM__E-)J`10(f`H?h&Lzh0#o);QD_D78tJrWm}h!MCAr^X{J+P5Ux>Q^6xczUcd>F^v5T-rwjS zVDLz=4}&ks7<`b?dC`PB&G7$i(xdOTMmwK}AItJzM&~-iKiJrr4!$eo<4x#9JOlo{ zbSNs1t--T`&hL!PEsdQU;m5hjR`6q4-VA^5kU!hN_xa=N<1NVca&|pE+JtjRrpuQ% zz*__xqrlPjo%o*}_`4bXFTuYo#CInASl{k2`dHyOM;Sda3c$>6W!H`dRu zfnzUFMHrO;(LwGH^4EC+Zy}L2H%HHOv{e&WBxn@KgMkb z!~YKa82<+heij_#upRmlKWOaCHsO93eoV{52G21%uLH-r`6qNd_T~K;bWGdpO?cmj zAIonp{Ft^M8~q=FBYzikVw!gX>rt7_Gk9mC^HcoB^gnL!Prxz1<{Q61GyGqGW19aA zj(PM3^dtVc(OF>ZJO|&Ve^+ENZ~mB*rABs`vGGmxVxEnGAH)0={FrBl!;g9M1^9Y2 zR%<X9IyQMCaCFWV$b~2-&Nc{WSOROTrD!)BM~Te~a;_NBapH&o$<}V8YN?xg^u^ z^OOsX+{SMydSBj*>-doAd0pXqCkFfv(TXxTe5qpS9Q zuo-(R(S2j4@9iCBXxTeDqpS9gfv5VQd7|>~SZI~6p9|I|#|62(9-ouFJ;=P@5lJhw z+Jv7E)+Q$yeXYj}f!6%6&ER%}JB%O2xd^TJ@h4ejWQuENj_wM&F)iIeuJBGYy0W`^ z2wj`>1?y`zHljVVA+m7Zu&L{8P3Zg|yn)+X->I{Zma&&f6fS*%BAK-+qBrqNeDI%|l2ZF07eD}L_{a{eUm z%gNp!WHGFBplw(mF!~DX+#&kx>lnGhIxooilYA&A`!KY%{ShOV?en3lZEr;K(IIqg zvId)a)VFDUJ$rCe(k>5yw<~??sql19-t+XYO5Fc@8}`bMihZ$PpzGf+A^SK^kM>}m z#?CDve9K6&K(9{1de_$ z0Y5d;$5ZM3JT#<>x9HD6YkX0>d!Vm_R+h--rQopvUu^V_L+^TMJ@R)U^kvX@1$wKK zMt}=+8mxk$sih&Cou*HAxD+qO`iyw}v0?4!4cmuTS%Pnw5bvzx~R6A)c=X8*v?c zS4L|;6>Fq#xHb3PMo;Tt<=Z{*)YjG4-3wNEs;|2btoko}zro)CE55Ox{$`H;7PRV$ z{5_D9J(#1v4IRV&4mgJQkipl0N1~;>G}2ZcwSyjp|6QDqi|@N6`P-a#CyYad$idA?kmOw%Ddl=|^|p$~>u`Xujw zo^I%mLeDVzdsb?bOa0U<>pw=W9hI~hp7tq@f>+4#?uK_}j&~0A|185(KR*EPIntp= zeU$9=3P(cR@-6eiAogMcB;%>WaUxPiRTXl6u zklriQqcGLd9>IPQbO>QwmC2-`Uc#>t4@EW;*MS%H3r*mW0nakH+2Gj*&jIg^Kl%Lw zX;ysH{*+gbLVKB~=c0R#dtZe0fbgAq7lLnGfwz0!+gJb|!>3!tKg{qCmwxcOP&oKq z1lE41^cRDp-zA2>RJhOU9AWS>@Ln#yNwOTgHHYJ}(*j-)!ula;I6dgBfInt8ALk>% z@4v|FuN3~7$443d(T0BvIQl&nJbJFzKhEIe!S5aC`EM6??*=7FtKpwu_yzD;WVqto zCQJt-+%C)@A>09;8}<&0;)k@X0>`qto%-4dt^PuOx{R!ga{QwySJB?N;1Q0?!J#4BilM z1su~l0M;Y@f0(#ENje9S#XOSjla0SMMkd|A=luTO(CSNGgpO@N^jiFTI!V@n&%N5$ zt5d)qc+|(|9S)ChaXVEyw{7Y0Y2b6Zyv{p?pYeX*1%Cfj&tESb+SI$jv2MQy{N7Nv zPY3T6(*954cY44Z;2$>I+c`tH!{al-3wQEioh5vs$7h4*<6n9BUg-zF?-O3-`R|vG z`!*f%1&<72eE_^6;B&#T-hL3Q_c&zpJa8MxTW2`s?e!vCq2R@NY2u8-+tZ z^##MfN&1c6{>|VRw_CvTL)>mPI$s1wJGTjkzVb`pw}pE4W#I$8&98v3J;CGK!OuM5 z@mIlHh5qplVFpv>!=2!0XQSbN4SaTp|JQ}X*mKwa;qL3>yPW?2&$d)5DnbbFZYb2c zPfcQ5tH#=9TQ`Wcw)fh!JA1!Zt#VuLbD#U%7D7I9A3~Iy$bASQgb+dq(eL>@=Q`*8 z+OhJU?|;9m$GbhBuh;9m&h2%sbDis4=ORV}Vc3;I{yZ?MQp?)_+xGN=uz!&lH=qpr z60p6ltRfDsD=!1v>&GhsuLic)l2?K4_2V_-piEu|wm#n=4t%}|Y|pp1fbDhSZD8wj z4Y2k34sqb~U0{1Hc@Nm0&ufA0`TRa@f-?DlI4HLdfo++r1J2OpgL@6M^?n}z2z*yK z=lMzf$KYu}c@6@`WmK2j5x|H_8MqvRC66we zKDInOZ3jcK#sZXAH7!6^(Tw`|-D8$7e&d4jntwc!kLA3#fbQ)IWZu18!DsYbF;G{_ z_YFdBd^)M9qNu7k%yM2Il=ogJ*>0$#PX!+gJ|N&6m-616^|%w4S@ijt@R0@kA8~!* zVaL<#H-GVD9GmRKZyv*cF8oe}k6ppp7CDAy+O~Q=*?({GWW3&QKsdH}oc`*Iz{eiQ z-x}C|3C?>(-ly~LSI#y;t%iPMz8oF0!!ot^^}hyTEdK-CmdT$Q zb2SI{#F>iwTy4wyO{{+c-$`171vD;S$vm;$yFXc(vhq3t^ zHj@JT?Z9aPZV4M6v}a?o@}`uJUB{L&Jz86oZ1VTt!<)q-T>R1aTVMaEo`%tnuC8T= zmKfxV<;CX@y9Q-p=SEw3yfrxMgTZ#wI@5N>)+egnDTEe74D}UwTdg;1^E!aH12@)* z>Splv+TPR^=TX}PoMrr9%Eenp^B;=Fc}S}(Ee+R>sH?zou>Xsn%&JJZHu~SI+DlMg zQPt$II#ib{OA_P7S&6ELE>~NQ3F@#0<(i-l4>+$`tJh$?hNti4xap%epx;S`%=RJd zM|(RPUI*~bo8avC^2=w0bEbxCODn3UWlS#)*KjG@KYA#aor3zB@XktB&kG`Zx?g4d z4`VK}FXAkQjP0WXaJt3`Y6;TY4}3+S+rwd_>ja*G!s57UIc)ao>qA ze~1Ivq!)YB3Oopy2gAPse@$tr4Qe7eEnlu-bPe8rC)5p;db9pGT8fs{R!?IZ_6pL% zeq=B7BPpQ>T12QiXcGTu2^`ZE7e&<(K{&R}TakzTou35wNz!#25;9&(RrN%mp>ppbj9LIeyFb}q?cC+vftkW5Og5$VP7C1-XQNY&6#M7Ir zETJ1AberIRw9p+d@Ug;f4SeJZ-HAfC4e38gb2BcepN(hMf*%fkvfxjGpAv*;yX%8A z6bc>!kB$E(mldN;n3uQp!rqai(qkt=I%ceEt1EiDKCgEgS`$wVr6vlW!;$_X!Iy$h z61?Xbcpd?c?n94V_zWQMos7T5b+xtOs%Ub4!RX|oXmw?IaZyD@eP~)yBvgd~K)8fu zT_XIkpAQF|=Op{kQpZg{&w8Ki$ygt$kZ~Ag!y&_BST{WyNyf>`T=(gk5~`{WRTf2y z%kbiPsHV0WgFfCmMa#mWAk85fmsi!{HEvuH%7XapwW!?1Z_;?G0Qn>eZ*H*xUXsP<%RZ|RW9IBJ}Y@pD?hZ9KJ}KH|8E zhv!lhGF!*2lR9T(uB%f$K2305XQvC!{;uBRGX$soOu=bC%j2gDPWv+ir~R3NQ=hF{ zTdHenFa$v{sR||ZVz?TbrnZR=cY|DF|;7sckg7ZAT#^cw5n=y(~*9m;Rz&8Lh zfB2*B#DDBJcuih@7S<1dv+gZl-^{SdjxKS%O_X$PVcS#=nMD5A|BooGaZizSx1yCWkbb#jI49Y8uUql z^W^kolSr8qPS#Xa7gY15He5POG3^+}Rs2!J!#Zz`Qs6Ux=J7GeY+G5XG2ib@P)nhE z+~ZG(@LXTSG(9Q8FBAAFfqw%w-%r6B9AZSs`gum+=YV-oz7^Qi6V}kvCYbMDNsJ1m z&GQ2P0c`3S&$@t3+r%>f;8j6fF9Vka_)p-^gSfT0p88!!Gzfz+=lsv;RCz2ln1z-u=x=- zJlF>=LVdS~4rY$;0p2`#9=05|Mu%o0?3P^BT>T22DJQfO^p!sd+i!t8YoC~tK)5b} zf7S`ygCL{CKcG8sbFERrFcgs^OL6JXOD z+_VqF`+)PHekJ_&1-I?4pTJGMevK}wjg%Et^iHj)s4nJJ%w8C)>!P9R(oki%vbwfj zRpPd>y14PHRNx|6yJ#>{Lwb)C*Shv7J?2gOD&ho3B((w;QCz=@__q>ws-Yf7sY64R z7}16%g+oPnyLDQ)mI;YYt7duh*X6)HWK1~>@c2N@Sx)%swZKORJQ$dD#`2qfS)v*e z=k(zVQAXAnng4?n@N#IceX9_$4nB~KEaG3MTdA+F?oc1+>v#&l)aO!J49%;a_e%0f34S13|%S->6 z9-rg!T)~UqQT6n)qI?`EkrH5Hfy|}w56St zO*tkV`Nmf?g0SZ}pLibyeeCRja~#C$I%T=F;flJFaB^{3ZAxfT5qq}Db?nrz2g4j~ zZ}u-cSK!-$nKq{N;lL;HBLY7v@M8ks4{Z901hw_t=4z?qc+UdZ`hCF3jolN1FFp_V zYK|+lOoV$%$e$MSXPg|*m=J!R&^-jqgV(8fNYip~(|;L$nXr9U=+1)el}?8_fB1dQ z)2|S`2KJYO+x(NS6yYa=KM!uwg7*UizRO`et3%saBzVQ;SkDM<{gPkf@fX2O*(Rv9 zi0382SAwtd_;ntC8Ql8k`1^W~zas1x!ry9elMlp-k9oc7IMx$7TYR?@xHAmdeqIBX zalG!hQf~dpW;Q9y1S?~H;G5VLy9{(}m^4|6*C*yT1QT^<=Nz=nf!xqRG zAFs2&IK9ckje(9!$C#&I!8uN|_mMnDesf`B`P}Nl85z&H-vb%r`NM@Ve*Xmb{cdwM zF~5HWKJ5K2{r(-u=y$sdWBhWXV&889WGqKnPKl7Q45Z&AA!FVdS2NEa&)Z!Z@z-30 zWx2CGwGcA;qpW2hW7>CheoWe130-SX*9KhXi|N?S*~H3g_rQnE7vpRj$QWlk7skZd z9^Ci4hqH>HA#axcyd=Iai;9O^t zCc>r%I*xZZ1{^N<1s7n=h_F3M=(<5SLU4v1>G7e0cYytojw_V{Z1bKBY|D9wkoOky zfxxz2`U6iwepzmVfqA|V_X6g@a^QXcF@m>4uaWBUQQ&qiWc+Q3s;{T-=kY<{jLVku z5gyMB?AfO-$2H4V{bekvU8D!e8_ivt;wjWtHk{T|0s>4)%-J4ot_ek7EKQIz}!`NB!s!MNO=iX zF_q#yTHHO<>c`mKBOx=((L?prlN^U5E?bsN1CI>+3Lw|sBXz~aGuvR z6NVk@mu16nrQj~@@I6^@`j`^1~H5Xw|^Ymvry;2c} zv8O(4&kAgr_8E63s6mcF z2Q!MNsG`thOng*vX%SXGJm(n;{>!r#Bqqm#fmuwq>a~X_Gj$BF2?+~ zJ;&L<)rhonUW(;BJCL!@Gb7L-K_FQ4xyu{;| z20rXKaWVW{7RcBaunk-;INQw?g0szC32x%RyO2W1b7P*M6&ummM(EM8D4p`OUyAGoEW9#6Mr?o)dV5vqO9W zKQHhL0xxyg_B0UJ&o)=Lfu{v}@|PUPb7+BI7WfummYwza0JzP| zM%2?nkG}$Lp5tOYGRkMQ$6s|Eb0WYzzvz1{e7z3NYbML@4PdkW0QU#by$Q~Px<>=d z^J919@DYzc?D2;@{uVgnWj?mulc?SneBiyf?|1fQT)q-zxyF;Vgltq%#C1oQUkrMy z6#bO!9cORO>GbMIv{y0a9`RaPg#DKn;9bu?TTkmYYO3CIwx$nZJIu_@Xy9?JvoZ1a z3>Bk8;M1LG2-#NeJH7G2_VPg>lPzB=v1&!FDQTpJqqJm0$*&0rawzm zw+haEA$BrGvpsXndkjUI7%-!XkMT-eI!A|#%ZjSXBb5=PZ5`6YCv+S(d?fJ4L0Wm; z=Q*U6EF{+Pu~gry}+A+S#La7>hDWbKZ5g|p=|5oMD>%<4}|{PAgsM^ z@kIF9lWh^4*Rpu(9<4tMI7OtVeB10&urr8>H}{eh_)$ zeabK3EGM>sUjDbUneX z-#-z~+6{Ad*vHb@m@vOPJHw9=wyB8%-0O`gD&U;ql>u4~2aO zxJ~~aLKlVa5rSvIc5h)j(&b!_Bz5+q_|`)Zj_vsu@B*h-suTDa z$9GYWfsX~}xxw_`0)OM2K0#$eKOUSqrlmjhr=l(MaQ#jzmC~w}N>(YDxAb%;XkUCk zDM1ar6!T*Nw_#88^e1_|&ht0H(~m2|8qN@|Dp;c%DphGGo&gob_hQvX9f7Fg$;Y z1DU-)I);;_I*hT&MV$MgMQcpkG<7FN%_xP!TGhb6YULm-?540C6-q!}#%ur!S zwGnnqXLrFF?hwHl&%uIIzq{ZJf0*FZA1XM*_Yj==O2MhG@_4o2^j{-5?bF;kG}G={ z2tDmn+3ekwS~(<&0dJ+aHlZ2}4U|5EM+GPFjt0B>-BmesV7t0j%sDZiJ<+a`T-r=q zJUhBW*Dqt*mv7?_F$Sx?Ot%nsB*S&DlU9Es`la|I()}5O z3>Q6F+;KKqg>i>&Sfg z!j9o)3*8)n&-Lui6T0&Sz5v*k#f88eQ*eIxB4Cyo=Z`ohzSwc>2PNz-0k+{U1-ALU zOyJ9btuJ1muL!uUk1IWXmB;6a@VuT~?Kt-1@@%j5_;nt?-s3j}ocUy5a-+xRd;BJF zo5!1lj@PqW99L>7Fb|ILhhshUtsZ|IytB|h0iGuKlb(K=(<^m9@bJKPIm+`Xk3TKK zE`k0ok3R#xA_!0Ya_|L$KMQWtLj7~#_MLpL(Z0vyD?Gjue75$d)Pum20{lF%jOSjD zzu@r~!DTvL0yn;}t_kT{?D19LY-b!>KP2$Wp4}_pw(RL=HMlH~SHWfZ-bW6{tV@>n zYv4AX*B!>Y_Rzfnp03kiY~S?wTi`sH#Z5q$> zszUm<01x*x#y;=Dj{OtM`xiT(p9&Y(@wHa{NFw%vwAt)qXIGlW!(~--IVVQ$ zO%Ix1Ta3`^0bNdJ49<5s-q+lGTas%6KF~b&PR56x{tj^ND#H2vHVDr;SO*#3tzbX< z5itGO`F_^($2yF;j(sBVdX3F~y9`5LpF(Ed(=hcy*=LQ&J{NvA2>gY>UjnlYFkN2> zyb;)57rqww8)5UUz?*;>f^WIZeP(BKQX_Cr7p|?r+j`MtJ>n7q?9~fD>F~kxZawn# zoyYguJ9hq1zuD98?dgB=^gnxiAJ6_rPu~%Go1XbU;JqO56+!yQ_X9Wm6W;6bbe)9m z0APFGGu?l9@%-uW13mk{JpJDuKghG+?&%fuHXn>X1aAAcc2_i4oju+Kd_j;;>bnZQ z2D}@1vCtn3zCrhwc$W{jL}UC1+wRnfGV1}}S#!+oA)N*%s500d3Y{&_!vsDY*ruQ5 z-V=O<@Y&1b$>1{1-rzRQKENxHG`2COudmSc6FSDz-{S*>?Lgp?APph-83YcG+V4W} zBfxpE-yiJhh6r6-f!hh(Uf?|h-c#U|0HYYykpd4D_$Y_5j~nW~dBAy%;Iki=`!Fne z;iG-dJ8&$zyRhMT&HOR1!yvD%##4Qq#iOfB!q~YYGaK@wAx{dz?+KJB!jmsY_+ub@ z0Y)tM0l1cAdwevwEkEjy12_9W8vAtcmguN#_#7{Mu4jL&$1^e_5VB&*S;v zOdtF9p3h?r4xAG9%in{K(R$vaV$VzPvEaORbI-L-FJKPNg~vNK(2sZF@oWJ46NLV8 z=udP!NgW6MN!s4byRAccP7r((_{oBA17E;Kfy0aiTIe!o`JV#29bX)SceZk)waMw| zn(-zYX3uu^oJa&1T|X{dG$lUgv0(Ap=T=~SLQ@0j3?M7xE8*&voXTRF!ru5FODRS>ARDfb5>b#S>?rLm2wznys=g($P4?Lb+|_? z@%R*-H`BLIb{P8%px-JLd@gu}2)h!z%yFz+0%pI-c&MuaXBk;u?eQ8H*4UrwIOa(_ z+ghhHw&jjvuEg2md#6HPC*)Iwe43C?7jnJ+8=IRnwz}v|G5^c8JRx#~xLDCF_wbv=mFE%)1kPq1}B6>A5h>Opz8TTxYpAOFR zf^!M1>oWvrTR1bYw`-9fhU_fo1MhMV_3hJ3LlpN%d}n|aF*4=+c77k zZLwbje5`*ZQC$gc`-|4A6V+9YC#V!~SvL*maM4=KPLsi(xJ>!2R}(5O^KqCF4+r*` zgVJd;=l?u`uNL@PVEat(4W$3NKxf$<8kCST*8fpQcSW)Sb{eNemL%&FYt{5 z-z@Mgz)TbCVdJY9nyB=siv0>@zszR+>(Z2*3U;8Vfx z)ZE0$`GUJVzR2Tudwi$mGCVxByqGVVXXY5V^U4j(^THK+u~2?EytCm83Ofieyc|ym z@m70%T<)bfUg!j z3jQj%^)=uc%+(3r4g7V%JAl6-cr)-f1>bUYbM=!M{orZ3Y_JY&eslGn(6532wSun%e_!w#@DBu^2>zkqx!~&rKL-3G!TW%JEO-d~ z6Tu$_UoZGV@J|K59DE75P5*kN|1+UK3;NFmZwJ0X@NFosF9hEJ{-DR70q4QC_y+V} z2At24&$_O;`bzN2!8Z!dwu>z~>{D8GPoU#H58t0-+rs|W4Zh)(qAI5pU@=ri@J+8K z3`%<2FdUtDV~1p`YjEDG;z(wGP8NEXs=g{ccW~b!Dl=^~|5Wr<>~tW8L9fAs2M+1g zSEXj>XBLj{pFE&f-ywqrt1$&5^nd;PWo3}`@0S+*CF?uLNc#>l(!PV#y)OT}ZYQX( zy|Vg7@EVlmw}Rh_wu+<_21zN8RQD>c?bWwWA0bWYJ7n+?NO@`rRJw+W+IQl z-D+gZ_5n7d9`6N$ zUv!WOOWs=O>8k~}^qmCGgT7jNy5``Uw)1;1*rNcxb^*WY=%XEPC&KP3aC_i|s7QT| zBitU~hZUMQ_5|*$ePHh=f%gKo6IoaS6vd5i__R8F>QApPuEn{D4dt){ zXGq~<&xJn2wdsH9FM0hhdBDo05ZcH0-04`Wx+u?TzC=e91-sf9x=wKDXy_3KPIGmt*JcIqj1z&`6Jjmlc!0oxE_oVXpp^hun z9k?sv=DBb%@Erl}3cMh|Az+S|Y10LGcz_Q9=A0?zhXeDl*Coc=6Edd5-jihnHnh(Z zxR=1k0^703Vzl98@Y%5Ec}1Qt_wf$1U72H*4d-*x)P2ZHAdJ^*};us;rb%&_fA3_l9?S>$K@t@(KH z@!$h)*$)5M&&pwAdjhx}gP!PgN}VL+6DZ%lUDwIU!0ACAPZ9D$fhQ6N@f8U?N!Szv z+jw(;c`$t?0*??l3~cI9spAFC3~bE(VWK}uQKg=Kvf!Kx$i!=0QeJaD`3Yp&D z6JaU>8KcDtknMt58f(Y474>9nUv-c*$60FanCGdGwZM~HDVru_Oc(8@HzKQtjQQi3WQM>q z1I+nU<}(+4_AJP3Ug&c!e4g&vv2Q;EGE+w8*~4_$oe3GwOFYg{7Y1S22G0V12|wbq z@%POeduu#f;ERB5`#lHP+Mg?IE)X_zgw6TF=3-%Up0Jq<%)_?pO9W>=%@7fL3JW>Q z7s0&kTFd?P}Wxq8SN;$ zM#yN#u-6Ki^>>|+S%23Hne}%AWIR}JHv;oqWqMEhBvH-RIx`=05BN=vC#uft@l6=V z6Vw;b-vZ9EVEDn{w`zT?Y~s7V^I3f)xxsx?Qv#YPDqPdU#a-hZQJ5Grt7__^@vO0w zqZ|`7r!M-R!)8`Z#iOs1{9r(cqEk`XF6b&jw}7dRr#!7Yh4( zfLs4=>h><+9(ru9)FNQ(=Q&^=^s_?XyM@i2z^jfnHYc|l4Z8%`hP@xyrt>jio0k`XdCXYG{81sNZypT$ps-mgY*q=I zmw`>%%=xz*+>Gfk9uYd8htCMzQ(ix?8af`fZ{qb$-%dle%(K;Z+`VwijpIpA_p0#2 zbJ+O7`sylg$njX; z{jrm=uS-y$2u{E29XEcN?oXY}`2EarPAY_aMTHy9h3?H~k<#a0j~nkPpy0GdD9(;6cEq z-NxG75kh9`ZLpBpdK)5Sw%$&Gj0fijHX}dLz{c`A$MK$r!?>5a1^c%+u2d1Q^+Vls zr^7r7c)j5B!N&>v@r$r;mC%#V5PI6r6ngSmj$`eYuw4e-=}w35DS)5hxKd|2jP(c5 zohA5c@Uy{fKFH7U^s^nuJc_WLh%_JNbP0-lj^LZ%>s-e%ha$pKcY@&Cz|V8GSo;Hh zzT>!O5jY)~_aZz;B0^p(@CboZ1wLBfi2@G?=KT?U@_X?X7XtI3d?c`$x5B&yu)PkJ z3OwG~V-Endt+3Edayon?N60G$z7W`6t15*2A|bz6$V&ts3(SMWA>xIo?KnxiwK;?>KUe@HaT# zT0IQ?jgI5FF7)#qZ>7$J{wBv0Re$Jjb{y|0g5TnJd-Vs>b1OLOlWq4kq~|uL#~L;8 z+Z}JGUWEMu$6KmY#JAA#w(4T&?{K_@Y6tzDnwvGH?NA@_ug{8os*le!>^iW!gukI^ zABzNE0viw@Gv7(${n@wvIduWsk?=31=^ZtTWLNV8LFOiDwbX##67}3>!0>D zh5ZEBFBW_y@_rvU%bM3-u7Q@%l^a=O*4UCa^^mwO)5rh3IC5%&-S4S}7LYx(6t{m|upVIRf$yCmRdJb?Gg#F{$p$D$m!;j+^*6{(HsAOnj>a=laf9!Dalf2|e4<>y8_rbCHKPoXq&l_I$i4^gPGk z^7z|=GYxA5r~Nw~e^+qYzb82D*LwVY!D;`2;I#kHw!|J383 zdHi#aZ}503zn!D|r!00)T)d-ur_>0x$Br%KNi*kYrZ`1&s(5y)Mm0EB@TFIMSwSo2 zgJ*Oz8Pm(7oO4#0IWfn4zub%KA4_@Mf+9J`jW&A4o@}XX&%B?(^Cq;HVJ?40whpok zC&M#z^gzwK`1~+l z&n$|D`4lDIfTN0POQsdohDQ|DRqX8hq*9LHWF4T@tF21QK`(@19)=XtiHZaB{1JM4u2FX46fj@OZ5 zZ7>vNBgEP#-MTP1Ve_hswHq;1i=stft7$COGQCx3s;y@?3PlALnLZOAHPD@ANp;u^ z#5IqFoy4xrc?!NNjNoCsGKCGIO1VCpLs|4xA_*8a27M5>n_?%VN5N=4*mMf1w*7|K zaW|qO_4x95Wyl!eH*nz!e%IV8n|79@V(P1^#d@+U|gH98Q7#lsUL;S zPr~MBVY5ZZe-ZdsV3U8`h70?xLjJpu{~_dm3cUBeNE8mv5p@)JA7G}F^D%RAZ_x^T z&z2$0*WQo!z#WI3z|92y3-NHcV14{8_$>I`1-1hMJ^6k*>_nZGB!TxAK068AoLGcc zPKWs`q%pzc?ZG=>Aqvw|f%tY4;mLOuoat#z`@lc-?Z5{LzPqqzd~M0`9x?rs?+MO> zd_KZ=2sp=1e6~PY*@%j|NE!A4^mL1%dk&ik*s(k3gv;{7QL~JILl^i(7~2L80%m>L z_pIh3d{^O<^T)%##(V2dM&I}@g5zf1d<$$&4Pn{({%iJo&>S~Z64;q z-vn^$kNgo~J4M*CzRv(ZG*~BeiU>#Dqaxg6z+ZPa@f8X?p0nlPHh%I7!Fir71?P9Q znAWp^Z63}Bwr!7gXM*#f-Qxm30sJBsLQ{S|u!&2liNKu$`zL`-8DnjZv%z=<=_&H~ zQ;sWjp1{Sx*5A{>T>{_d3V8&W2m7PVX#3ANjyZRMFBEvX!zRpf$MKzWfiDpFS%K>u zPEZ9Xr{^3;|E+PNp2sX`{f~E+lSd3sE-m5Ptl8C7dQ@&Mk7{M$!>&1Jz4;RzE-do< zyt6m+UM~pF>+g$>n`gOfKQB3%xt=!aU%xurFmc0NIJ4fE*Ns&|#`xG?UKTR0C#LKb zCo|8mS37Rf#q*(&bVS0@eC%bR)T_dt;}G_5uX(aH@KH809L=qcaN1S9?)0W?-f%of zKkVOx3|*U^>ty;Pe3=x-Tf&y{u}!`0Wb~J));Mm)Mr;F(U`Z4Wm13#RvjWT$#_lv)RVF8j~L!aP8-Z`;9VCHANOrJQutv>b9};U z`e%?2Z=h?T)5#?zb0*)6HNJ%WMEq`R%JS-^as(1t(V<7a@&^qmQw9fUm#*u;%@g@CQkbA-)oVKYbAoD0lzn`x*3 z=0SX(usI*t`oBQPF9f#bcagvs16!YSftv+&dkiqIc=Vr29LUp%QR$Rl0z4;>X9BnV ziSI1qnoaz3lExXpzqa^Yze_lh^6e( z2e8i$xG68guk`p;;23HkE~B64@vCW%#%}fFJbn#0uN78*t;eqePYcp{JunaE>jq%k z?=qb?g4^<)FYHQz&AEoT2-w{u!jTt&bBzb%ABuDCB*9lgKf&WSd;Av1mAVz!rl|nF zs=!T}jPFWt9!&pjz&2mE3%o$!g#zCp@SOtRCGa9(TLyOn+xBpekQWO)1(*lVD?Z!5 zH{g1_j`YhlOu>4pQqH*QZQk^PoJn=1rQzBX^L2}gdfYqW(FOO=aVwN?8^f z-upk?TR%9%7J?DInb%^GR^AiXHDmTMib+W*f}6CEKiS&`V;c77%qQ1v+$Zwc1Nqcn z3(-l|w@4*0Q~wh-n{fT<2+q2-K4M|G5DQCwu=b_8HZ%`$hN;4dRG|E6aPi zh?WRD1-rfUc#QFwdoQ+8|31kSklXFJ;nQQJ@dWtfImNW{KBq8T3?UY_dfu6Kc_SP_Yi4jd~EwCI-3NY2A-o2IvM&l)W|~tXL~C_n1=SEdyr1XW!dp`k#V~ZNT0mQ1-M4{|qq0^0yqA=^>uzg=6_VE5bb&VDo$| zQTIbx`(xe>VcA!#fWADyF93gyiluy|kdKCaIXW`RU!)BH@h8Bo>WJ|j(uc4|3+!wk zkqyj)cB^PNEoS#B_~DCU{1xzv^mWbn$w64jUt{=a%>F|!{5zihbx;46$3O7w-}U%f z@`6}=>pXof($@+PplrTB^7I=#{u#K;@9|#vJaQ4==U(_v$%Q`Ov;WewFYx?-;pyM> z{Jrn#$9Vp~^Ymjq|KC6_^Eb}Zf9r+c`thE>6TI~O;MxD^@e@7!Up@Uv zp8qY-%l!P}*>Cmu1keBPp8jWYk-w9@_}->|K&(Ce;f4Rx)1Tsn|I5=iqdpq*w~NQO zd;XK4m-#L9{I~GJxAb@-xyau{FZ^!c(*Ler_#$$V|2Cd}61nidyQgpM>DzkxV)72L z@+k4_+k5tZd*#ysdYS&P=Wm-={(E`;_9PeS-`mrddj9tD^pnX&`RwQEJ9@l~T;%rv zaGCycPk*2n{#0_2-p-!Blc%5J@h+Zy1-VF1rN={_{o&wd+>GZ-z-Ek(c?9C%KI$-F zJI3uHa2||z?-fwg%RnV+pWX)j`{ragJNPoi{%Zv)2?2>#C#;crLy^PL`Z3D95Qc#`@Pe5M(gr-b1DLaj6J1FfC)FYA_r zn;5g%2EGQT?<9Haw9}^s4MJs=R|T8uHZ7cf&iP*=)DI?15}J@q6H^ve3}%;C{HJhS zDcppB+2LvU_+^-%SZG2h?i$rpFNf3_rYu5@NmjdJT*Z!^%^2>z$ zMqnO{^E!vIZ{rV`YZ75D7h&cL`4vKb127Nzx>?v=?Mabs~d^<2pj(td4k0iA~@Poh?YHrpLZ0nw+?hyJg^ml4*%9GDs@ACL;F+afa zX4xzfHk94%@q0Xeug4b)&N%P$`2RfKfs+?Fcs*h7+6m9LSYG$TZYMnszB80LXuwW4 z9imD9e*bFHchJ9@4DO0=9q4p7)AI%o2>fu6A71O*T!^`pfSdd@)3Oc7*&~o=PM@hx zPv+}s)A5BB{t2lNp1*MIFIM?wsusvs<0XAbXJktj@V+CB>h5SR{NeIXG`5v$hyH41D1Z>7J_*MikYmoLI z1M?vMMA)nqHtU7WN+EyM$uWLITX;qAW#DfKz8d@;!PkSo4!%OijkTeVV$A@!&Byz| zHXon4a2Q`Ru{hZ8u+2Wq!4wY5R|mFcp3bD}Y!<4pS>tRtW=d>0H^^&DgVwCnl^jHf z@S|CH0q6I7hKs#In5LJVfAdZo%i?i27Bg|K!h>0kPnhn#QLAS0dAx7`GLd>pSG|C^ zSg*Dpei7XIWuK5+8?LA;2`6{%oT6X0oQ_YBREMy^`Q)&A$qT#63k%CEZ3zEwK*z(D zE9+DGuEIk6X!%skF7jMap!%dyZ+hWa@1Fqn_Y!*ACksw} zZ^5bW1CC*ePB-;^!EHW9LEq2Q_ZNEF4*<9E)89Z(KgiP`0nT+m%u|Q{Nop`S#}VYi zz=s6kc^xSMPXXtlpJ85ty>^=NRN;5c&5kq24}f3-|S~`Mj=~VqNaI zkHCWA3VtR9?>0`ZE!x>lZD7ei|K=~{V5H|boo@D19o5HaSl{UQeyV?Zk{a#!Vd}jj zlT^0jN2nRYl2nf4`>2NyKG*R>)ZVZ^-tmJ~c1DuQbG(asaCnl+cYLsV5dI1rAELem zALIDZs_2*`HP&%_Rdq;`8s~VDngl-HaqR04euCqPst@>yj_;yg06)p`W@;Yz1jk#b z!%~ve$&MeR<{URHvYv3LS5ymV!@od^hz1>aED}UDbuqPjbACx)%Ck z$6Kqfpf7QJcl8VOVaNAZ#b}qMj(1X*f=_l_snvrqx9Rxds^!omRql9Cl?HyQQnSD-9Ph7|AC;sk9q+CFhQ7-2KB_Uc=yfKPM$K=lLcr#pV6%0D_u)jK{E-+)L` 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%0D6C1NlKL5D0!1To7CqToM!uegPUptpE;e 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

RrTawp9imNOZJJx_t)I2t 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

?B5powz9W|N7W)D~gtwOWdltHN0y0D^V zSS9o@FT_jH3>LkGDIn39R+g1*Wf?fuGA~Ul8`|s+dyE}Zip*Rq&&s!&qyn*7DzS>J zVyle34CSRI8dop-pTHscKA#ZA{HVWH!V$ zpl$Gk7P$@Li1ZwJiNjV^xC)!n7E_1m8e2y|ptJ;9+i*%}LkxPG!Dh5!5~B!aS!^bo z*l4!-bXJ?qX19e^ZkyBQvN>#Vfyag$6K1cCB13IHvCr04NX-$I%I>$3t13>w7BXbS zZF$I+P={?1+YmEqgE>ZZi*6N@v@u&$Ws$~h1A3nfVD+*Rwvm5m9i+^kI}EbvpxybYEY1jDw1jfUiGB^$?(;1_K*Zb*>VRBdJ3s1BEm z+7ir~tzxqvBeuFt$&7H@wn1~l*0Hs0O`FBsv};ttuVcAA}T_lrh(A!Eik zqAuwfcBY+e=h``To?Xl^8rlNB9Yp|1FGpbaYlU`^U2K=wL0yKEq)F9MyI73L5WCFY zBZ=}9c8OML4`^BPVL62}tfni5HD-g_j?0KZVAt9Q=rvlNMUmUsC6mFt+5xg%Jog<)0dmS-Vp97$= z96csjA|O~_G>1Y?cNF9t2P9!S5=IgCBL*0oAb>F(h(qm=6C6a1gO2DN0AK3pC=>)4 zY>+j~N-~uWnWN6tJG2f5qGu0qRE{b~NjE!;MA2+>7#tRd$zc>)9S(=r;dZzj426ne zcQ_ps36t(|gcvbLTM}{v96?9eA*S;Y)Zufqm{CW8m2gBHamSF}rRHfXr&Vfkn#F@0t23kTAZn%EX)!pQUME%WaoU_t zr`rh$bb8dOQq&lEiQnmSX7~YT$Qg7-oGxd~8Fhx8W}!{$MB+}7EKf^l{K}*=;Y>Nx z&Wsat+Vr?n&B!`MCK^*`*NUa`oHJ`=8Hb%|IaeiX)!w0~Vu({JZ#PodI-bYnWqMtFIqK?h`&@okz!h?ZT@hDN4%0D_ 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 W%o|6xsrji5?z~zjn@`4?mi!MPO+MKG literal 0 HcmV?d00001 diff --git a/public/index.bundle.js b/public/index.bundle.js new file mode 100644 index 0000000..2cafb5e --- /dev/null +++ b/public/index.bundle.js @@ -0,0 +1 @@ +(()=>{"use strict";var __webpack_modules__={151:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{JC:()=>ClientMsgTag,PG:()=>RefStore,iQ:()=>evalMem,ni:()=>encodeClientMessage});const VAL=0,NEXT=1;function Cons(e,t){return[e,t]}var ExprTag,ClientMsgTag;function evalMem(e){let t=null;for(;e.beginencodeValue(e,t)));if(t instanceof Uint8Array)return e.mem.setUint8(e.begin,ExprTag.U8Arr),e.mem.setBigUint64(e.begin+1,BigInt(t.byteLength),!1),new Uint8Array(e.mem.buffer).set(t,e.begin+9),void(e.begin+=9+t.byteLength);if(null==t)return e.mem.setUint8(e.begin,ExprTag.Null),void e.begin++;const n=Object.entries(t);e.mem.setUint8(e.begin,ExprTag.Obj),e.mem.setBigUint64(e.begin+1,BigInt(n.length),!1),e.begin+=9,n.forEach((([t,n])=>{encodeString(e,t),encodeValue(e,n)}))}function encodeString(e,t){const n=new Uint8Array(e.mem.buffer).subarray(e.begin+8),r=(new TextEncoder).encodeInto(t,n);e.mem.setBigUint64(e.begin,BigInt(r.written),!1),e.begin+=8+r.written}function encodeClientMessage(e,t){switch(t[0]){case ClientMsgTag.StartMsg:return e.mem.setUint8(e.begin,ClientMsgTag.StartMsg),e.begin++,void encodeValue(e,t[1]);case ClientMsgTag.EventMsg:return e.mem.setUint8(e.begin,ClientMsgTag.EventMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.ResumeMsg:return e.mem.setUint8(e.begin,ClientMsgTag.ResumeMsg),e.mem.setUint32(e.begin+1,t[1],!1),e.begin+=5,void encodeValue(e,t[2]);case ClientMsgTag.BeforeUnloadMsg:return e.mem.setUint8(e.begin,ClientMsgTag.BeforeUnloadMsg),void e.begin++}}!function(e){e[e.Null=0]="Null",e[e.Bool=1]="Bool",e[e.I8=2]="I8",e[e.I16=3]="I16",e[e.I32=4]="I32",e[e.I64=5]="I64",e[e.U8=6]="U8",e[e.U16=7]="U16",e[e.U32=8]="U32",e[e.U64=9]="U64",e[e.F32=10]="F32",e[e.F64=11]="F64",e[e.Str=12]="Str",e[e.Arr=13]="Arr",e[e.Obj=14]="Obj",e[e.U8Arr=15]="U8Arr",e[e.Dot=16]="Dot",e[e.SetProp=17]="SetProp",e[e.Ix=18]="Ix",e[e.Id=19]="Id",e[e.Lam=20]="Lam",e[e.Arg=21]="Arg",e[e.Apply=22]="Apply",e[e.Call=23]="Call",e[e.AssignRef=24]="AssignRef",e[e.Ref=25]="Ref",e[e.FreeScope=26]="FreeScope",e[e.MoveScope=27]="MoveScope",e[e.PeekStack=28]="PeekStack",e[e.PushStack=29]="PushStack",e[e.PopStack=30]="PopStack",e[e.PopIns=31]="PopIns",e[e.ElementProp=32]="ElementProp",e[e.ElementAttr=33]="ElementAttr",e[e.ClassListAdd=34]="ClassListAdd",e[e.ClassListRemove=35]="ClassListRemove",e[e.InsertPlaceholder=36]="InsertPlaceholder",e[e.InsertPlaceholderBefore=37]="InsertPlaceholderBefore",e[e.ClearPlaceholder=38]="ClearPlaceholder",e[e.DetachPlaceholder=39]="DetachPlaceholder",e[e.CreateElement=40]="CreateElement",e[e.CreateElementNS=41]="CreateElementNS",e[e.CreateText=42]="CreateText",e[e.UpdateText=43]="UpdateText",e[e.Eval=44]="Eval",e[e.TriggerEvent=45]="TriggerEvent",e[e.Resume=46]="Resume",e[e.Out=47]="Out"}(ExprTag||(ExprTag={})),function(e){e[e.StartMsg=0]="StartMsg",e[e.EventMsg=1]="EventMsg",e[e.ResumeMsg=2]="ResumeMsg",e[e.BeforeUnloadMsg=3]="BeforeUnloadMsg"}(ClientMsgTag||(ClientMsgTag={}));const decoder=new TextDecoder("utf8");function decodeString(e){const t=Number(e.mem.getBigUint64(e.begin,!1));e.begin+=8;const n=new Uint8Array(e.mem.buffer).subarray(e.begin,e.begin+t);return e.begin+=t,decoder.decode(n)}var utils;!function(e){function t(e,t){e instanceof Comment?e.parentElement.insertBefore(t,e):e.appendChild(t)}function n(e,t,n){const r=n instanceof Comment?function(e){let t=0;for(;;){if(!e.previousSibling||0==t&&s(e.previousSibling))return e.previousSibling;i(e.previousSibling)?t++:s(e.previousSibling)&&t--,e=e.previousSibling}}(n):n;e instanceof Comment?e.parentElement.insertBefore(t,r):e.insertBefore(t,r)}function r(e){return e instanceof Comment?e.parentElement:e}function s(e){return e instanceof Comment&&"Placeholder {{{"==e.textContent}function i(e){return e instanceof Comment&&"}}}"==e.textContent}e.insert=t,e.insertBefore=n,e.prop=function(e,t,n){e instanceof Comment?e.parentElement[t]=n:e[t]=n},e.attr=function(e,t,n){r(e).setAttribute(t,n)},e.addEventListener=function(e,t,n){r(e).addEventListener(t,n)},e.removeEventListener=function(e,t,n){r(e).removeEventListener(t,n)},e.insertPlaceholder=function(e){const n=document.createComment("Placeholder {{{"),r=document.createComment("}}}");return t(e,n),t(e,r),r},e.insertPlaceholderBefore=function(e,t){const r=document.createComment("Placeholder {{{"),s=document.createComment("}}}");return n(e,r,t),n(e,s,t),s},e.clearPlaceholder=function(e,t){if(e instanceof Comment){let n=0;for(;e.previousSibling&&(0!=n||!s(e.previousSibling));)i(e.previousSibling)?n++:s(e.previousSibling)&&n--,e.previousSibling.parentNode.removeChild(e.previousSibling);t&&(e.previousSibling.parentNode.removeChild(e.previousSibling),e.parentNode.removeChild(e))}else e.innerHTML=""},e.getBuilderElement=r}(utils||(utils={}));class RefStore{constructor(e=new Map,t=new Map){this.scopes=e,this.refs=t}assignRef(e,t,n){const r=this.scopes.get(e),s=r||new Set;r||this.scopes.set(e,s),s.add(t),this.refs.set(t,n)}moveScope(e,t){const n=this.scopes.get(e),r=this.scopes.get(t);n&&r&&(n.forEach((e=>r.add(e))),this.scopes.delete(e))}freeScope(e){const t=this.scopes.get(e);t&&(t.forEach((e=>this.refs.delete(e))),this.scopes.delete(e))}}}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={},proto=__webpack_require__(151);const outBuf=new ArrayBuffer(102400),mem=new DataView(outBuf);function runWebsocket(e,t=null,n){const r=new WebSocket(e),s={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.EventMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},resumeCont:function(e,t){const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.ResumeMsg,e,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))}};r.onopen=e=>{const n={mem,begin:0,end:outBuf.byteLength};proto.ni(n,[proto.JC.StartMsg,t]),r.send(new Uint8Array(outBuf).subarray(0,n.begin))},r.onmessage=e=>{convertBlobToUint8Array(e.data).then((e=>{proto.iQ({context:s,mem:new DataView(e),isMutableMem:!1,begin:0,end:e.byteLength})}))},r.onerror=e=>{console.error("WebSocket error:",e)},r.onclose=t=>{console.log("WebSocket connection closed, reloading the tab…"),function t(n){const r=new WebSocket(e),s=Math.min(5e3,2*n);r.onopen=e=>window.location.reload(),r.onclose=e=>{setTimeout((()=>t(s)),n)}}(100)}}function convertBlobToUint8Array(e){return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{t(r.result)},r.onerror=e=>{n(e)},r.readAsArrayBuffer(e)}))}const FD_STDIN=0,FD_STDOUT=1,FD_STDERR=2,CLOCKID_REALTIME=0,CLOCKID_MONOTONIC=1,CLOCKID_PROCESS_CPUTIME_ID=2,CLOCKID_THREAD_CPUTIME_ID=3,ERRNO_SUCCESS=0,ERRNO_2BIG=1,ERRNO_ACCES=2,ERRNO_ADDRINUSE=3,ERRNO_ADDRNOTAVAIL=4,ERRNO_AFNOSUPPORT=5,ERRNO_AGAIN=6,ERRNO_ALREADY=7,ERRNO_BADF=8,ERRNO_BADMSG=9,ERRNO_BUSY=10,ERRNO_CANCELED=11,ERRNO_CHILD=12,ERRNO_CONNABORTED=13,ERRNO_CONNREFUSED=14,ERRNO_CONNRESET=15,ERRNO_DEADLK=16,ERRNO_DESTADDRREQ=17,ERRNO_DOM=18,ERRNO_DQUOT=19,ERRNO_EXIST=20,ERRNO_FAULT=21,ERRNO_FBIG=22,ERRNO_HOSTUNREACH=23,ERRNO_IDRM=24,ERRNO_ILSEQ=25,ERRNO_INPROGRESS=26,ERRNO_INTR=27,ERRNO_INVAL=28,ERRNO_IO=29,ERRNO_ISCONN=30,ERRNO_ISDIR=31,ERRNO_LOOP=32,ERRNO_MFILE=33,ERRNO_MLINK=34,ERRNO_MSGSIZE=35,ERRNO_MULTIHOP=36,ERRNO_NAMETOOLONG=37,ERRNO_NETDOWN=38,ERRNO_NETRESET=39,ERRNO_NETUNREACH=40,ERRNO_NFILE=41,ERRNO_NOBUFS=42,ERRNO_NODEV=43,ERRNO_NOENT=44,ERRNO_NOEXEC=45,ERRNO_NOLCK=46,ERRNO_NOLINK=47,ERRNO_NOMEM=48,ERRNO_NOMSG=49,ERRNO_NOPROTOOPT=50,ERRNO_NOSPC=51,ERRNO_NOSYS=52,ERRNO_NOTCONN=53,ERRNO_NOTDIR=54,ERRNO_NOTEMPTY=55,ERRNO_NOTRECOVERABLE=56,ERRNO_NOTSOCK=57,ERRNO_NOTSUP=58,ERRNO_NOTTY=59,ERRNO_NXIO=60,ERRNO_OVERFLOW=61,ERRNO_OWNERDEAD=62,ERRNO_PERM=63,ERRNO_PIPE=64,ERRNO_PROTO=65,ERRNO_PROTONOSUPPORT=66,ERRNO_PROTOTYPE=67,ERRNO_RANGE=68,ERRNO_ROFS=69,ERRNO_SPIPE=70,ERRNO_SRCH=71,ERRNO_STALE=72,ERRNO_TIMEDOUT=73,ERRNO_TXTBSY=74,ERRNO_XDEV=75,ERRNO_NOTCAPABLE=76,RIGHTS_FD_DATASYNC=null,RIGHTS_FD_READ=null,RIGHTS_FD_SEEK=null,RIGHTS_FD_FDSTAT_SET_FLAGS=null,RIGHTS_FD_SYNC=null,RIGHTS_FD_TELL=null,RIGHTS_FD_WRITE=64,RIGHTS_FD_ADVISE=null,RIGHTS_FD_ALLOCATE=null,RIGHTS_PATH_CREATE_DIRECTORY=null,RIGHTS_PATH_CREATE_FILE=null,RIGHTS_PATH_LINK_SOURCE=null,RIGHTS_PATH_LINK_TARGET=null,RIGHTS_PATH_OPEN=null,RIGHTS_FD_READDIR=null,RIGHTS_PATH_READLINK=null,RIGHTS_PATH_RENAME_SOURCE=null,RIGHTS_PATH_RENAME_TARGET=null,RIGHTS_PATH_FILESTAT_GET=null,RIGHTS_PATH_FILESTAT_SET_SIZE=null,RIGHTS_PATH_FILESTAT_SET_TIMES=null,RIGHTS_FD_FILESTAT_GET=null,RIGHTS_FD_FILESTAT_SET_SIZE=null,RIGHTS_FD_FILESTAT_SET_TIMES=null,RIGHTS_PATH_SYMLINK=null,RIGHTS_PATH_REMOVE_DIRECTORY=null,RIGHTS_PATH_UNLINK_FILE=null,RIGHTS_POLL_FD_READWRITE=null,RIGHTS_SOCK_SHUTDOWN=null;class Iovec{static read_bytes(e,t){const n=new Iovec;return n.buf=e.getUint32(t,!0),n.buf_len=e.getUint32(t+4,!0),n}static read_bytes_array(e,t,n){const r=[];for(let s=0;s{}}const debug=new Debug(!1);class WASIProcExit extends Error{constructor(e){super("exit with exit code "+e),this.code=e}}let WASI=class{start(e){this.inst=e;try{return e.exports._start(),0}catch(e){if(e instanceof WASIProcExit)return e.code;throw e}}initialize(e){this.inst=e,e.exports._initialize&&e.exports._initialize()}constructor(e,t,n,r={}){this.args=[],this.env=[],this.fds=[],debug.enable(r.debug),this.args=e,this.env=t,this.fds=n;const s=this;this.wasiImport={args_sizes_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);n.setUint32(e,s.args.length,!0);let r=0;for(const e of s.args)r+=e.length+1;return n.setUint32(t,r,!0),debug.log(n.getUint32(e,!0),n.getUint32(t,!0)),0},args_get(e,t){const n=new DataView(s.inst.exports.memory.buffer),r=new Uint8Array(s.inst.exports.memory.buffer),i=t;for(let i=0;inull!=s.fds[e]?ERRNO_SUCCESS:ERRNO_BADF,fd_allocate:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_allocate(t,n):ERRNO_BADF,fd_close(e){if(null!=s.fds[e]){const t=s.fds[e].fd_close();return s.fds[e]=void 0,t}return ERRNO_BADF},fd_datasync:e=>null!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_fdstat_get(e,t){if(null!=s.fds[e]){const{ret:n,fdstat:r}=s.fds[e].fd_fdstat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_fdstat_set_flags:(e,t)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_flags(t):ERRNO_BADF,fd_fdstat_set_rights:(e,t,n)=>null!=s.fds[e]?s.fds[e].fd_fdstat_set_rights(t,n):ERRNO_BADF,fd_filestat_get(e,t){if(null!=s.fds[e]){const{ret:n,filestat:r}=s.fds[e].fd_filestat_get();return null!=r&&r.write_bytes(new DataView(s.inst.exports.memory.buffer),t),n}return ERRNO_BADF},fd_filestat_set_size:(e,t)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_size(t):ERRNO_BADF,fd_filestat_set_times:(e,t,n,r)=>null!=s.fds[e]?s.fds[e].fd_filestat_set_times(t,n,r):ERRNO_BADF,fd_pread(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Iovec.read_bytes_array(a,t,n);let _=0;for(const t of l){const{ret:n,data:l}=s.fds[e].fd_pread(t.buf_len,r);if(n!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),n;if(o.set(l,t.buf),_+=l.length,r+=BigInt(l.length),l.length!=t.buf_len)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_prestat_get(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();return null!=i&&i.write_bytes(n,t),r}return ERRNO_BADF},fd_prestat_dir_name(e,t,n){if(null!=s.fds[e]){const{ret:r,prestat:i}=s.fds[e].fd_prestat_get();if(null==i)return r;const a=i.inner.pr_name;return new Uint8Array(s.inst.exports.memory.buffer).set(a.slice(0,n),t),a.byteLength>n?ERRNO_NAMETOOLONG:ERRNO_SUCCESS}return ERRNO_BADF},fd_pwrite(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=Ciovec.read_bytes_array(a,t,n);let _=0;for(const t of l){const n=o.slice(t.buf,t.buf+t.buf_len),{ret:l,nwritten:f}=s.fds[e].fd_pwrite(n,r);if(l!=ERRNO_SUCCESS)return a.setUint32(i,_,!0),l;if(_+=f,r+=BigInt(f),f!=n.byteLength)break}return a.setUint32(i,_,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_read(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Iovec.read_bytes_array(i,t,n);let l=0;for(const t of o){const{ret:n,data:o}=s.fds[e].fd_read(t.buf_len);if(n!=ERRNO_SUCCESS)return i.setUint32(r,l,!0),n;if(a.set(o,t.buf),l+=o.length,o.length!=t.buf_len)break}return i.setUint32(r,l,!0),ERRNO_SUCCESS}return ERRNO_BADF},fd_readdir(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){let l=0;for(;;){const{ret:_,dirent:f}=s.fds[e].fd_readdir_single(r);if(0!=_)return a.setUint32(i,l,!0),_;if(null==f)break;if(n-lnull!=s.fds[e]?s.fds[e].fd_sync():ERRNO_BADF,fd_tell(e,t){const n=new DataView(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const{ret:r,offset:i}=s.fds[e].fd_tell();return n.setBigUint64(t,i,!0),r}return ERRNO_BADF},fd_write(e,t,n,r){const i=new DataView(s.inst.exports.memory.buffer),a=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const o=Ciovec.read_bytes_array(i,t,n);let l=0;for(const t of o){const n=a.slice(t.buf,t.buf+t.buf_len),{ret:o,nwritten:_}=s.fds[e].fd_write(n);if(o!=ERRNO_SUCCESS)return i.setUint32(r,l,!0),o;if(l+=_,_!=n.byteLength)break}return i.setUint32(r,l,!0),ERRNO_SUCCESS}return ERRNO_BADF},path_create_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder("utf-8").decode(r.slice(t,t+n));return s.fds[e].path_create_directory(i)}return ERRNO_BADF},path_filestat_get(e,t,n,r,i){const a=new DataView(s.inst.exports.memory.buffer),o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const l=new TextDecoder("utf-8").decode(o.slice(n,n+r)),{ret:_,filestat:f}=s.fds[e].path_filestat_get(t,l);return null!=f&&f.write_bytes(a,i),_}return ERRNO_BADF},path_filestat_set_times(e,t,n,r,i,a,o){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder("utf-8").decode(l.slice(n,n+r));return s.fds[e].path_filestat_set_times(t,_,i,a,o)}return ERRNO_BADF},path_link(e,t,n,r,i,a,o){const l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[i]){const _=new TextDecoder("utf-8").decode(l.slice(n,n+r)),f=new TextDecoder("utf-8").decode(l.slice(a,a+o)),{ret:u,inode_obj:c}=s.fds[e].path_lookup(_,t);return null==c?u:s.fds[i].path_link(f,c,!1)}return ERRNO_BADF},path_open(e,t,n,r,i,a,o,l,_){const f=new DataView(s.inst.exports.memory.buffer),u=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const c=new TextDecoder("utf-8").decode(u.slice(n,n+r));debug.log(c);const{ret:d,fd_obj:E}=s.fds[e].path_open(t,c,i,a,o,l);if(0!=d)return d;s.fds.push(E);const g=s.fds.length-1;return f.setUint32(_,g,!0),0}return ERRNO_BADF},path_readlink(e,t,n,r,i,a){const o=new DataView(s.inst.exports.memory.buffer),l=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const _=new TextDecoder("utf-8").decode(l.slice(t,t+n));debug.log(_);const{ret:f,data:u}=s.fds[e].path_readlink(_);if(null!=u){const e=(new TextEncoder).encode(u);if(e.length>i)return o.setUint32(a,0,!0),ERRNO_BADF;l.set(e,r),o.setUint32(a,e.length,!0)}return f}return ERRNO_BADF},path_remove_directory(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder("utf-8").decode(r.slice(t,t+n));return s.fds[e].path_remove_directory(i)}return ERRNO_BADF},path_rename(e,t,n,r,i,a){const o=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]&&null!=s.fds[r]){const l=new TextDecoder("utf-8").decode(o.slice(t,t+n)),_=new TextDecoder("utf-8").decode(o.slice(i,i+a));let{ret:f,inode_obj:u}=s.fds[e].path_unlink(l);if(null==u)return f;if(f=s.fds[r].path_link(_,u,!0),f!=ERRNO_SUCCESS&&s.fds[e].path_link(l,u,!0)!=ERRNO_SUCCESS)throw"path_link should always return success when relinking an inode back to the original place";return f}return ERRNO_BADF},path_symlink(e,t,n,r,i){const a=new Uint8Array(s.inst.exports.memory.buffer);return null!=s.fds[n]?(new TextDecoder("utf-8").decode(a.slice(e,e+t)),new TextDecoder("utf-8").decode(a.slice(r,r+i)),ERRNO_NOTSUP):ERRNO_BADF},path_unlink_file(e,t,n){const r=new Uint8Array(s.inst.exports.memory.buffer);if(null!=s.fds[e]){const i=new TextDecoder("utf-8").decode(r.slice(t,t+n));return s.fds[e].path_unlink_file(i)}return ERRNO_BADF},poll_oneoff(e,t,n){throw"async io not supported"},proc_exit(e){throw new WASIProcExit(e)},proc_raise(e){throw"raised signal "+e},sched_yield(){},random_get(e,t){const n=new Uint8Array(s.inst.exports.memory.buffer);for(let r=0;re+t);else{const n=new Uint8Array(Number(e+t));n.set(this.file.data,0),this.file.data=n}return ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_set_size(e){if(this.file.size>e)this.file.data=new Uint8Array(this.file.data.buffer.slice(0,Number(e)));else{const t=new Uint8Array(Number(e));t.set(this.file.data,0),this.file.data=t}return ERRNO_SUCCESS}fd_read(e){const t=this.file.data.slice(Number(this.file_pos),Number(this.file_pos+BigInt(e)));return this.file_pos+=BigInt(t.length),{ret:0,data:t}}fd_pread(e,t){return{ret:0,data:this.file.data.slice(Number(t),Number(t+BigInt(e)))}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=e;break;case WHENCE_CUR:n=this.file_pos+e;break;case WHENCE_END:n=BigInt(this.file.data.byteLength)+e;break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.file_pos=n,{ret:0,offset:this.file_pos})}fd_tell(){return{ret:0,offset:this.file_pos}}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(this.file_pos+BigInt(e.byteLength)>this.file.size){const t=this.file.data;this.file.data=new Uint8Array(Number(this.file_pos+BigInt(e.byteLength))),this.file.data.set(t)}return this.file.data.set(e,Number(this.file_pos)),this.file_pos+=BigInt(e.byteLength),{ret:0,nwritten:e.byteLength}}fd_pwrite(e,t){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};if(t+BigInt(e.byteLength)>this.file.size){const n=this.file.data;this.file.data=new Uint8Array(Number(t+BigInt(e.byteLength))),this.file.data.set(n)}return this.file.data.set(e,Number(t)),{ret:0,nwritten:e.byteLength}}fd_filestat_get(){return{ret:0,filestat:this.file.stat()}}constructor(e){super(),this.file_pos=0n,this.file=e}}class OpenDirectory extends Fd{fd_seek(e,t){return{ret:ERRNO_BADF,offset:0n}}fd_tell(){return{ret:ERRNO_BADF,offset:0n}}fd_allocate(e,t){return ERRNO_BADF}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_DIRECTORY,0)}}fd_readdir_single(e){if(debug.enabled&&(debug.log("readdir_single",e),debug.log(e,this.dir.contents.keys())),0n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(1n,".",FILETYPE_DIRECTORY)};if(1n==e)return{ret:ERRNO_SUCCESS,dirent:new Dirent(2n,"..",FILETYPE_DIRECTORY)};if(e>=BigInt(this.dir.contents.size)+2n)return{ret:0,dirent:null};const[t,n]=Array.from(this.dir.contents.entries())[Number(e-2n)];return{ret:0,dirent:new Dirent(e+1n,t,n.stat().filetype)}}path_filestat_get(e,t){const{ret:n,path:r}=Path.from(t);if(null==r)return{ret:n,filestat:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,filestat:null}:{ret:0,filestat:i.stat()}}path_lookup(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,inode_obj:null};const{ret:s,entry:i}=this.dir.get_entry_for_path(r);return null==i?{ret:s,inode_obj:null}:{ret:ERRNO_SUCCESS,inode_obj:i}}path_open(e,t,n,r,s,i){const{ret:a,path:o}=Path.from(t);if(null==o)return{ret:a,fd_obj:null};let{ret:l,entry:_}=this.dir.get_entry_for_path(o);if(null==_){if(l!=ERRNO_NOENT)return{ret:l,fd_obj:null};if((n&OFLAGS_CREAT)!=OFLAGS_CREAT)return{ret:ERRNO_NOENT,fd_obj:null};{const{ret:e,entry:r}=this.dir.create_entry_for_path(t,(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY);if(null==r)return{ret:e,fd_obj:null};_=r}}else if((n&OFLAGS_EXCL)==OFLAGS_EXCL)return{ret:ERRNO_EXIST,fd_obj:null};return(n&OFLAGS_DIRECTORY)==OFLAGS_DIRECTORY&&_.stat().filetype!==FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,fd_obj:null}:_.path_open(n,r,i)}path_create_directory(e){return this.path_open(0,e,OFLAGS_CREAT|OFLAGS_DIRECTORY,0n,0n,0).ret}path_link(e,t,n){const{ret:r,path:s}=Path.from(e);if(null==s)return r;if(s.is_dir)return ERRNO_NOENT;const{ret:i,parent_entry:a,filename:o,entry:l}=this.dir.get_parent_dir_and_entry_for_path(s,!0);if(null==a||null==o)return i;if(null!=l){const e=t.stat().filetype==FILETYPE_DIRECTORY,r=l.stat().filetype==FILETYPE_DIRECTORY;if(e&&r){if(!(n&&l instanceof Directory))return ERRNO_EXIST;if(0!=l.contents.size)return ERRNO_NOTEMPTY}else{if(e&&!r)return ERRNO_NOTDIR;if(!e&&r)return ERRNO_ISDIR;if(t.stat().filetype!=FILETYPE_REGULAR_FILE||l.stat().filetype!=FILETYPE_REGULAR_FILE)return ERRNO_EXIST}}return n||t.stat().filetype!=FILETYPE_DIRECTORY?(a.contents.set(o,t),ERRNO_SUCCESS):ERRNO_PERM}path_unlink(e){const{ret:t,path:n}=Path.from(e);if(null==n)return{ret:t,inode_obj:null};const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!0);return null==s||null==i?{ret:r,inode_obj:null}:null==a?{ret:ERRNO_NOENT,inode_obj:null}:(s.contents.delete(i),{ret:ERRNO_SUCCESS,inode_obj:a})}path_unlink_file(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a.stat().filetype===FILETYPE_DIRECTORY?ERRNO_ISDIR:(s.contents.delete(i),ERRNO_SUCCESS)}path_remove_directory(e){const{ret:t,path:n}=Path.from(e);if(null==n)return t;const{ret:r,parent_entry:s,filename:i,entry:a}=this.dir.get_parent_dir_and_entry_for_path(n,!1);return null==s||null==i||null==a?r:a instanceof Directory&&a.stat().filetype===FILETYPE_DIRECTORY?0!==a.contents.size?ERRNO_NOTEMPTY:s.contents.delete(i)?ERRNO_SUCCESS:ERRNO_NOENT:ERRNO_NOTDIR}fd_filestat_get(){return{ret:0,filestat:this.dir.stat()}}fd_filestat_set_size(e){return ERRNO_BADF}fd_read(e){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_pread(e,t){return{ret:ERRNO_BADF,data:new Uint8Array}}fd_write(e){return{ret:ERRNO_BADF,nwritten:0}}fd_pwrite(e,t){return{ret:ERRNO_BADF,nwritten:0}}constructor(e){super(),this.dir=e}}class PreopenDirectory extends OpenDirectory{fd_prestat_get(){return{ret:0,prestat:Prestat.dir(this.prestat_name)}}constructor(e,t){super(new Directory(t)),this.prestat_name=e}}class File extends Inode{path_open(e,t,n){if(this.readonly&&(t&BigInt(RIGHTS_FD_WRITE))==BigInt(RIGHTS_FD_WRITE))return{ret:ERRNO_PERM,fd_obj:null};if((e&OFLAGS_TRUNC)==OFLAGS_TRUNC){if(this.readonly)return{ret:ERRNO_PERM,fd_obj:null};this.data=new Uint8Array([])}const r=new OpenFile(this);return n&FDFLAGS_APPEND&&r.fd_seek(0n,WHENCE_END),{ret:ERRNO_SUCCESS,fd_obj:r}}get size(){return BigInt(this.data.byteLength)}stat(){return new Filestat(FILETYPE_REGULAR_FILE,this.size)}constructor(e,t){super(),this.data=new Uint8Array(e),this.readonly=!!t?.readonly}}let Path=class e{static from(t){const n=new e;if(n.is_dir=t.endsWith("/"),t.startsWith("/"))return{ret:ERRNO_NOTCAPABLE,path:null};if(t.includes("\0"))return{ret:ERRNO_INVAL,path:null};for(const e of t.split("/"))if(""!==e&&"."!==e)if(".."!==e)n.parts.push(e);else if(null==n.parts.pop())return{ret:ERRNO_NOTCAPABLE,path:null};return{ret:ERRNO_SUCCESS,path:n}}to_path_string(){let e=this.parts.join("/");return this.is_dir&&(e+="/"),e}constructor(){this.parts=[],this.is_dir=!1}},inst;class Directory extends Inode{path_open(e,t,n){return{ret:ERRNO_SUCCESS,fd_obj:new OpenDirectory(this)}}stat(){return new Filestat(FILETYPE_DIRECTORY,0n)}get_entry_for_path(e){let t=this;for(const n of e.parts){if(!(t instanceof Directory))return{ret:ERRNO_NOTDIR,entry:null};const e=t.contents.get(n);if(void 0===e)return debug.log(n),{ret:ERRNO_NOENT,entry:null};t=e}return e.is_dir&&t.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,entry:null}:{ret:ERRNO_SUCCESS,entry:t}}get_parent_dir_and_entry_for_path(e,t){const n=e.parts.pop();if(void 0===n)return{ret:ERRNO_INVAL,parent_entry:null,filename:null,entry:null};const{ret:r,entry:s}=this.get_entry_for_path(e);if(null==s)return{ret:r,parent_entry:null,filename:null,entry:null};if(!(s instanceof Directory))return{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null};const i=s.contents.get(n);return void 0===i?t?{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:null}:{ret:ERRNO_NOENT,parent_entry:null,filename:null,entry:null}:e.is_dir&&i.stat().filetype!=FILETYPE_DIRECTORY?{ret:ERRNO_NOTDIR,parent_entry:null,filename:null,entry:null}:{ret:ERRNO_SUCCESS,parent_entry:s,filename:n,entry:i}}create_entry_for_path(e,t){const{ret:n,path:r}=Path.from(e);if(null==r)return{ret:n,entry:null};let s,{ret:i,parent_entry:a,filename:o,entry:l}=this.get_parent_dir_and_entry_for_path(r,!0);return null==a||null==o?{ret:i,entry:null}:null!=l?{ret:ERRNO_EXIST,entry:null}:(debug.log("create",r),s=t?new Directory(new Map):new File(new ArrayBuffer(0)),a.contents.set(o,s),l=s,{ret:ERRNO_SUCCESS,entry:l})}constructor(e){super(),this.contents=e instanceof Array?new Map(e):e}}class ConsoleStdout extends Fd{fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_CHARACTER_DEVICE,BigInt(0))}}fd_fdstat_get(){const e=new Fdstat(FILETYPE_CHARACTER_DEVICE,0);return e.fs_rights_base=BigInt(RIGHTS_FD_WRITE),{ret:0,fdstat:e}}fd_write(e){return this.write(e),{ret:0,nwritten:e.byteLength}}static lineBuffered(e){const t=new TextDecoder("utf-8",{fatal:!1});let n="";return new ConsoleStdout((r=>{n+=t.decode(r,{stream:!0});const s=n.split("\n");for(const[t,r]of s.entries())te+t||this.file.handle.truncate(Number(e+t)),ERRNO_SUCCESS}fd_fdstat_get(){return{ret:0,fdstat:new Fdstat(FILETYPE_REGULAR_FILE,0)}}fd_filestat_get(){return{ret:0,filestat:new Filestat(FILETYPE_REGULAR_FILE,BigInt(this.file.handle.getSize()))}}fd_filestat_set_size(e){return this.file.handle.truncate(Number(e)),ERRNO_SUCCESS}fd_read(e){const t=new Uint8Array(e),n=this.file.handle.read(t,{at:Number(this.position)});return this.position+=BigInt(n),{ret:0,data:t.slice(0,n)}}fd_seek(e,t){let n;switch(t){case WHENCE_SET:n=BigInt(e);break;case WHENCE_CUR:n=this.position+BigInt(e);break;case WHENCE_END:n=BigInt(this.file.handle.getSize())+BigInt(e);break;default:return{ret:ERRNO_INVAL,offset:0n}}return n<0?{ret:ERRNO_INVAL,offset:0n}:(this.position=n,{ret:ERRNO_SUCCESS,offset:this.position})}fd_write(e){if(this.file.readonly)return{ret:ERRNO_BADF,nwritten:0};const t=this.file.handle.write(e,{at:Number(this.position)});return this.position+=BigInt(t),{ret:ERRNO_SUCCESS,nwritten:t}}fd_sync(){return this.file.handle.flush(),ERRNO_SUCCESS}constructor(e){super(),this.position=0n,this.file=e}}function runWasm(e,t=null,n){const r={refs:(null==n?void 0:n.refs)||new proto.PG,stack:(null==n?void 0:n.stack)||null,triggerEvent:function(){},resumeCont:function(){}},s=new OpenFileDebug(new File([]),consoleLineBuffering(console.log)),i=new OpenFileDebug(new File([]),consoleLineBuffering(console.log));window.stdout=s,window.stderr=i;const a=new WASI([],[],[new OpenFile(new File([])),s,i]);function o(e,t){const n={context:Object.assign(Object.assign({},r),{resumeCont:function(n,r){const s={mem:new DataView(inst.exports.memory.buffer),begin:e,end:e+t};proto.ni(s,[proto.JC.ResumeMsg,n,r]),inst.exports.wasm_app(e)},triggerEvent:function(n,r){const s={mem:new DataView(inst.exports.memory.buffer),begin:e,end:e+t};proto.ni(s,[proto.JC.EventMsg,n,r]),inst.exports.wasm_app(e)}}),mem:new DataView(inst.exports.memory.buffer),isMutableMem:!0,begin:e,end:e+t};proto.iQ(n)}function l(e,t){const n=new Uint8Array(inst.exports.memory.buffer).subarray(e,e+t);return console.log(new TextDecoder("utf8").decode(n))}WebAssembly.compileStreaming(fetch(e)).then((e=>WebAssembly.instantiate(e,{wasi_snapshot_preview1:a.wasiImport,env:{clickable_eval_buffer:o,console_log:l}}))).then((e=>{inst=e,a.initialize(e),e.exports.hs_init();const n=e.exports.wasm_app(0),r={mem:new DataView(e.exports.memory.buffer),begin:n,end:n+102400};proto.ni(r,[proto.JC.StartMsg,t]),e.exports.wasm_app(n),window.addEventListener("beforeunload",(()=>{const t={mem:new DataView(e.exports.memory.buffer),begin:n,end:n+102400};proto.ni(t,[proto.JC.BeforeUnloadMsg]),e.exports.wasm_app(n)}))}))}class OpenFileDebug extends OpenFile{constructor(e,t){super(e),this.printDebug=t}fd_write(e){return this.printDebug(e),super.fd_write(e)}fd_pwrite(e,t){return this.printDebug(e.subarray(Number(t))),super.fd_pwrite(e,t)}}function consoleLineBuffering(e){let t=[];return n=>{const r=n=>{if(0==n.byteLength)return;const s=n.findIndex((e=>e=="\n".charCodeAt(0)));if(s>=0){const i=t.map((e=>new TextDecoder("utf8").decode(e))).join("");t=[];const a=new TextDecoder("utf8").decode(n.subarray(0,s));e(i+a),r(n.subarray(s+1))}else t.push(n.slice())};r(n)}}function evalUint8Array(e,t){const n={context:{refs:(null==t?void 0:t.refs)||new proto.PG,stack:(null==t?void 0:t.stack)||null,triggerEvent:(null==t?void 0:t.triggerEvent)||function(){},resumeCont:(null==t?void 0:t.resumeCont)||function(){}},mem:new DataView(e.buffer),isMutableMem:!1,begin:0,end:e.byteLength};return proto.iQ(n)}function evalBase64(e,t){return evalUint8Array(Uint8Array.from(atob(e),(function(e){return e.charCodeAt(0)})),t)}window.clickable={runWebsocket,runWasm,evalUint8Array,evalBase64}})(); \ No newline at end of file diff --git a/public/stopwatch.wasm b/public/stopwatch.wasm new file mode 100755 index 0000000000000000000000000000000000000000..fabeeca766390add7f5d47c0814b8fddc5eeb886 GIT binary patch literal 2699145 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�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

CaBMu!rOpRfbZwc?@ncw6q#IzpF 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 z zg&u+dP#)o5my~)1d);we!%f(&K7G-RAz)od z+cdzS$#Ma>yFIo;wpt$7k_T%qE6SSHXjU<-%XB1ylf~bbF~!lI1MYSE8JF>J25Om$ zuN>H%OmiD!o>*dAadhxd-*peip9#RCNo#|@P>bJIAgIs~LCUIL#p$VAwg(L?;YAB` z_VXe2H)4Yzl2qDOg7ZJ=fp8#X%AacqNm@Ip__n`Fptaa8o2Jkk-K4ZpHmI?@PT63o zSOkm-BHd0(y~ZyUPE}Muk=D#XN|8ATSmncP_RmG0jp^EAm7-6+EmqZGxZlc|)Mqp> z+901a7|}ach&fP!a)a!L6yep1~>* zSy4FvZV9gH3Gy_t^tu7}nkv0(Y#N|7Cyfu+2jJ;muX?8tz;5%u6Sh9__ptTx6Ylhl zFfy%8K@B7P`ouB96yQWPHfzJn$k3L;U`17&sbN0F1IOKoP72dUlZx4JH0vpDWW_gi zamDTY(2SnWnTzd|W7+>e_NR}k4au)Nc(2`f{*4DlK&`xFdklot(P(jMw1!+5Tfthy z$Qao^jfC15rEZ|fq!+_*U2~A9G2>pBrTpLL1;>at3ke?0Zl)!nCb;w+$GDw~$kQuz7Zlk)R)Jpmt@o=Q@sNF7*4-oiXPaykI}umThsq z9039lGd@57zNXY2lt5ilw_>9ofgGl+(-8y5Dmf1^4VmmJDPqGn#PHz|gE%zfF>Hu| zsEtr~`Ku@C9^rlUEA6l}?!!<9r-FX2~z! zL((h5)y+2tDG&XwlMJI?pHR|NHKMb0th%27HgX*I)ZffJEdkoQ z+rCIO14VhLRldnhKHQqS_Y}>cFoncVnGqbJIL_;spmls^_l0}~#a7^#qT5%|VMAcvSbUpdJJc-UBbUwE=_=idJ%@saV2Ug|T5njJtEm~oXYPLEe&$>Fc zn=D<4h7U_u1LIk`CPGf7`U$jSi}J8^bs8t`t~*-8M4Wrsv8FwG#7rRM5y5O8cnAkJ zSlMR7MasJzF}F;6t=q8;!R$AMcl}g76fjit{H&79qaRlZ_vU%|j?RGx@W4oI* zU$>6!WwsRSC0+TxPqBe> z(+Wn2^4I@h58e7`dCC_Cd}nc=j|u7G{}##>TiY2PxBdueIAY6#xspZSVch`%BGzqT zNfToD7OB|U$U2#%)5TAS>UNO~#qgUvHTe+ER3fDKJde*IFMc`c#WBnc9*=-oq3lpt zbdy7sB(~Ag6(9Uh5y0lURMb#4*BYl>{>w5|X`f`8`V6Bb)wN4&Gi7X^+Me-*qRm~! zU-IeWHW+0+dVh!K&gkRv4>0&mHbqmA#%s*X=BNAyi{WPng4Zt)7u+mkAp{(YHb5d_ zmI!8BBPI$6T=?0Ge-auP)!Eg9AnfxFR?aEqoII8xh_FGuQ|Z%9IDv;=kUhG*LdBsF zb#j-xd;Rp>tU^|@M{><0G7WS`LXp+UZ1M9BODBn$pHkZo(SafDS=-Q(s0iVYbJzE$ zi+^l${lKPF6Cy6eJ{61sJEx0Z^hvB(#pt^8rapJ)e{?ZE9pWL#M$@asx80QbR&`(t z?d%B~|G=~t0KK#Le}c7U#W3f1ue5c^v9tKUyjPhA+c)jPS6q!AnI)+c9fS13NW@+f zCcx%^xmcYe5m&A^WR4*{2BU}=MFq_Xk0ojwSPo$h=-z6xEZ$lj$Gi|9keSI!GZG~! zrYR_$mt|w)a;U^+2;srQ$v}|2J^dzwv>CP5gaF!b#4v%#VYS2TawKPRUUXCyqdVg2 zu?R3JsOSU%CoPRZ`VMM~8D;fkNm|262p&#?Pc5c*Q3<4r^Bfg{rOvKxKet$3Ln|61 zxgLq4lBv9H+y|YN`Ge&RW=bOO?Z?<*RM>TXkOil%<)C1~{AWWkRf9Zh?ga^h5OWCu z#oz(u{RZ?>1eMc65sa!k6jYpZrF<{mH#tDkLoOy%_XG>&o5Z|Qa(8SaW?fSx9Zq^F z&$TNjUOCB?WQ=k!N~X^~lN&4C7|46ALzbK^QJGJh++O_C#*Q)VUU3^q+SrzMdgGf$ zJWHd+>V`?aYw(QgjqdQBcVsKJ4X7xogtXCHR%aJ0lMMTHHx1u)hr~X$rhitAOrXJf zF{?`Ggt2C{)NGC3bw@tqvYA(KK=mjR-)cvV@QQ4rr>GJldEgoOQK5|UKMHXW$JKth zcu|o);ews^0At};EIE{7c$vvbY_I4^N$Q8`6e+xI{mywH3AELwh1O^1YbIN-@#5a3 zSKBKN!ivH*ZgYky`7;UHm`O-BCg>k71GakI0@EnZCb!8mi#7uJpv7=-YkAOGlDOpt zqUOJsTSg#_fmL;lo7fC~NL5$P8%$-DznRnO5N1<*4Dw%?67V)3tNPk}=;fMHov=!2 zGMK=n71=)ovPXmgi$B=IH9NzbIOUHEUmfwKj)RjnAN>Q(XLZO8k1CuY16~A?%3cr;vVHWR1c%}*_^qHzxhI~toG;MVMun9DjAks8=VX5VpO3& zB)6)DjVeQh72wNTIs&zIqSMXMNl8%fT^B>-!w?UDWHE@T(oc&&jkcg$A89d_BT*qS zh8+7=_M^eO<7Q-MsxH1;rnWO{J9(VvpO5~@BOM>H;~idy|4Yn zBNk=jw$a#CCC>lLoJn#1YeytDZrwlc|CwW1#Ex`7CviVfJydzG-A@%J+qxhH|Cm@HTgoaC2)5kM!{+XBIk8$B?ULjVECiaG z$0ym-!C^U_J>jx7Xa{qqbKo4GoB__dvoL+KX2RY1FYK5@PUh7_vKdzPnlq35KvkK4 zHQdR^Zd?&Me|S9d>qJAc^Dyi9`p!OiSqQuO{9{7#`IeJNQ1ONt@H0V7_|`r4di{(r zoSl~b%h4DP{78O%S_giRoNi~Q?P>FN8!JuIZ96+HrvWKJ;DA>0=+La&U7z-mGih`Q zI3opgg4b>*OxW#uen3gxaK<2vfI=X#i$>oaYGx}< z2^4B!NFlCD$+y5Kldp&a<^>i>hAD9(r6_sDoFSK((RhkhuEL06x4OnkL1t~?q8(Uw zqYkQB{1wiebzQUL*^{3}8_Eo`KB4z4RHH3ZB{vT1AjnR{`d6~N48Zh(Ip6jlu8658 zVvoZ}7_d$Q#F?rFDfB7UWc6aAg2-MLjjClX{=?A)sLjD{6n|`q>vRy;rre&UF{ZDpF;KAv8ZT>%2`o6dtTA+b zW{QT8=!^S=Nqj_&pov&RO%CTdP1ff*;YOAD$dh{mtVxBUDjwrhZO(Jz*cuSuV6{SM zeV)^7{K)lCtJ6&&d1*O7>e|Z6uy9|fx;$Aq2%Re3o!Uuu5 zrcVe%vCQ0x`7~Ywce)Oc8+}t@pQyTzi^-b3uU%};^4BoStrMPS^UuZ$1-ei(aq8Xp zfToWD7}=^5ETcEjD$HnWz1ALRT1EFb=X)wQHWOXsL1y#+Voa>LX#cxBdyk*lHDgy8Z{g;!9o|5g8b%RUIV~L-}`;(b=rCzj-~m~5pP#u z8i+Bb%gCEgmy8c5p+r31jD1l(pIFYq$uB-$>((s8Jt|Ysgs1P8sRQo2R+G^{{gFF*9n92sz$z4U#jV!MH zvYmtQHuM&s#A2aYcAyVCOSor{nQKSD<5rAAwpJiikIz*_#}qXdB&5MyUs=+86fSyb zV|JFHtX7&z81TNU=m|vuBmzQTmq(~J`4`sUX#@N6Fzkz1ph5y*6026Mpu=|Ef6BG+0O?ulLItL5$ zW6i>iMQzUn9zA3d2+I^B$lr^1U|9@OxNoXTgM6s80WGNN4O*D-7Tr9jFqFNF7I63f z16rCW(D{1vQVGVuM+$+W0F3SemAgHEuZcpWpz;6V6Z~(&*FDUQ{|`3&f3VF(SNXq~ z{}R_Xl4eD@KmX}Zot(Zp*?LpRURkIz9#8)38$pJv-7atO7*D42#gA#qFc4!p$1LLH z7%*LY%*$}p5p@;1P_-C|DdIi{$YncR>0js#rDBTuQrh_5gVN^fWq;gC39L)=$BlhF zl5^p43dBW~T5TtbUf5X|sHZZ~)sNBn+A=7kNDjf>ZAUY=!;rL&2ZV0mS1Rvnuh$I5 zBbp(z$%=X7jx(lQVzxrhC;9*aI`X`hQ0N0XcU{$j;V`SO!(sKM=ek)@Rd6|LDo2@D zv3OQi9vnD<+kw|fwn_`~6xedKdkjk^%!3AI(oCO#D5CE@V|-L6al1^!E?9(o`o!b% z8eJ-6c(hF=OR3r)0N-C@{XEFF>StYq8P!*qt zR6~YlvzwGL<^w9lR2&d@)5Qfjcv<7JrCc#E+=+o=Oa0+X$JQ`l)^cW#_6LJ#5_q!Z({BwWFdypR$AmcZu9I-C;p#l(f zf01pq7-xp~WC%WqOo!ky)s@qdD6wH{zZk+JIE3)ZFfSlj9So#D=}wpk200E+0X&Z+ z(w+q9L_L%(!{AeXW(+g*7u;qG26A6LWxp<*tXH8{X2|YLycBJhEOY>U^bpPH?^8cPO%Bn zaDq=?=E7+>uqb=XRZsh1Nn3n)hL88svC9MakQ6Jha(luaTfTG04+8EkB;dmtr6N&I z>gJPDPS1IbGAd!LfpNl5owX1gy=-;VmJCo4GmL$W!z)~IWb32*DH)r8TycV!ScoJ0b|fC_nWYED$p&ht1=xrp!~j^SW`69*4kk3s?$<#*<} zBq>UDr!>!t{1roAFQ4@~^NKFGAw1W}$R5}4o46b|+{S%_2i(kl4VR;i`QY3zhrQ;o zLEAOv>iGP=R&@&3f-Yd@iAUXybotPORzN&0IhTaRC&_bIlV{s;3JQ$E1R**2qINt# zXCT9i@!Jpkzkd26qeQgQY;W=R#Ce)&pUCH3Fl`pOZ`b{!R7N4NDOasP7%l!A6VBY@ zwQ@!^2eZETue|;ofFoxxtkS~6&4LOk2;~;xnYz`sV63a&>E2dKIIljHbTBW*g%3o4 ze@X-jztWQp{9$~xjtZD36jLd!_5f4Cu)mcO>NTPvpOr_L_fi!45!6PW_`df0hYkZEKyD5lXBYa zDsdlKM4g(NRTu-@L=ov@F?)8B7nXeVwC_-iO)tB{r0Ly3O|Y6cc)XfC5Ov(e@#!-C z$%EQTT|C#F8oFuYW}gmD3KY^K;EP0XVDVmZ#(pdiMh`LE*Y!{X{M`%b@&)@OIUQjhCIa*+>QFaFsw zJNi@QbCuSQuS+N;TAv?i{VDENb;7a`t)C_KVfcoWQ`7n++IdPb@*$k)>}tgo;3rgv zGHU%ChLy!7Nee}mp^r;sJr5&V-@}y||<Ue163BjNxTA$cTRndjxcZcH}sAU%E1dVfgj;AZO2H!hY z6`u6(e_n;Q`|Yb+zh&fq-8bL;KzH)(t7q!x=y%@z!23A?OP|u_yA)tpT;2k|QVA_%Lg#_G+Z~X|nI;u(SawJX_|lB7U4fS)HRxt}X4CX{vyoc$fuphbf)owjg0Z0FGXWN}QB4E?N4U|V$=!W#OMq9LDx-| zEUbADO6Tk8GR3C(a5MwX_W3z1$YO>rgL4xBvUC?Pg@gscvF)0nVZg~6cXoQ6 zo7;1=Q(67`)*Lg`DXCDc~ov7848^fA{Rp|zX;XH_SK8nY;>>brLw2&JxBz~4?*fQYiWCHx&T2p;Z9 z*2jWDbHRS-xM{F=+krM?@!P=ZD}9&(fZ@`3{_93S31Rg3q#UV);z4%vCEZw;YL4Ax z{+||k$zW6WTSrQeEakCWnYHuC_}#9w!zrHQx17XN`$HQGXp}6b!3$mhpMLWB@NF0K z-@eJ|a-`4r1)_zojR1AjUS~TApDFzEE>180G;J6S1dzcLqpa!B6waH5FiF}NPxvlEzbZDaGx)tFkdkzqL<`J>oN&njG2JwgYXTiTM zke>|dA>&N?rDbh%HZ0VXOi8jX04NHgwp?*6Q+d1;HE^(~PHd8UI#stbHXZtLOoiC8wUcyMyPCUq#6W z3xrgF1UQA$5v5br!;(l9!{*_V>_ST-)YD{D0bmE}lJBHiNb$uFXYmdopam>2!>tq( z&h*w|-FxR&PY`7p zCDn~v@U7G&0g9aIee_XMz={Px!JtJN?^%J8w3|S|D*)wM2B7R3plTsQjKbTK4OlQa zU~%;dSj0U!rAM!b;!}01`JE6Awuj7HL?hEEbe@JDq7h>^4avKul7=)$S46Am2kWm; zYg4`4s6};JOHD#6NL1SvC(tTna@x*`i8Ir^!Uc9JuTtYq7G~a)Kpc5k>2THoPY`IG z{zelPCg4FPB_<%yAcO=btV(SJitOaAJiI~X$0n2VbQ50k zm>Am~)D0tf<&>3wdllV;z|s0ubddtH#As%o2AumTPfeb-$c*W+BnuAr?_J=Q736XZ zs*JO-;$+B{`Na2z9xPW2CoGG>$syOmvMy6~19_huZrfH?KC4)zs0Bny^T}w zIFgLaENey(MPEfCC~+Z+(cG;V=FZ61BiKYFm) zV)u(9NK=Lgz^Gq@y^=>^A&hN+QD82!R5^kcV@{&8|L!qLT(8;00`*yfgQD{X+si1d z$TkM+LZ^%0U-3*|gxX#^k&F$DZ_mc**1M9Z#CI6xK_6UyH)Mc2yU9D-t|ZU0=M1i4 zKhp9T@*tQ6L^;&}jO9%x76)$F?<61ZX6K`Og+@GJrI~??{R^Tj<*)Z+6a_A&-dP2K zE_p!~Hu|Lbn(_Ks-eFT)hjb2Tpr68)RgQ^t5IjITWXWD#Ext64psq#sC{Ss^v7O?X z!(B<%db;F7F7PCMUWhc-vz_2^bz}9vx<1WN|4hC1POXLjQri(^e3Bp=XJ67$Ri}Wn z#F$u+xK{&kxOI^p-?XEcZB(8!_nd#BqYHQx+HkP%I1Q-X27TG>!mbns7a1|AXujq< zhO3eO;rDYrN0-R`m)qvh*(&L`n@w{eXW~wci=z3gPND^8h4jS^s&u7u4c zZuz4;f}vxbGJ4l=tgpnUZDPOdO{hf#-O?RDbs~r)QSb7Gm_~&QP|6=*+eR%p-~ z0Gl37sf;eR<)FNL=BB0r1^5|a4V|#f-%p)9K%$8-ji@Y4gfReT1r#b#W*vQ#%r0Ml zadh5P++P2l7w7-f^NwWOur7+mb%MJpN}tWx$;U+0dk75rxamWxDe!vizu~Vb@^xvr zk9+o}l7W)z#w{xtkGPC1Po`cj$&0ZSN8?MT-t1#6Eic+2lhr(2mPJ}l{?WrlL(80A zie_GWxPX^TFI5UvAICClYq%#IYDhQ?hgXwe&0U?-aYXK^=h=Sw{6-T#u#h7yzBtL<@ z#h5)&7`U*Dm|;JB{cCwJZej{T(VaL^2+Y-ka7uSOKg%$6^~F9uPhYudKyi4W##(O{CP$WFzpO> zA(7J;KVVkneEx5a7dG6uYsbWCHq_-t=mRpyJZMs@Ea~MO2FmA3seSPuHs6YR(_y*hk(0__r*w7NfFfdxUTH|gf~zQ zFk&;<5`x+e8FOON4J%a>$MiT8bxYqO#l%{po{-mV25ipRLDq*Q;n-kzn ztNe>0lYUH;EMBb1;>(24Fq+c^?lLKfVz@BcX^w+zadI6C$Jft;nnhoUSm(E zdXYnytA$(ES0`~4S~J4Qwl>&AeZHP!;f2KX9}p;x!KbLAA=X$En*f8@970e3HC9f# z0R%@~%^CM7z-1&xrx6x&a`*M=4>H4z#+W$gM-3>7v%lK)QbogbIKdHv4A9XQH+Tc0 z>*z$lKWRAOnhjEVQUh%$1zV0laHJ>fx4-zWMbWl=g-^mB%2!^3a6bPJN1-KQ9xy;B zzg2M&PT6SuIiTG?8K$4!_x3oq-8+@b{OtH+6Yi^|p1ru#T+hFDZ+u+BC{&1J$(vaM znX!)X=L~qWB4fNrFP2**1z{#!OWET%;JFl&H@Yz^RPHMaVFs31DgVJ&$a_Nwa!U00 z^Ju#Cfck*lD0OI^#5=N?SmXHO6IhrAr*z1Q+&7~z2~OP40IR849n=R0LkP;`E^G`9 zEFQ*^u%M?Qu~L5U^IfYE`+oqAmm{#MG&lqvtKI^tH1EXMBOvwE{fcJ%?vhROP?NiG z(evs$@|%zn&wop^P;1mqOK{DYyR?geZ7x4DY3UVKDH~8L?Y_Ek&Z+*K>#vqGBYmCi z-0)5*jxYjJVG!I9MbU;0j!fW?)BSxy+aMheFIX%G!5aJ#Ik73|C|?t-l}9)rznp$w zI)spGA6QF7iAj|zC|Fi%h+9KkRD4*NPL5++vGIP%D43-EizgNvb~uF!i)FYY;JiK$ z6l+KHi&f+%`44K>c*~o}7@!iv<3*Od`5>B`Zb@)>yvUnOm>~O@|JUry)5(<8rCLaY z>EFDkOZ_~TUeH{xK$+7a>pty&vP!M~2-N9+=u)j!OU$pEe6vk{{JXw*D>45YBjgvr zJ1I2}4)Z@YQn7NO#Ldy-%VPs*){WU0IsbJYIz=R8Sj$fJDBuE@%8Bx!4h#*lW!-Lk z$u);48p^?Ut+-7bS#ik#a#wSSbk?vkx<`ndj)H*&qa29W<}K_x5cvCYB365=_#E#C zpUKCt;)WXtZZv16?Qe2vS_PL=woQ3>mcox?gVbUzoiB(2q;`(;G!l<(VI|>s#A}rO zWRVU3fu(vT1=@8SGzu@BO0)Uzoo+(x?>D0MLW{9akeqs5upPL9oYu={;mO>qSH!Mw zqO`wLIt;hJDN&hO3t?=UO`<;6d>oQC(vLZ^B`-*@{s-3$jBWR!Xx;3v{eUJH1& zoA1bB`cLa-`l$cqp}x4@5qS04KmUyJrKdf6$|(eo`;V}@nHeEeHKQLr9%htR2X1xO zt`Sk7C`pVlgA23?$Vit@A55gp*G69)F3 z^B-|{HQOukW&7Ltmsc_EJ%Am<<+EILiPkRe^Uz20-A$R1q1KI#Z3LrVx0!#_n8TOp z-@q9ste{9ErXB>P5Vj-b2;iUwlxStu7B043ytF7R96v;)Yi9^;)*E6dIUe5U7x`XC za>ZW@TVK#QZ=XRwJSnb}bs_G-*s_A9yWO(x?_a8mZcnRr~Mh85z(k|eoQ}ChiKY&EVla{ICI+X zc&XpZ_r1@pgKu3ulM>-X4ix$y6L#HGyEp8a*Oc?i|6_-_78fAQR+lQz-y%>ruN4S! zMw)x@2_l&4ecTKqvsSmW*N$0g{mWZd^U=Pnzl-Ex3v>Qe0yO_?GvBA^4A8>{z7cGY z%Sh}s;ah?w=8{Lma08CKS+BR@)Q?9x69qr(@%yxLJWmhhgV%ebE~w!??el{svh6mwry3;*gj+oyl!tMNK>i_Mfv2`1CNpx(} zb79mX3tx!M4DET9dVtAY_-(1MWk^~CfI@@*luF^)xbnLZzobvf?N&<$BZxvYw1O=cPV z;+6O(oe78`0PW-)9)gmsG~bCP#sOTyo7u#PEx<2P`pF4-(hs_4f^Gp084+7B)i{~O zgDUn97~&ZI3K!&U3DqyR2;i(a50oM!)2t79(r4XQxqd9tf$M^JJJW(ywFXOt9DQ=u znfl_Zm8&f2YxH4us*Gy!{z%^ZN7|w4r7oks=ve{HRFL%ozz4aKt0j;%hLtY6i$7v# zRfRIS>;DMd?>X&p~%;PeLx!-{o)A5hw1D#%|XLbl$mN ziDRzQ!ZDI6L2DsdMJRY(wuw_U0imUz6v^%4US9=>nQ$&L`eDv?qL=hhpaxvP9E~Tl z+0=ssoKpWo-}pn{XsF|lI<@EWzT{m0b3gr|KMHM!>rAWK?=5~v1@3I>!g0I6Vxlg* z@2mdeFOSwwy3mZpNf|H<*euFHTyNuKd=s~={6j644Leh|D8O6O=)LSilF27qnoouA zX~=^n9D$yCw-&O1|IRz-BRLeNVAuNk#HCF(uup7v(celEJ9WwH!Q)L7#j2p!Y9sNh_tcuSz z`&kyn+7~+VNKpt6#e|gql@=Dm>TSk0Hakg*DH1;cQyWH#ZXc?|!$>^gGN7agKdlWl z|B7)97G(nR8`Ag|q^XHFYs9s3Z;RqYRAq+-Dg&TSE16@zNl5pqZ0U{|0yFiOwu`9JfM$8#u+?>0ejJI->~crpR(LUXk>!u_mgDnJBUX~fb1wD&VBSZIGS zUm##|+4$Wcs~bO>f6LD12x)4`_FmYmbM3y{O+$7Q=eS3B{O#J9w?DvfVJiNSTqpEq zAa%&h13KY%d5)pk7Jq5KF}jgQ+ex6fg&ahmDWcCjW(wCyer(}o@)+IWBUyx&*?v;* z4&*G2#n;PJeaBFE*Sx;!-E0ToY`gArhz$~}O{YBafKKVg1!DFkrJu)~(OV`OjfDtN z3t;KRF3AO>p>EedpeG`7KQrlx!R+5b0H$|^h9K?NITFhmJk`7LZRd+WDUh;Hmt$mj12fg`ubv~_42u4N>o3zKG1>+M>WnRN^jrbUb$?NU z2osPnqgZ z6cIv}_eh{+SaH*TEeGL^a#wi5O$p;{u4?)v`$qO7*bGb2977=rIe2aU-7^lT*&KOu z&@hp`uIqz+p$=M3WzG?ZOsO~}4#!dW;%L~VYbFH3shO3Jq_g;ktrHLfUpurq!l2h) zrKD*%`EccSYDS^TNaY!^@;uG*vt*gj>@S#i^ZWnW45vt{{a%Xz3$iV7=8IMA;(@jEwXnA=ivg@5A;0#7www!B@pIdd^~qA@EYF}tR6}%>CZiC3hdGC)#q-2b8qYt;@&5pN^ z-Pw`_2KDX2H5a{dIQGW5uw}XtJ_U&KHCl7o@37s;qNn5aJzYj zOKT1N7PR`%-3iFtGVc+iJo7Vc>oJwl6 z+C?6F7Ud19RbymB0O~De57@-;TyCZPrCYjZum51{4D{3Yb9Cdjh1=bybZ>!*rTamE z<3)bDXGDVAs+d-`Aak&|D9Q9ED1#wX2J-lk%8G;LS?&%Iv)jWR_@D*OZbSCH_@BG| z2S+-f$6#zI&FGKQ?2JqE{_JxRR?fC#%N`&gR2;!=Mav!kmGaD*Rz2BmhOgn*=j)YanJgZT7Urw zra^bhC6@)RGdnLN?uZ%%TL)Bat)AgQEmS4zZ-arGw5o_)VjVYWMH^MRckLs0!Dr{g zphvBot%s_F>#)(hQuH~gyLP-Ba2&+ZW({5A{is9A@3t0|INdzXb0GeC*#mVhM_m>4C$a~-WWk3nJkn= zi;3IAzC?`YHA>uz@gwt!%gUO?hBs_zF6joG9MdJgEU$6JVEF|o&{1QN$tFDZL2(UG zahyi(D|n-b`K)4u$p~_{hqQN@&!ar4P?NLu*FQ*#dAoD{7!i zn?qV%D#x@xN>i(zf$uPwxo+gIl{loNyUwUkiK<2px@RM4mU>0fWKKqya+?#FCgTKl zoU-)_F4d`D;3=a3trA32O;vBZ3a)B27_nVuv&L{uVb}=#)`mOjaVs`H$ zVnq(>!#N9p`vfm_{aM>qdTN&h*Wv?;x-95Ynjz>`zj6%Y4SnUbnyNEHQmwBVl?Q1I z5IkGKJxe2@FL#04e~^l56o1}5D*@86*GqY$W3M{=Sy;Y zTmzgypI%+>v{=J>qX3asRyPxH;E zMd%ace4Rd8rILpsRWdTOxyBzMSZkee?q((BcK z)we{i1t{#(?UKC#U706=swL63godG>01fobL-0BxWj>wtODV`|22BLpvaJEp^2bm# z#-`A^%^49x$&_52r&_!su}_wE_k^i}wCS^9#K>3C~FAIXDU`tRzJ_09H=uQrC7Bvlj7ng5PDo7r1xF}sTid9y45Vy@R?d)Lf( zQsL%NCefTR@Bq%{^WQ(qAT(dICI}*gossAvF{@_0wc8|A*Q|*`1>$K^GN59MHDf~1 z9+E^8B9}xFRkOyL<8CasS@PEMSN?)jNY}cmZV%Xk#8Mr}LIbNTi4cYGf?4ch!otC# zNWgJ~v`h~aYi(@db9Ft)!MLU7HqdMaN;Iu>fPjq}Ae9)BThYX_WHC1*R0|Q9lCQ?} zq-)C?la!4Y;XUo}tU3BcWbz}-eCs--L<5I#;XZ~4+gThyE=BpYd1JWz46cZ*ZZn)o z4lfnMK@h3Z7_MN{$1f$WK_k>Yxmb70ENi7dfA4raHeDu$%$P$d?HcS{pUi^qtvKY| zqRr>u9V9(~sM8?5Fhpz@91Z#AtvuD}4Uq_pUw8$CVdw_RInWgh;V9_f_+bgIvukrT z)k@GxJPFm>XykC{E0pB%OEm^k5+Hs%%+rRc+88^uele^A0&3NnAt=mRdooWO;%Usn z5I=T&DRjG)6PdsR{X+K~W-?k;4xz7z;}(9IB}{GCgF$)4t2PCC@LMIJHrK?2g5sZQ z24g@KM7^3U@b9-=Ik7$W@B~469%V9xKI_tEg-q`~`_3YPq2 zuwFdLH*_ufR*oW6><%r8zK$9MF+f0IT`tdZT8%a)2d!R)A%(jQ1`iYg0#?y^#}Ci3 zzWlALoX&EHrQAtfNM4Xg2pT9=_5py?CuurN|4%Xkv^g ziE(>gFhSrIGl_1-3+3F?4HAfz1POKCn7fQ*jCuiU!D6g|{$`$)$ijhD4;PMw<;X}2 z_@Tnio0|k|Fb7QC{>$nVyrzmAR(WAHOwdc(3#sszHWkGKiG~AmIOeQf zDjuYT;t4jxgNQ+K;Kza2=!S;TRJAdQ(t_<28rQ{i4)1xHSV%jcj3114svl{|oTu`k zfg!!`%yPkn8=aTtN)goVqh>nZB|Eqz^l`8n`Sf8HYQAHFm*6 ztOkR}o6-4-gK)s3*l7beL~H1kGV&JK^tXI`+@f7A45f1yZ`|WBBPr{$pEfabI3hiE zG~CP$9ledjuZE(ZEvo?5H_6!f=cvv(0t0Exmw(SX?h)3c|LEvJ&W9WIzdWjo)ARl# z=)$%F2^Q28rg!LoG_I?jL+ zkKM`#PcQx_yJ1m2*n123_>L3TWg|bfc51vH5QljE;x9CNhfd`{%DkgARct434Sye(i%J_bg&w{d2Jr?GbLo z`{v^0(ObWcc3wIALcj3G{0u6|v@kVIs@>On$98Gb+SzD^@1|e3n&wqoV~?=_@4n{+ zG?hc{GL_Cw=ZhaVtTmed&MJXK4_h$;ugv-m*Ng0D)_SaPqqw2KW7i9=tU$A3gdjZX z_99rx{z9ER&zLR)6F|oY)~6%6`)K}Wc5=F(xK;)%py3I=`R=Yb+_i%Y%b_K3b*vYj zvP;gUWX*D6(164|-BGTN5~yQsmR7IuE(_*raEH3ro``h_YSbXxD+So&A+s|qRq#YW z>5J=3)zmy|lVona(pFwYqzbsk8e2STnItM8aXf-SFr;si0RocmY&uO>!!b>1zmwua z>+8w7aTaldnp)gL>gzc-Ykll6ZPW%-R#@fr+H0x6JL|4X2l%jLZSZDd<$olZ&Z6f)qBkt&yk2*t#QL92i@VBWZ`D3$su!r*IAWm}F9rzKpT9EexQ0WC+A znC&4}OA?>;KPn{hca!S2)h*i{LqwJ(s$MKiG5j&!6<-qM}Jd@jV?!Ys$@ol~* zeS0g1$K3MTvthqmvL77&jGIo@ha%nTZp-b*q_*L`XY(wtxVgn~+N{>NeiPYFx{;I+ zn@gZCqASa{aWH!|DlGpj8}IFly;F72lW>utrp2?x^3O6c2fQ$^c|n)7SfBm0x(&-e z+ueG}!?WR5-#ZN6NrPjd^9_i|&cgDyJcEeGITT8k=Zh?V%M%V^c|I?|KVAo&gyp?M zr3=G?d00N01|HH%hx|pfju;q)Cec^`F0dhRmv`VXEZA zR%?25A}2@b4s?*L5|?Xrkoq%?-sEq$=>1H$klw8~*o9^kUJP`92I@$6PI_c84+VJ& z$!|;0GfDRttsu#7OY+z)}%P6D(@ezryO zMM%y}0qyoca=u7%A(Z6y4auL8(d`>q}CiDS4lWz#>Zb~Z{x#X2% z8W2epAH`=uB8 zXb%2L>^!e&uY0CZw_Yfv)a~74SCP3&8D8rJNj;<5_Ui5uLlb)N6pYnm@mP(Nnws_! zqhn3OaUQ`rx+VCxU?^Zd>29NN2*NOiE@MuwY^hXEu&Lt9@6s{*N0-n0X17wa#J8Ny zGk~TAKmbkz~g@9|N(sP%9HdXv8P#a`{=(w^Awf7)~Jdy6XK>T_HBVR4`b5H|Z^ zf8a`29lku%;&0dwJMBMsFf2R%{&e$>?l0rDd6)53+2?ZY+o^7hsJE$b;}Ii(V+D^= zJq6G7bOc%Uc3f_{pg|A7BOd7(wM+cCz2!Fvg=CJ<9j+(v3h5Wouf5myGr?cMhi4Vw zAEhw-BtYvAtQ8(t!i3m@oG+UW zwEp%v<<3tmo)ryH_hcj*fGQG=K4bmWZ6eXFz>6R>D`Ob6Hj+qj1I6-%@n@bG0yu_a_I^hxOv{)vt4qG5QYgq=HO9ARAs2B!&DE6qW^nPhhY1igd z6*{2F0tU8dRfJ(c7-Gb5M;V>~bBiAnNluVv2$nID!Q+EKVDOmIAcq#`*jq!$my!Au z0E}>1_|)E7>TF#)C*ILbSOgGNMB~%>CP0gi*aEck1Za1&&IgkT(4ql+yP!s=6)sZk zqff~^!wi`(tjuI^4=)F3nX-$8ZC;WLL6Q&0Nua)VZ`jlc4hkKfmwkyKp@Zf~D!(Be zkS&dx3m%35A@Cc|)&3$$Au?NW~n^n%M;w#e`hvhFnzu z+aXsu$&jnOJ6TJYuIrmnH8dso6pdxbHE~n%*bd2R;9^b~lBuM4Yl41<3s|?Y!a--V zI=p}Yth7lG*TOp%fcEnzgRH><7J(;0O$)NxPqdyIoQbETWl$4WCW1+-+~k((1J4-Q zL34kOSomautluC1ltTiZ9%OAIeI>~H-ibjz_#YH$w=O~jAmBTyrXOQjF=YN>WdWKX zAjJt0H>%l)x$F2Ng^JaBa$zodh;tnEZgD8_7Ek3Lr#a@!M^nj$t^6#y0;6;iT`TqF zJw7!0`q-MdO($Ty+Qc5C)dm>j9Rglj5O z^cfE0McAmBw|?Ca!`{TYSF+3`l?Z%Gvm74Z7sx4xhAzM&tzbq1*%V@7>UXiUfd6<%9vx9{FXHx5y+~!a|9j^_7N(5F=?ScL z_gblRtD+?ZJgBJWkl8~E3B-;KE5O*ST@+*F_Yf^=cd?TzY{=yv1#x|xtv)H%G{!mI z1ZPo9{x}nX(T$TcA6@1eSIt^Q-7R*Xa4WxX}q zZcl~+bfL0a-)H(0+9R#~rgyxO%e~_QajEr=PO4d9l~Q#zj5n_FEb|GJJd#{{dxOYc z9qqKk#F0dR`a_PatzKW^TT18aSSS1pCXGjr<>Jf!a5Pk!fafw&de%%51KK)d+SLt} zJlMAahBSX-fqY<*qgCyj3DED(eIti@3}&_U$m&=rdfLADR|a@nm+4-;o|wb#W$>`2 z+PBRlwf>xbe1tWvTR_PU#EeukZ3vPtg2U}++odZAVkSWbIwpR3t(Xu>e{rw45HWmATY15ae@eOG-|(mGy+no+yf`mII~(62#uVJ;JDU%WT)l@su7JfuKKL zn~6HhlW)@F{G+p+@>I%$?AOkd3L}Nf_>1jq#=hwc)1B*+86(h0{N_q|#}N^HLXofs zdej)zA0}yAw#?MQLQlvR2osNJ3k7wngQ0CyMS$L^IF1D0S;uj}rzV+#cvsvN!;uXF zL@Rro4FRCEVG^^=<2)?4a#DOM>{uSPKDLJxtgRvQ^Xib*k=aVW)f%!;m|8M?7k_cD z@hU2h2?t;NOURLU#{**hja6x_xbNW67S71~_pBNi8xGuOeM0J-r(;^+)IGS*m2P^i zGBtW+**I}H0AyIZhlN7^&ZoV~2=S^Bm1Z?7hwJ-LJZ z$vS7tzS(MP6c8W?D>I`!GRUCy9I@I#aU}Tyz8at?sq{hdkdd2}L*7I~a6^Pj?O%02 zyh2&hP40FlCzHvD9?T>_8B$Sel%!Z883wNPya>n&gH(pq`#m|Xm9%bpuSca{6@$`> zJ5mjrkdtYf5F`x?79nEQoR>0F5!ZkUIP3?9q8VArd$Xi6s7^No0eQJqLuPjpXFml~?-<_~9JonkR-?c|tGR3w%0!3LIk& zwdVtOl{9iY7{GO{+A0eiW%yPi3)5K*X#8~ZGS-3Ufs*V-HnQ?k3IKHyA_~ZO2J!=W|()+%_TWc@?51)pTKr* zH#F2{i#I*V`P=rXKL|5Y#)u4X^1T4LI5Iwrv}8@-np=w#_iWxmj;d78ByK9zS3}#5 z2RJUTiJbuJmr!Sb&ZKffB2l2?Ud|gvp;Hymoq`cwmVR0H+~fjYY7-+A@GS%}@5XZr zbTuyzD=)jhrCR1VI=7Va9!0ZV93pJf%!B;uLTJd}0%&_fm`LjKteb=S#XF<-+> z#+tZ#(LLJ);8}M91MQqNF7C1K!=t}LrSe(q&m(?cXP6eDuW}HuRiJ0-Psxf3l)qF9 zQO0rF@W$Kga*vmiP;#@uTUhnkAja!kN|{&6^2C4`(FWkPgfbQP%JP<0s$HfUK{VP$ zAqymw2@`};WoN-cUd)ULhy~JpP7Q!hshVk6IP z>XPFI2f*B*>?E^eKe+B60Os?d@^P)N6Ku&oQ=Y(?84N$1V9Pu<7r$GD;VVDkDCbIa zN3K{8!E4l+)^7g|Iq_DKvBB5pH{ESttnTs*F(gHFF!H?R6an0R6=Ay*MqZDHc7=m} zf|HSo$$ZGdhBfeV-f*!-8^B#n#L3#NSY0>6&Q^4AW6^f~zn;o7Fz8L7V>;D2Q=<+) z`LXSL8Kd3fVNd>rEp%D3bV6a?Xltu-qlfGBMT2e>rK2HjfIrYR`M_sn)6j2n=Yu6Mr?VJ0fC2{?v?HPh+t z)vq<_=}b@NN=c9{98brwE^uuG2qQp%01-su1P25*pn#GnAQA@*2rNJZ0VW6#AV7c& z0z?pazVCnR+Eu6OJnlVGl&r=J-BVS&_Wt+({{Q{&U1$kW$H5cyEM_-jAzC(bv$9{@ z4OtmkEpk9-1=G`II=YX{;21RaxfxTV9a__oMP#@Y6avLjJA0WF#jS#P0FJeJ-@Jo3zcfTUJ1KI4$^!Hm4dFL* z2!VapgCfy8K;CTLJJmgu5e#uO08u(?b0D&DVop8>zhQH*4!Ba#M&v_7I5(pbp#Q?# z)Tu$+b12ZpW(Uv_$A}!*GuUeb0}HnhF`o6xdGh;MteQ74>_t3$1&{{EjzZ#58}eP= zSU}7heW~CB@pnzp(=x9)&ff9PQQaIS?d|aF?XeI2A zk^Cb0n|nY|IcBTN^llP3`gDqM-b^CE;gbwlEUc}1OUSk03FO@DBz0NM;#MfNIWFY5i6nGS6zy$ z!Df8VJ{=)43%8r5R)U$!*sX+D^g`KA-GIw@S3k>*+e9i?V8BRp`h9~20fnkJR~kD~ zXey~QcqW^>%^ZN=(dEvL)#hH~4rQ56ua1E_UCh9MWQ^rfE}U$0!YlCaalS^v17Z;) zX<*0qEDTd3LCeX)tjC0kIlJ5PyR^}>iV5cLSUt_PJ7s9?nH!>|XH1a;3alP3GN$kk zazMoZUEpzu1o(ZG3babD*6O3$V_}2Hb9#Crc?{MBFg(N<+k`7i|8^F4dV&F6Ulk{Hw+k3dgwfVnG%j1H7ZA8B-v(7=a>jNtemjaJQ}Wp zHi5Vcqadi#y;k@U`K+WiJyf*j87pM5`Sn=KM3k*nCk#!w3;7@La8;-hZl=g8Lx)szqmlGuKQjlmj4Ptm^_aq z=nA}mFxe!M{ogXTmI%B;`?3ebq8`15IiWaBkOe%M66Ck$C8q(}wapcm3O6!1!9%4e zdVrP+3_;*8RGQoNrM*snXy}cteFkJCp~IVLg`xMeXPtn#KKO zYDYQE3RQdr2E*J8cgS)j>nN4*P2`lX5aXsqC$|~mASP>w(l|`PuaGKaUnnf#6yaW2 z_6bIjGE5`KqHF)oI>F@!@0bY4Wtf&RmVqgV2r0zn6?|afbK)KzpGvOau_)Lg1Il8r z3;hx?Pgr;*QyFUV9xJ1P zeRQ*=M#7>yRD3`QD*72r$^;4eQ=?2q4Lr0FvX=*H@lAy&SSFvzW2$Bn-<0r1i85heu74vlh%$X3lV30QwIRp zuvpN@41{liF1wip!&`3wD#?o!Nf3m(-bskj;mWP+oDj*rdsT8(R1jF@t^$6uaT8l^ zoS))3WEs9Z(Ve>HH{pas&#%fhZn2Z(xCdKgfH|d%rGT>UMcr12kbLs0(fNc~G!_9t z9d!5yN|1uqUBl0Y%5!82_~0=je=ccMx4eT5n=WMQ@3igI}wr-dY}b>i*SQgH(}5JE5oP;@Z=xP|$D;%Lz$_c$kRQh~i!F9KoV z+V11XVw@Zt0i6xotu?RU@fh>*5Yzd`!^YtOcpNvF@kE5Bo)a=}3)xR&T?FZFc(7

w7URu~6EHgH&Ept3!(3U7N4k0R-+RS%EPjtD>3w!@*8yS7za6_~2 zI3`yp2eY>t%!7<_c);Lr{xRYa!WJ5Fxl#{b7yoaHMnpPaG-B3xn)?=*KD`KkgZ>0q zMaYSt70rw80D>>gv7-uK0|PL>OfOeoON-nZIT_9a@vCxkWb0MJ@Yyopr%(}yo zhT4Nd`J^Zm+G4IbFjYiqGaC=}gImhYq!nAh1j)(~-EY>P$ztPW;ygq8=?QZEp@rY; z0i>O#0wRr{gEhm1AU!4eh%6j#vzkhxnISfgn7zFS3w87NL7gUjv$U zP3OZh5sDh!<28XjH0VTY=wGz=2Qze4Z-y2TGjR(##d1RDV?qENQDKNeb%?3t$KqYV z5DvM$3N%wRfE}s1CP8KQteHic0$ZDp&nbz4W-3qbNBRkQM%)YzK0FrTa?wxNmU7G7 zV~GxIm1@L9Ofa5jfuuaSM``6`!giMenOG~7(}o(E5UnOzP`how(}}G!39914Bhp4lAoXB!%>GVP=Z^3+KAT? z589W$01wW$mw`eJC#Ov1GC$225o>C{gsdBZjn<~6l+3@iV|x?Y(mgOore-S0`2f2S zu|YSH9_*AIBs$VBx9|~cHl?32`J0GXA@38}2JA7B*nqr0K}^8;kX$sberF3b8T^n0 zjC`E4W6X)F6Uq#|OuR`^)^r}Ok)B zYz4w0zYspwZ0Cu6Y}K84OW~q;elW*w49fQ(^BS@O=sL+(*~#AcnwZsZO^Si1v)a;wCGHj zHMcM*h6^nA2shCDn%@-QuugMQ1mrVRUd4?} z+=788Gg$)$79+AOMZS@QMGPLIzlM#Z3WeZsN>Y$Q3jv{k>k0J?rx}+N3Vx}T#t*Q& zFaY;x1p!byNh=IqWrB~IY$k7r1SM6GoBTU{e4(5LUu z=a~NNi^<0tCNB?N*&Xl7Fo}Kj6_|XiVKRQZ0+Ww5OvcRuCS@Y<1|5UB2`FPwOh69? z@|y%Z$I`w=4MTGXL^!1fcO3jyULwF3ep~n{fUCVrCv; z+=_ahWeBtpG&=g&!4^pM!@}|72(J7cg#vG|a=3vR{uEqYM4qsewjc#h82fdFA6brq z1fpIPm#E?g04aYZa)ueL!ji#_K~fY;Zsw32U&|T@@i|)ff_3)OTUc2A6z)fcRS`Q+ zs1Sh4zA#w4$qYM!5o4~(THq6Nyy$dV%-qhtE7qRwvc`;0RO305`<{4US0FUz+sci_|Cx^M6}QK7rClODg`kpN zBON@1yP1254CNICt3);1#NkNXtSkGNM9su!!^DGy<817<&&I49ch%OS!ZL2naU2u&WY2pu*5WjE|1t!`~|5qht8+#{nM#EL=#( zL+<^@%t5J;%*y~wbRw>ROS^{7s!bylU=S1jO#Gf&&RA!d;4%}v(kelrXIaF=I>Us& zRl)>H=7cl+alnKC3;#P8lS#8IF(!g9J^&MGh?<1iWCnImg;s7$SW!EF=LEXaqjQ44 zRhqwZfeL?Q7?r8tqkp?W!aNs%2v- zNDErQt`y%?-1w?Yq!sLn8dTwQ8OS}_nDQa}IAHeEMtOdY9EnT40u23Re%fa1?^JR6 zbPuOb+id-<5~ZhYw*J^C&8XjXo@EeCy?xJYoEdZ2A`}ZU&+D=)5ZrA>si##5Xnj{q ze>*!Iz0_2&l`QN9#q1;t34v-xi@PkzfE15_@UXPF`-EjP`kQ zV|F?60Env-d~O%X1jhT!Jhb?!N~D@$r?I1@3c0Go%(Y z2f=iM96M`?3i)!*8r(!(nItUulbD|bs1n|xsFH~YCRxRKLn4A_lrppq&JkFfW*;TN z$iX8efiwb`ipdEWRj&Nee@yfC2v+byAs<1&8-ff5a)+FTl^ZeoC^hU&MzEti8IivoIk=>nHWLT8Fh~gOFh$hn(AQ!WFs95b z1D7CLT&LA!y`Ji<_@qkF5N`&ZJJ!Nol#8PSU~L^%;NX%yCIl{J5;^a;VpPq8KEb65SpS>vucH}9C`0WaOddeYg7U2`v(@G&pIdB=DRT5I0 z2+Vls7va=hHtIR5a$#dA1(-yALj}vY-%O!UAr{ z*LJ7Go80wKOq3CqS6NUPzg>aLt1Kvtn+06TM6lj$ILw1XKva})ar9#Ri5$z_p)hz= zgh4oZj}<2{pLVE$pbqipvfZOE2Cp^@UKKECcS;z9b*{kR)rP_N?FtNDZ5WK31q{kW zWc^>b5OI_{h%p9(gIK^|xO)o|EdrueJjE(7NbwbhK`WCBGq(Gju{|P3565{|gkF}z zdGXs7cyrE+n;G7G4&*zWABg0{>RwIgj%AE9zjupmNnygKR_}SLumNN|4mu+j*+Qzz z9#$l~O1kfgkR)`*wL2wlQ}oA)ZFY1;ND}66S77amkR;5Tpw08tC`2%|l&7Z$F;*w!x$<|b%mZW9UX|7fd9M8J3KVrho-1!=DB|Y^ z6+a<=Y7^GFt2|RRqv8b82`J?}*NjfYAD8o7GYY8+ojJY8+9(w0aN6=*Pq91~N};sA zf(IE`YK!Y;sN&Q-R~i+JF`1M<=*F)^c`h7-x#U~@4ZmO`UQ zc7T3b@I6tW6RIo(2W-}&pWo85A#B}}Ll3yo2^As{S`u8Nt=-`?^x7(hnm9*2eO|K& z8NoNWyvRV_!d)vNQb1X7t*{!9-kOhz0naFQTL>8PnK2nys2m~vIB&S$9Gmb8eBnSr zKK2=VDTIcmIvXk5SQ!#NV~0oSq*!KyI&)SC<75S^H|MknHv%qhjN^0eL6~W7LJ1fa z6S)bQ_+<^R5$tLzEUt$l>BxYEXJjyd1NW?AZ7VmGNk>ZLzy%x`tGFD3CDJok5XN~6 z`7o@C9WV^uMdU>ig_UNBrSK--MFq6-lr_ zeosw1wpyYfDaL-Bz^3p)fra~KKp9M(?& z3M=@~hsf)U00v1e1BSxiYQT8xI1iOkZ5JR$jfDaR_zHk=6DxIY!jVk6p%{@?+LA*j z`!88X1Wlz3(9|pn2E)wo@^ne^<9jaoq=2f`X=eczF*(7V1=uWR0bZNrPgC+=-QwwA zB64;rDap%{pcrJ7@KBh@8HhkJGYS_pWi%^QywSXwB5H0zQ`Ksm8+UTKR)d1$NFa?U z0U0vsd`fbn+|=UrjO2~@J&a1~(n3K6&*Bfx4PfCv71WkF?oXj`Z$Y99o5ixG7oT-g zGNBGCj3cX>AXRBh@nBgG4T#|9Uts_@&vBg&{0K#=rv;im26}1sn?@QO)W5EQ)dsBny57*)38=_&0Xknh^fX4K*+Onib zYayhEc>~Op7}RUcc4t{{2fvMFkWFkG?#{4o8in<+V-QzV+q1zeNK8F7BlqPz5Gl56 zGp0ecICm9JWZ;R;XGk-QA$9lGJu-mSJ$|u!ezbs+p{Gg>9LLV5f?WnIS@TxwEL^io zIoWE6o=|ng)io+R90T(B0I?L15hyH4!WiK|0?r#=tqq1>7-kSg$Wz#c9eU+ScrsPT zG_+Xga3oBN?Q^hf=Is(D+P4xDl!0L}OMSW~dt87QR5N%53%b<|MO}gg%xxGPKtjn~ zvYps9Gjq0(1(Zcc$l(X<&;r zF;I6vvg5lXB>Q6u6JCd#f$VmY4Ai($3BQIQJM99@fD0^`2RFiw02)9+2#~M_LXwz} zkmZ!Dc3O{OnV4dk9Ym4UOzR_5M655UXd1!s&7&bjX+0`}9|N|}VZg_B^7-3v>%;u< zYl!*N!oe_`0>e*Ms0DPekXac5-4h3O;$ea+JU~}#qB)Zm#_1Mr|1S=e7Bgi$e#1uC43R6^J=OmZkaXU>^98y43LxyPE;0fUiB=`YF;^8>XdRi ztGeHmGfgRu7c9yb?HHStEC9R{G7nf3Dqp7M9tDgs_PdaGp)~*iAka~uyC}c(3455f zW)!x*5)uK0fL{o)s7-+fcg4gQD|jev5N_5@t*8qgJXKj6id0Dr5InpFlM*`n$WSeW z2<5KCFDFX_FpJ3sl*&PNYBq!Ms2PD>p~TOoxxuCxd^8!rs6fvGc(+(lj6D_=Wad0( zmFtT>b2+oGn#g)sN^Uf(;c9Mz(<)m5Si5c1o|TFJlt3FXmLUYiF^&*s@Esu_TAPRR z4}lK*D6IM}%Dev6XPiXH8Dg)2()Q}K-Z>H}Sx7%~RnozcRd9~xA$PDF;-Ik(Yy!>^ z&XPxn#NTjcW~q3&i)SK3-V9Y2wwC})t?(-`eQu6N3lbX}K7yH$Z>!E?FT64JYEavn zan+QfBj>H*9k^z2o>=canPCrc=d+WUE>$!g+uEy=G?%p?W`fQtN;_A z-)ZE2Q@Cco6S=oAuwPW)(u^{Wf*D;0GvdInm2EFHqx{N?4~#8oHVOPvGtw6&N)Gy^ z+)j&>c<7&7YaID?7{c*YLnGfjO2b6(Fv2x4BOc{IoV38y>mo>{XxrI@xKP`MKaLCh z8UhzQD-)DcjsUw);us-83U-_;$JiG*A?ms(O-`A^@mJZReqKPoSzuF|bXPH4bBa*H zh*<}5DtA|`%dYluAqh+b1Y)nzk2;}1!ibGuLrf5dx1+I3EuPs&mF*HbD2`&9GU|=FkyaGDVb|% z)POEi=@&!{MQ|Q@b_Jx{hs4g^c;e=suL}gnuOSGIJR3j{GX>pnBj5oELQWS;nb?xR z86!;98PkJ%YzPW$IuSq1^d`j4OVjQ%!u`ed?wS0W&v)%R z9NbWPdo$Tv&OP!e^L}y7J4J7nUl*Rqp10%C3Gay~JI!Q=Uyuf$8Q(hwh{7QBl{-A! z7u&}9`&ZR%7II{dKEeBt<1Ml?iTlwc*i3eQDs)MY2>PC$x47Zh{T;jEJZNkNRlIE{ zBX=mzWJs>%H^BM$bdZmTBP(!?P08LMp`>KH)4Ty+Sp4>6egnkGK7RHkpLG0?LS_7P zxcg%w0q@TMF&Dz5qxQYYvv-3ogUFqzs!#^D>ff z9*9!nd*pb1sf&>Csl7|>0Mg}`q+@7IFruei%c2Nb3Qt)hG$tna)Otpxqj5bW0_a07 z(@^1xB8PE7R!Dm?msvh}1EvXnyZ9kIm#@bUq2tJA?&9#Ib8&G*bAwF~9guw>!(_<<0iQ6Kgpg5!O_p_bg^)P0>r)`=%Vo%fW zbikFS>dQ0ViR4k3FONGNV!j&Z4kBxF6B5Z2Ts*&0Cr)}YJitVI5HOk3nFW7NXAo(E z!Osv>w%{io!VkJa@WVsXPDo+(F1$*RP1jNQX%ua6M$TJliLLh!LnVvYV_v>4C|B4e3nH#AEeA@ndT%&~0!Mgb}q%6ahmQ zpj-3Ez)Bom2M7aW1Gb{vqY^`sC`mQ+@OuF3+Yk_ zW`m9UdG|Vjp6(L}D_!;(48__W3H~#%3to(~vRnlnJ+-`GcAe zo-Su+{-AmsebR4`EQ5))mc*l8+z7%@K*L_k9x$N6h|?z4m^6o!L=6t8-~eG@R=Y?J zs5r3tL{=CDc#PB0t@UZsNa%Darw{Ct3wl`iB)cPYG1H91n-EAcwOnFHdI2bu+8#kC zC>I*bwhWf{hzH1Y^E4bY)+qq7KpJN$nS&e_3P>+vMI7)^jc3d^@d~3;*h6Ly{2Qbw z*ML~)J^!!(4(!00*QAbe65d}3BB5Cz{nRPvDJ!f37-^0{_I@WqD#QYPs^Aw@$hRSG_vZgmg z9K!aYFIW^ox$p=q5Kr_d^GKh0$(MxiZke*BxmEQ5duVe5*#kUKSb#{-WK04NVd&}c z6cX~=f(lA{e42GAEP;V}rG`b~_GWw^Rbw4fv|3C+bwy`SACaSYod;yRX82Z6nbaez z>_b{;9k-WDF+>z-K+6`lZkivgD98V4Qk?1L7Brruj65&I6 z=rH4n7(=>=)+ze5#4^{uSqj7@5~m*~CiJ5N&(YMUg>CPTMN#3}lbxrB#iIA6Ns3MQ zf=8YM%g@51h*8prnm!gFV1QtDx6pZlYO<%Kp?p6z_YF}mQt;a?_d${%U?4BD@Jy4+ zP>57zQiZSq5>6jDBjSU8m*traC!r)ETq~bfc+oYOVnn+Z*=C2A3(2~aDag<$ z5Mu4f&=RFV$Y7ONJA?HISYVMI;WsRR;|vS~0fYnW3?Td(o-EY!a4aZ9;doBogU!kf7}JV{r!ZEoe6{g) zrkTNec(vqylc~_3Ba=IsraWO)T9(SGqQbFJB5T?(!xPiQf&$O-u0j=Mlic+4$PLPIb%lH(YHYRGgR ze0igwqzMTW#mHwW$tQO^*%ml+YlctvTAg2B;m{uh*HWV6n4IAkDcE5wNj*u59z0Un zh+7Zr;p0+pmvRcLJmn6Iejbqd4$FKpI%0-|y@I+i7PUSipMu~C&A<^bDF9OqBug?# zeKEL9SHS)xS_z&+6%xRriU#WvFj;j!`KDf1Fn;xb0~h`O1nqx020+W zz|9)Sqc!9<+F+S4L6Rp+(x1oHifi{^J)@DGzwafBJU#N-=kRi_p|?RIbh$z9>76bb zwX;{h0*%(D|2BVr$Nlm98|0J1p^pvEWvAt?r_23LXYYHV^!xGzp9c02hY_o~FxTHT}ZB-JkZ_e7QZEyHx#xiTuk0nWS`?aqjnAp+3L4Np*zCmXqe%^)I*a2oa|6wsRI6Q_t9R)4lrdM2va_}dzUH!y>lCK#hi^l zhe#z32Gjs_7_|XDu~F#0n!M?irMWk`dROh}w=n`fZ{B$y zv4Ux<9!~UcF4ItCA_w>@>Mx-nAO$N$iKhOTd_%sP$#c}_Q~kAK^|$-aL{*Ckf_lFd zTLE+RSC~FO^X@!4?ObDuQKwPaLUv|QAplL48o>MVr>Z~>G|BZUOwWp>^z89oDRqq} z3LI6??SWU*Hp)h z%8H}O_hLdn$mKiBnZ8=WA2qZpr|*56NMl>ykL@NIa9VjqALhd7YAO4=&M&vT?YIZ% zlbB~}EN}12GL^D!s}|Z=#6>8LxvN|M49vFySUHBzOFMBMe?Kh*b0@Kb18cAD9{waZ zwKvT+C;aiW7%EW>zbNjYDuSn>QF~%`0*Yw@L<-MMP0)3mZB5L!@jN?p0@4co8Kcj^ z$qvfHR`tXCK+OXe_Fax z4qtD;QR4tUw9+5JX3#iv#o9^7&PyE~CoqL8t^F#Kv%S5G`OT^6FT$z78t4Wy z@~wkmX0}a%tQ&2-FsIpR6{mu$4?4LsJf`^Lpkg?5+c*CBhHJ3%JYC*-gUsVhkx>$W zXBY&Ub8j-;QAJ}e1o+BCj*U1II0g7V2oJ1RSE4CQRdgk=hYtHRTU%1waY}dlNv-HWs8`r z#8#tOq_2rZQUepaQpYL+9u04z@R+erVcPJINPn`~5L1u+rk-glNbrkxyj{#*BioY` z#YkG|7j4hJC9Kfv7rjQ@Mt2B(01xsud3X~-i$XlHDG#0`o|wQKMVD&Kv+TgZsOf_P z4^dnL{>V-mhKKhH&(zExexZ`^bPsXUUvn|Qi07TAf+D&G5^cjEOW2CPA^@r-s#Ja6 zmx=EqDxCj5WPzXrgiG=uhehSoC|NLY*m%8l8w8{1&N9puxLkXwcRL!_kJkEa%^H1L ztxch69JX0qbDU$KA?iXD(gjhl54eLol!6@)t3d_#wD`6u*oka!u69fiohCsGji!Wu zzNj^+VZdaO@^&G~3PGnU!t^5rx7v|k6E?p>7M7@@M3c!VB$@muxpN5OXMtPQC-u&%th4QAH9-C%dO>@Ju0fyW+ne`3fy%l7R1CgY|dES=KNGc&b_(To zBM<_*gRV~g(=ruAI zmx!u$_ec(b9=$a#hu}xXq{=5p|3Nqe50Byy{MboyS2MWtQ2ic8ZO@MML>C47SZNd$ zThCg^cB@t(HL6TeIexBMT#LiXvPm*kHt4lrG9@vx7CJ_tj_qP_J_kES*2zj7qkV=J zS7k*ZxX6ytU9t{m;yCMyg<8KEQX*6{xvGN4)j2}Gp^A>NSRKtFwjSJQRExN5CHfEn zzko_~=Y>|Hi;Q?iUuAnVvO0B60mxjSl-ot;Q}LDD;-7Gf-|KnRSp4S*b{{bJW$4K~uis=c$6U7L)Z(J( z2rk73gj}V#%Y?LFDL^R%JMAbeieQh5v7VVvc4ET~=M)(&9?>gi&# z)u@M1XHdwMoma?bEBwZjw{M6svbtVbyiOp^?Sr`BmM)A}eb_Y~+VtR#dvIXYofSk+j$BKxyU6 zXw&&J+ANpRR10Y5@JIHja?VRzG#GZij-u|3&CXogpz;7*nsr%DZVzr*&>U*FWg#rq zOHfr|(W-eTK^1&SeMzpFAda>!w)l)y51llGb|+nszAeD>#_#_k$(ihcgJBPUvp_(wlHGq+42`99 zUTBC@UI0Z7`)a|^t0gb0#J$Ta;Jeqm?6q_Rt{18jad%b@;663dTed7wRQ>K>*Q|1_ zs1)H}<_i?r;-Bd9lCrsio=?g7HB&@Wc7m`7gzhCcn(tX`KZW3#%`cy#cxmQggTr?$ZH|@8C@9wiRbSc>rIoP4a-NKJFQE*&j z%;BU12mcRUH5s|99sOJbD6I4|^6KP>3ZXM_hQG_Lpgf{DL*=XCtZxP7fCL#-ZBL7r zIL<~x*-KhsNi*9L{bwl^`ON?y_zM+X~@p;E>e#XLemMHJ2!`&=PhfBOCu4_V#(=oz-$u2 zIBYH|xl^D<k^p5?~CsVA&Cc zt?jCHdV`d6I9`-{V=2-*71dZTRi$%*i{B2Y?gaLX zpA*6zVl7nRX&8v?g8a|`ts(}M6wBy44KVXSf+FkJz~}1flyPA}S1H)OH23mKtQ0mI3Y#g`3kPg7>QmEGu&3P4nuA^I=%xmN+|blXJ*RNW`^6#5b% zJ0FsixmCbAqKBw7qoawESS+O%n7T5e_q0L@=v@YMfrS*oj)aoAle!vMOyM)v&2;9{ zcZz@JIx=4M%l5;FYGGYU-CNi=9SIL*A2wY)OwGx$H|UB`f>b2qX*ql`QFu zlD*2bgwT#w+x<`HfozWpLP^>To28!8^o5DX-f_L{Vvi|ya-bmauqlf;tSsBpWmMLt z=|2>8zTY%jK^C2)nn072L3)J`=FP-$n3|E1cAq^cy6Hm3PKQ0-94dAi5N|?ads@84 zq;kY?^Lq)y&0ckOs)C6{S-}H~6qvg+a|stoMDys=C+M~=3j$zRSPCYO<|GnzZyOrw zV6bs8K-jg`TIlh)2YA_$1`ArsyzD;v$7IsbE(NpV@w=kLHGl3|jlcEdjqQ-Ah#~Qz z-;~$uhS-Ulc#jTaZSdArWWW(>Dey<6##i6-OU&Id&1!M7V;O24f@aO~1K zNb^$hC{1_q!+FNb<>(e$AZ(j;sKAGHsc@*H3VhkV%-#D@1wJfAY3nXLrQ)t+E;7Q1 z@z4(HgUW<6{I7w%MjL{003~8<>D4?+q>Kf4xR9cIi&(NokU5>9suAQDc8^#nxG8(B z8E4b*8luqO@`w&}QW8Gg!}#e^vzgq1O|-8fAw!55g}mrQo@FO{UM7mVZ`tw2ARDF( zsdApwa{FFPtiZk0sp`gcbn(Wp^lq=?g~)dbnRng%?fw8Tb!^0qvfH!0b(nf*zRj+n zDbDrIxyZe-awsHRBn1O6(|-+*{N zV7`goQIXb%zgw`@p)Ot7E60}8JbQyA2hvZ~_*=2%F50nJVj~-G@>#O#84P&v zy^KjrUOkA+bEYO9K<3%1;)sCQNSeLAun ztjl`8zH$yVS?~AMkoLr-MOtw6j(((7(^ewpzDh(yZsE~#n&CndbKi(_*q*(iat;%D zjoQ0pNYx$;RI*e!Sg593(sSMyLw?%%IOl{jNn7VLvb z$k7*STh3P?u2QKv&a-{K%ONs{<@CsfU2eDoF+_4luQ{fg6`+2G*<7aIp3%l)mHL$h zt#9?!KhvCrV|iCMS*mE0PTXKFY2np0eQKe^APQZON3Afou<#Xk)AVJ+%0jDtR(QzR zWQRTL_7HRsf z#1Vp|gSX$%3dk_DOy{DrIh;Vgs%G^7Okd@ZHM<{B$+opiK^YiK}X0FIU3$Y#dek4cwmj`bczK*r?>*HyYNQ ztSH2S*9jbLR;T+WXh0QGczh8Dkd52fr;Ts51(>CX^Vky~4%6u?m&YdiZMK;&#|4Ov zRB}NS0&E|Oeg7!3c5&W+*JtwsEJP(Bg&mo(x!}U9#6uIF*QBr~8LIOBM6N#%X$SfG z_FC*+|J(ZGdeXF5XZN5pLBS{>kceeJ9?gSvQ*XZ3`f#OdpxY~qb6B8nKUtfs>Jjg2 zlq#1vWyu23LJ%2FHApMe9AtOtSQpt9 ztRZ*6{jVwx!|9MvYVJe>4I0=NiKGMm+=72vw`@gOpZF=rLlCL_1J|geD(s;`$b61f zZiL1E?1W8BXMfVDT39CPiBF0yQU1ened9$A#WeDRbQ9a_v#GIAAFA7X@kkI>%?n6|w<6O=y{Ksa3i z!eqbBT&S0Fp;i!T-crDk?LtuK6Nj?wCs>h;G-Gs~%VBLgx-5lOo_G;m`y5s;3#@s| z(B)GE?H|xLgLB(tme6os=p@dpy28)2wj^k)1E#G4F{(PsN&Y?~-pUcT*9L~n4nmxw zz%g*t_3Hq{8Ik?9hf5P3@U~6V-v-*xY6k)BSo9nn?G;DHs%lLCCh`G8{!~N~PB=JI zq`SiVmsF~;+HrFO+*+2L{2`L0NWf~~68x%SSP*-9rFg&vTww`G(ie+EwKBWpp%AE0 z0;fJasR3skXkJvAhk{gHJ`OY&-Pah+CBL<1USmdc37iPc{~*EXJ*Zhd069Z@S-ctK zqlhV0qj}sp9JU_c=F`UmAgwwtF?EV^N&T==uUzC`A*_?oYkkf@g zEav3lT$AO7h7a0AE?8*zGSOt_2*`E<5BiueWC~H#bxHO=+XoUQlsn4Jk@`{HXfBw)4Q@*akQA@~i$o@eKGHQIB@yY%; zM1221V8chCcPYZ^vX+;Y zN56LOe1^R93U&0d;=s5$9}CDy!LN zFNTdYg%S^xFk7y#SSOoYmif#pcU3)mixXf_(oMHZg zg}W=y42}akD@XwDQ(tVk2|$x+kNi$(d^YrI=1Q{#OJ(&Wra+Wc&S$Q>%qhEbfO;B7 zzUWvfPIXsj*nE-CYkc{ll{0G5=;r7hC6WG|yj+WpI$S|@)N#TkcS^XUu1n!T4HnAG zgL8dXf%f6{^NZvS_jl<16biE6N4N2~-)Fb~W4_NL`dm%!@#`p|jNU?{0W-1k@AUQg z$wLDw-<72gmf|P|IEAeYj7RN!>EPeLz|dBixp|<}Bg@!}J<3LsV#M&msvd*+f4J0T zg1sQcE@d-FvC9`#cA3W5Z-wH%9Q#UpQ%2lrB?TJJRyB1Rj{WEM=S@L5`t;sf&nRTX zoX?!p65qR8^oQ9_Wx}5OFV_3%V^Opick30~xL?4T-`|?=hDH7=|9(=A674xhiDx9U zovNb3di^idrVzBZHMB~U6oy?MUqr; zsWL$YN$xR{KtB2~Zt$m_B>!uqlcMoLyTW++wh`yKor!OE%ukKko*k^%Td7(HCzUKZ zzGO2|%&sIf46D5*@@}eR)=%JTZqi=wOAw zrLfiscadYNgjjp7;F!aIJyI&pIc8KLzTfHX26`Anv%8AGF2sjQJq{(ruc+!V(BX*U zBFZWbVQ5}i+2s&ItV~crlH*2_5rw!n{xU!HqJ{deGE}IP4;Sk1k#_@*HjVub1$7InmDCNC1Zx_R% z@b*WGZ@YKnipth4aa=gg;VG?oTZq&^j3G}dcE%!~8P3HyQNx$HVlSpewI)NyEG0u7 z`Vy4Ae5Q!4NUZNw1u>4?^yz`~D&_nPZ)4b^^*Wu!I4s$@fwL%5$5Fo=OLp{PZP8LH zyAwK`k7GEkKKvyJwNKyVqnGo3Pf7EtW`c8bOM)|mw8Sg8yUf!qdql%3^w+C);klkn zq9`yuu1UPgR}!~MrQlT&p$Oza#bG%iF;T)-y4)S6_ZluPm<4`go)$v(N4`mC_5go| z*kNkO*7H z!e(Rt+-9A?MeEo_f%9~qoChggXZQ5bH64^XDTJ&+afP%+HUAvw8OOCJ@<0!I6u*Kz z&>O1xXN8j)bHPE87h^|cI6i!Bn;*;z{-dpXY=Q>Cx`#7V;6iDKdeI^`;=p>A2l7lV zoNT;!+tb2}J*ry@nsQkwGE<;@K?Rq!w{i7JSFaC5$0YeYXg)S&zh6zjd<}$!fT}v> zKr-#Q>Kq(=TL&xN`RqhqD;s8qs%%S*V$A+PAcRA#f;SAFlkhpFo>BrHUNzd{bvVtF z9~3x*Grv{SS{3MWE#I#9N$#(4!7N{O`PiZj>&{2uYH=pAdn&o1Sb@FQy3ki$F>}2} zILjC$x07`h*ne0#)_dqoHZ24jtp;0;$4Bj;ot!5ECrr+B+x_h2{rwQIDf^>JpeoN2 z$;+rca)P2?n;sW$*lrD3LM|u$Ib)gZ)|8ye(SCX~piWTV9kRyTv2ds#7Pe<^ti-~; zWfaG6hmL{jD}=f}v+Q~MS*!@NNTP{qjE*bJ%i__8AEkDr40lj6eagr0t(pzofxbYw zoxJz`nxhW_qa#9@M+MqJb;Y`Md-lgw1Bb}|RBg{v+Arhe+P>KHn<{%w|C@VB@mkQ4 zS|0$)@r+rBN*}Uv<>$@SLm!<;(%eQ?xYk1y5o%eFRY$)5#$_5ru0mx-*i?PfVzPhLU~Xp5gM{)30N zqPr(NyPIs?j4tt`v32tT-k<7D;j_+9cs2|Fr}U&douT`n^3iAcz%zCZtiqR^ldb&c z=I$zNAdv4s%^vRT>8?8$biV`GELf zwaeLL#enzefS6A7PSnr?&+PsfvTTH-S4`XztLwUMgb zsIxyTsMM!!#6@oUu?nggi#6VmIZRI^Ev!r6#6k3nl;ZFQd3+x zigQS%(rg!H@68ei?-!ZTS%xDQ>-2YY&Z6SLn7?k8hAo_t4D~7+Mh6<=5JrSuoJ{nk zn$k>R%w0bWGgA*nwiGCtomSA>6+5z=8G{y)8Dwv-(PZObmnG%%hPy7~XO~i74GcRH zOM!I_yNqMQ#NPh19D+H(P85TPIfkBBpsGtU7#R-jC6>SFO=p|6A2XaKnTir(C7G&0 zTQ8jI!c;8ysH;)&KwXP5ETR{AK*hF}ziTG6@-%7@rDZ6FL+d{lDE>P|azlM-;NsGN zVjMEE%nFiw)fv2SS-h22+q|O?X$`l2bwJ(;QHATa>`(Omax=B%Cl&74jAxW)i@TjTQcd22#aa5t49|-K};`v?<>@v1a_6maOvEBzt z+Y0B=2smc9xM(FuUw-_eB)!DKG_w&XsE~%) z=?@CQxT{o}+wGtzLLYo7J5)KauQVO7xrDyrm$zqsQTg%)gR`(g<9N;PIw;FVJL0K@ zGkC)CUukL>Kd$QVtgm-k8D>Bc4iogh-YVZVR;UVgIu-aq9DK3*2E$nKG%lNpLIU;LClsPL913F?=v{@ z%}HPSi3Z@(HWSvp+_6u|6!vgxb&x>N)R8L>6%TrFcVW$FsnpwmRgDi67k}sYZL8XgJMZnt!j9%k##}ApPxp^z)*n8OCO?rJ5 zQn0czIaieFINb3E2Ld}jcYHwD+TX&PL|wFC?}N+Wt`A)V?m9M*U`3_+_sU%-1_C=i z?&^){R6$h4bfyJ*-%z4gykV66FYb}YAFbVATTD~+HQKt()WNjnRlD&ZC;JSN9s8I@ zQ`c6xj&%d7*FoP{yqhD&?`EdG>br8r5A*>>VTe_49RQiu_N3{@V;8Ce7s}M!EJ85* z*@l;7Kc^9a36Qj+Fu)r4qK=<+w+4L+1v>by`%V1k#?4*qp$~z~&JTq^Cfbr;u;Q+6 zvv=>3r~*~278(f%+1b&%NZE%JzUefwwj}xscEUF7!jvysnCE-rg1|TD` zs-BRVrvE-Vj*zaeqUVTCt(|-M`c;)ew561)C>YwWIIot1rMzaj6hNVN{h)uIc?DAN z;c6-PcVVL0ex02;(mv^mQrGe^Egz}u`Uc0^p+diX&dYJkwX>6N7WT|h^{fTo2(dkT zxQ~ox=Rdr1h4E13eA2Hc#dwIBso?E0)D$@t5_#l9_nJO;8`VDe|4sbo#?71OChX(i zdAn@;+yvr}(%Ttg3Xe$nNpLqh%|fc;wgo-RRhbmo+dSHcE7JW7;X%i!dOTV=+v|d^ zD#ih>L5d<-EiR|VAui(pWa)@7#meM%G(aM`+NYzBE>|C|q|BFMn^F~)2UZl5;VdR; zuN&uDw%1_}wR>|daGW&)r?pb$=#u5>Hu#BWeZAXyYHn{HG^~b#w3-h#e@vzUJHd{S zdyBfbf3z+_A4$~5p%MG20oNHjd+x!K?%5LQp0j<-Ot#k*-3rw7$17=`g89@lC>?I@ zVV*wq_~`<-mg$v`S+9m95`#0#6@z1yD7j?B;Mi#VS0x6EYP3+1Z8?zsl2j=MJ4fuJ zW~?9vpHQjIO>pe9pYCUZ??1Y76Z|)oG^ZGhznDx7)L}YqNa(F&mDT|ib(fA;awd082;4fL6xixdN$!5CFyNj~sDKPN;HN7G zqzNDXSdG$d5loe;#vuh!dh#}@8YkWD z`wz@*TY#P&F00u7vrV5KVk^y%E4!WaUP_2>^+o(RaC7vS@*PM%cHBIyedi`@S-82U zhOPSJWqrmD+jcjIltcg;X&7$%fH^B(F%&IEL9N&5yb1SA;;|&}|Q&fAB$4WWibIag> z6BmX99x&m)U|X!m!2zdgG|;dd;P@UN2lOfjlhDmUd1H+&d-x&qX+?3u7P%b7i5QxV z+-Iv?$^N`CjCnDZi++zBxnNxmw~JcbpG1qBtj1|Ou6+4#Nqul0ZXTO+7jEB-Jdy1@ z5ehfVJu1UC#N@AG73&tuq@_@DtL{&WA8_#GA$D4=_NHXgec-BO=Nrf&r#9J1Fu zaWUZS4;S6fJ<2Mfm|(yHzP+9P%Un83i#ZBLF1`qrbb4PBgr`Rm-|H2&Gl~wXI5sZc z!?<5(S+1DJ-o?WYn?g}lhTz)7KeEhlRu2@Kd7HvEM-y=E2XGH&aePsJwAo}2y)bs7 z0sg(8ErTyQA&&(C``$vE9K#CfmW6(RJKOk-O`9x(fL~q_0gu-b@SXx?vN{6pDKzux ztdxK&--dk7>LfT{+3snBLDfGsD0(iqDy+)5)zE$m3>c)qIO7DUJLb(o|omy9Bd zX+bVlcZ<<%hE?69+x)HEq*esH-R5uP&!1hisHG6N+CRr>Mf^Cc&5M!FX=5bCBD`HD zQ{x~a%BJSkho33KdzOz8J5<$v$#v1LHGxRS%*(BfYt)O` z-$H@!sE2+@yeB2?l4uTro=;?!Yq>H^IH@a~5GLtxaxa1~)+iLBFDLyzTeTS>`r4Fz zO^6we&(ryp;Rt{|tV1j#q}r5yy=tV;^8+8P3)TjORGYHXl|84~HI(Ic>xQ9}L7IN7 znM{T0Rn-nykyTGg+p0f!4w`F5E+NPNPVr+wMqEh%=@pV+9kk zb(z5Ek^lWz4R(9Zx}y!VTkoN1Wd;BlK7aC8HtqT5SJzbjB1=};wJB#n=EZ#bXS)3a< zi=y}Dcv#K}^A~L+fKu6Ie7IfThEspZ{h`3iy;L|mK3>|T3Ion~7^db#oOtl$Z>2AM}qGvLj9#45{!f2?;VKg@$q{v%h(KiAE^0CKOlR=RWF5u z*F@d)FBFK*V9O5F&CvRprjL@F3v*Qx_&>6j9NPgII?)?cIEFZSYX#@Bxtm|$Q}-da zxN267dqQV6!U>b#6OJmm@o);l%!~ta!@~;bWI*ZaWw@Xa{q3McC0={pUR7wn25^!#SJTLRKp3}zQm-K@0lI`y)YxF$o zrvG7n|c8I0NAMz}MaFoa%C*6QFgT56ge!smoWY*^+#jMY<(%S=)6!!KQDl&FhMdiq7 z+FvfktXZKgq3M7gUlnR91|YeFrsJizheXq8J5`FQoqJ6itu(ds<4UPsX=&i2*6S#q z;Npk1;!5>uSUzy&xZL8%SVOBz(lYHE2<(MaGbYl#YR2faQU~~5 z%W#10G-vmCJV_fI;9g*r5i8C$(k+)4&+xur84~fr8j0}DVB?U8vjdsz5;DAtwllVz z4$j5*LP~_~%<5$_rELY183B9Wc#%?e90c4s5GP|I;6*bYiX0d6;li4o14LyUk;450 zF?}Jq&t`aO97C{jD2^0X;&P`zy`bS%(dKMkVAha{Kclq z3mNM)eO91kn4P|fKfbGtQ5 z=CJT=HDBS}gXCwLI57^p^O9$@x8Km{wtjbrfzb}{&1T)V+|_L@4e>@gaYJKpzgWqA zU$YJL+>Y97R7}!b6E<7dU9%;L&R(hTO(4OH!FZ`k)h@WUH5|&*bSRvk7bA2> zv&v2vCqJT{&L^)24@n(+Y=JkS;AybkkB#r(=3t=+cO`Qq5VYw7OyV$D_yC(=+b4&x z=rHJAyr(|EKYZbO3`$aQnM+r=|IM@o5IfgQ+4|5Dca z?a;6Ss}Ai9?yi=vYG}^)gJzc>fLA5kbw>#Y5msq`#VFA1=;t$>9)r*D%4%r-IT`mZ8y4#Cu%XWE z>8EUkzjBM0Gi#duAZaFdB-^hQsSd7BbP_GH6!I+F-8->v zisi&`tMRXV8xi;1?KQ0r!E6)-*p+_vU}36wXUX1iAc9w6lhhYN5yUnWvp%Wi{#zmD z294|;b7<1^+d@I1O_+FY!-)e|3dl0f=c>u;2MI`zdHNxI%merj_Ho zRzxYi(8Kt2F7Ryj{-c`BMWW5?E)LQz(rhl$Fc*o_{&CIbzatI$*voQ;)zB9SX|4tS zGYjFxR3J~TA#M1fLEg1XbR>9Fe(254hb5bCaXMTjEU0W#ljD0BvOTX52jp_(qr0${ zFp=~4gdM-4*KMZjo-n@)Pb$T2Bx%KAk(MMZb(`$L_O5R%hF}7q(Z@XEZ z$`zm7dh^ZczebxIe)cZLZ9i^3?}m+cElCJ>e(HHQTq$=K7tgJI-VM`tE%CwhjvFu` z+`#WE`5Wzce&THf8^g^PX(|?ldahq9z3*gU89ly4+870S>Y}q zDqJt5Hx1Pc?{!LDA^OAY@&Omp*V9euHr_a&06oQV;HehJ#f{z$lVXRMX?MpP%P$fU z6*r$)b@OL&Ghk$4aQgkD9}$i?I>pbjs8_qe6Y!o;hbv!jL8F5;HbkdJBc49>S;`kj={Pru?3i z-!1;e|H2l^UtP$~oroRx?APrJFFMODh4=uT@4-`r)`<06bl$Wz9K3UdFn}2qeY90R zLa7MSJHMLW$^Kg*OBarn@o8%igBkC`40TpIL!Fh(5R+=#SeVq(=L=wtJgMT*h!<{B zTr$iKV^%s7nbku0xF;sEYlRb$@AF&)>LB~$WX%q&5N3%_F9ytMkL24??D>9(kE!Ip zc#7NZ6sB%T^0`(iPbya7x<$!9KeFVHN8J7BuU|s~ut=OC1YEu_uncniTD^e#O8AHZ z?q3bZH0~XF8q3vFqfVn*q+K@w^ur^AzFciII_SpYfbz)5P%c+&M}~3;vHiG;?W>!t zDOj=C?l2QM$YAS0K;DU>O~q%O+?MCYveKAdJRA-zIXI>$d~1Zl75F^6M?xVC-{~R> ze?6cu5{3(p*HN96H2s4pCl@W?WG5?9%M!l8CznbDIp9NsuK3JTy@RBh6c&+v^iFZX zDXgogr#fK)QTT+HCD+7}!cuP?kf$yVkjh$vfP86$$#`w=^awx#Z-V4HyoEfb+WCp> zK^{_{RWA#tX&p#sE(A!b!v=x$|2jjgH1Enu3$Bd80%|^?iXgphTq6~~0yJAY@DE=g zQP+hV7)2zNGyduyU*LgJwD9*cFv=nN4m>_?s>AJH-LJSE-$-@H^pP$)-#Yt@Z;Ewf z^C^yRq&g+wBULUIAOBo=iQ8AMk?q*=1q;Q6@pO$Z*s#iF)03ibLOGHft;(Sv?l<&t z_hE+~`b#4WeXc_3yKT^tCb zb&c}bS`P^;Mfdn5tDLiPw!?!_r8dvFlY^?iT{)GS`pWbDpxN)1Vg=BAXB21_Yo!yo zd3X%aoE-(4rGC&nFa~J8I|?*A`ayGc4A6XU6liw#gJ$O#xcK{{K(nhKG`q)un{$Jp ziF0vB`ayGS47mBhD9{}32hD?HfadS2q1n*L&gVm$IV%TfLpAzOo@2{P;J0Td^S*nx zaUJ;b!0mkj#?5oMBzCkK(CqgB$YS|Uliy9JeeDgg9V0M;2V$+=O26(;!nBE;h zSdq{iCxjIwb1UPaYMMUx;=yAW3oz_-ocuk)@M4EyfcYQO<4VUk9aHDkj`f&2Um4^B z-X8FHfWvk{=RIKTl|5b=l$x=aPMN{ z7gjg2t1^@wcAo!nHY(mvvXveGVsRczNGUqK6>NU z`Bs)}CH(mB`lb$)%ryaOx0N;d1lvN8Y?CJo1eG_E1#i;sX~No)LX+v9Cal{iH0ks- z;gWEnNw=p7>!1ov4mWz*OqSa$%53pkKBuXkHof!aCszw&E%r`)RZpAVna}jJ>79Do z)24UsvpsDpCcnC;QN`@n^fr>|b8|K5Y^+&8*jl_oPD6|E_!m|;aYK#y_03&mM&;~N zZqkuV5(Z+YlxQTe1LI^s#<%b%T4>v;Fs> zv+JAZt^2)-xpQ{8&k(7Xf;s)!t4Ds6wjRuz9d!I%-&|B3LSRm?0U(dnmtyI<&Rso< z?HYjBs8D#@!b0f-$8T6mWqKk5g2NWKiA$t}y?QC;XQ_!WI;68R%a*oaHz@5-pPZeW)ZYlg+%zqx@&!>U? zi6hi#&ttZDk#J3PfmnlUvH%wl-<@>0z(9m6>EdLh&8*p9n1_xMxVkOd6=BCnZ5tgl zzz$ls(?4$G86Xm3TfmC{*PRfW|MO%z z`!5S?+RawdXr;W_&RQse$9GJn3pApS(!xhf<>AKW`mD)os0SJ13HYK0t^pDMLUVvV z7#1*03SCJas0|^=q)}lar@}-QsDKdLsep{WQvqnbourc?$>ZeOd8nkDjU}eKa9`Tp zsqEx#u|^I2oL-p22W#ghIbmTbfFpE(h+u~Ef|>ay(9)g80Dzasq23duK>s+Jh|=-l zXp%UZ6e%vCs!3D{Xmf4oD-25R7Bm{l+BwSFIm+5O%GwdiCJbc>sFZf6sEZq&zdH&6 zf}&N2!Y@zqGTn#<8|~4X7}j>a$JV?l4e+|$NM~}j`cISQ9RM@=$<{P>0D%jCvIQM- zCw8CQ*=^nV#?Cj`L;4e!$0DcJ~*uprqdTtQ#Ch*#$s+-xR&iu;T`%07zHTp8&@~v>%n{%PSp>NM@|)VoU~!5 z7@3{6(5ZI}MMJUCzC|^l!)dXLP!V{@&&81GssAQ7#aMFR+AMKG6>a3cwb@bAM($gioi%ObzO@lVR*WV0t8<{mKu@uO^2yq_&NsKtgR>zgzf2jTU^H<)45#qdt6*NcN#~K{kWIB; z5IAHYwytjQ2Ncf1hhF^-*j|`Qk#e}vw6lJfy)ZVxH~HGx-|YOt-II{d=Pw>^%uQrJ z-u4?8n!+UD6HLz~uzd^=Qdq#L--gvpej8td&Svp%E4%Esp-#GJ z1T#+q-ol)l+1jo1Q(2p4Gl4TSH8%=uo(x@j%qn;#yzm6oBjy)O=Not6ajDslfqsB@U*p$g%Se*!6;0HmBgcZOAWSGfp z`vMpP2dL2mPN42Td)q^wdV3=5ljhREmI;DWiVWID?Xa`6@|}e&dL1u;nZa+_9SieQ zW?camL>jnUF<6Z;ft7-Q5W=;$c3Za?#~_4ReQP(l#bg7Q9bV42M4R=fF&v9aF-*5& zCph{lXgqnPpz)}|x($qoEy(8|{rRm6*_Cu2aO2Ubt@J~2A@)ZcYU;~w@-)?$ZHD^v z6vQEbAN7CQi0Cird{Z5`Y;pQG;IpA4>zHYpnQfbEy6&8&(yi(L(RPyB*7FWMCAcy4 z0C5H?W0Q$3;tkQspWq#YjMNH`KKk=Fp+ES`0Avb7&q4Rit-^aaI#zDZ5T5yzgLY>O z(rmGtedL3Y&xMEd>a^#%Rm_m!qnH@FyNaMNZ;38fbteQlnwDyiskbpik+%_@@q{3~ znUN{lE#24mg!KRD>R&yFt03LzQ8X*PZeYko^_sp$=@bC{W!F>E! z4#cQU7|<&&LBw@SOt@>BVe+Z-)7KCHHkrO=j_ojsYebzRilRB-cyovvrn+lj5a|8Q zDoWT}N|3soDZxfG9`!yqrND1&?mM3^dQ@nVhTufveU{|uEPY|;Pq#)t<1at|% zx=mss%Zk$*H3TO;riAp&Z;>(Q$uF4ogt6xQ1d%P&;)4luneUw_G9W_`VKoiFm6Q=5 zwz@QSMHZYS3xZB_(@mH>j7Yv*B`i22EV#;Gs$)Tw;kjwfYD!sfnk>llI=Y$_+Dh;P3{a1gY9!HQC}st|a%ROa!mQIdvtsI;$_UKbBC{e9>^W@+pKrO?k<=BeluSdwwLCM*D~m1HnK;G7LlxvvPcZhsyXs z!*=?f7D6M%hhkv?*g|UcIk(aFHpx5^FCa#uib3`df0{V$g-TWlh&gID22XBhq=DQH zy6|)d+hOW>2%{`^0NjERVevQw^Z~h${^Fb{P;n>mTu3bHoERpDl3Or2f+Z~L zVUy!Bje&mQeL|N`$Q#}fc|~o&@Ll=42-GBPIsBVl=fE&XH>3tUk z<}m{NCl>`^;@*%f4xaq;3#);(W#ak&g8QEB>t-+hLGGwEN?yo37VNG>D8>8dQviSk zQ&AN+aQMZ=u^U!P2sivx-b7WcenZ-85*v96WDQ2(BYn$bDOEg8^rqE7${iTp#l=;K8NH_=b zGdjk<4TV+QTkyDDNwm8*%?|w-Q_q)||5*t@K6*LpbK0IfA6J4K@uv%au8TWzu>ltw^zkgBGtdZOxL(8OW5VEBdUL(JF_~@QrFeww zVG_l;dVQrmm(^uFf1F*5?Z@>-z1GG*h4_h)C;C|IyV_JRFCXwK5vn_tZ9la0H9S@zUDm(nfn-T8v{!@m={*w3_@hXM4DdpcERSa~ zL5{t&^SHP1!#ac2`7^bYUTY9NC?aanV7;-Vvwoy&UP|`aLPD#t_l2tYQnzCwfr|H z0)5gh7?&wpUA5GeST1A=nINO;K}n$jm|Z^AF`c!xWpDimfH1Y*QlfA{FJ^zPUf$ zw#gl&Cb>i1ZHOT5I;Ghez+&(4`tWBK4m|#J;O*kidgP+eI%gHQez@J9o8j&59PKfF zkkjyo%mo(&WJ>XCJ$}tFh(qcaGnMxbnl=(zJwORTg0Y<9IM(59nl=Q=wI<#Oe;u1wD z2q)KP+iB!Qd!XD1Ir8;PTjbMuTaxQ+SgK}jsgzB%8z`e$IOXavAgW%|Oqy`zn~`;3 zpHK0r6(?AY*64SYo+Wxx6eJqvd5wA2RiLiR-h4dpJW|;FF zZUqC?MdeKPp+9;)UTBnI`WGT5Cno0_ov#uKC4ww2lm=;ZUL^ge_f9lX#eYY}C~pog zbav63zM*y3d~(CguMnIYW)|`LJU+Uz78mmOSFX9Cx#Nv7Qf( z=KAJw{mBYk39MjF7qMoJqMCP08@!Kq(6k|c@drWW!}bzg7yNJOFy7vy?OA7kMt@3h zx~ui1)``&7AAEitdI%i(jGgT z(BTeihLXTV|A|DeLd-(J(|-5KjidR`gZa;W`cq@;?vq;Q>>7|A4?i1!@gB!dn2!Dc z4EO7^8y5falm8sk*Q@L~&7Vt7+Y|J4?_ueHnBSBC++~fECpTUjy|>5STm19`tDe+a zv?rvW|9o=ePkjp4HxFosobEUC1_%8v;^Hu3^B!ve!kx7S__^QjKDlwmUwd-nHF;8P9Y=NNdAs|*f4cWcZ6l1ZmC*0TPUHj)-U;JBgdwjqCWeri@$N9Q z$$s+L$!C)JEGv6vkmIoI#>US^F$y>!5{C$IjKC%sEMozl#DIYZh#-h<#NdDkCcF?E zL~uX^0Rn8i-`_b^-F^SOXBiVFnUUe$?ygf+r_R4RRduTB+b8FXxNfNouDDu2B4koihsjY7D5d$=5*0t(m^ ziUp-cHdY`w zufWo5{i!0fNd-x|EI;5e??PU{7cgT8unLNCGm(#G9tn!!3woxY4iAOTtl7d+y(w!> zBDYC)f2$5H*%9h^53az(AvSRpoVU^dXnj(+@ zVq4DiZYts)3rfayzpQzpC6UX?K(5$B_5uuyGy8}>n2{7atS_!|NjpB~E!+B6pHo!f zBL`$}ipJkF)*0*o6KzG%fGxQ>FShh=Ru^_tQrNpJo0&W=%j>n$7Rv#N5!j`Qfwp`c zW*UwOt7w>4tYf;uZ3AG-KfB|Z#BS@WL2Qj(pG*+h>78F~ou13l){glM7#UAza>Dvz z1x}IOiC{f7rc4f{dmAxXAKol@Vj;~XO@+R}kn$q8c9#9kHVQ$84$kVEQZHk!n+R-r zx6kSStobQ%xL6d`_Uju2h;~FObN`<@$!=091z1)f(!qiM3G4@Nnhb-tl`jRcV;qk2byw6Hs9zNf$F6GxsQ~1KIoFz{lY*ivOrhLL%=M3YQ;sMH@6;s4Vl zLT3Ti3RHm1&9X==rWf4b!00BU3juUF{6E`67jRqaM5>VqD9Rd4E zz+hnu?CVzK2-r_~X=bp!v`>weR=&k8sfugCUGs^NT5Gs8JoECtx>k8MjB~g@KD0)8 zHnwuO`~P+gI2(9HxW8Bf&PIC<_le_cz}e`{;r`B6cU$CZxAzatr7>=N?_)#dIeo8h z(yx9k=7F(Aulzenv~UcD|#9 zYE45kv8*}hJbYLU3twLH>aw3>lvIWnM@<=@TM8d&H}IMBKLtL&8*$xK<2n;gWfU21 z2A`WH77Ge_VeE2q;obY8BdRpI8n`6Y?D-x3{l~lR3U7FDIu7iepfA0~FiXg)-~SqKS(T6jlbJBUxQ2D*eWESFwM$E!M8_YQ_s@N#g&U1xVJ~P%%_%HjQTU@&rnO$ z#ePz)A11ub&UiI<-vb>Qd*Ot)$rn#QGAaFU8wvi5qL7F3(+rzRA-~JtuY_Hn5)l4R zXVfI0uEj(Q83HC-nuj~t;VPk?3B|Uh<#WJq&t`-28jVqmjF{U1#qBVy){nhkb>p68Qq{RJ>lF7rz@Uh(GmNAq6$o72bC z#`~H!M)nM5&ntGDXX`2=HTl(N&OZqPDu{_K{8@NsB;rywHqq-%Y?Wnmdr{qDSwC8r zwYw>6_jp;(v%OjP+LxVadlO8pB|j1yM7JV}Y;!Jch+N9yl1-M@4gbm1Wjc$mzhe9P z*{oCOAJg8E*5|H$e9_nNS5c7S}_cohzCT51ng?q*Xb^|fI- zX_O%_yKSjzqxcM;`0byTN*_)(VYPu(|I}2xldHw1Jz_ah(J=i#U^y%Z)0E+?3+A7U z1JFwURnimmFD?GsGv_Hh$;keOulp0vLbF_u1k+fS`Q_uzvS;`xtiNeQP^E~H?Ioc} zs^dRG2WzN}KKoBd`Bw)#ZX7u!0h&Mz2yT2lt(*$ql49r^i_xc8A#^Ph?AJj<=oFDg zoEiri%xO+S=;No@a^hrx_i)YTMD-m$hnP7I@pLs>ZTQFU5* zIFz_mYuL$=K=SWsflcoB*IRpKB)=*;sqs*XR=!O(IQ6rwG9m?Oj@j#zqCH;8!l%9x z4f0scWdu6f0396zvUnX@w3OE+Ex`sGhSv29UB@wJLitNN+JM)oaE~2wFg2ftH@=nj zC%j{ex6opy9BdAtPd!F%ePo)^Kdz4$?rtjIJy!XA%=r^0Vb7fJi;y6EY%dgdPZ~t! zN&S_&M|m#(pGFi01t-n1!sX)3kxpUM#^usjQJeZ1yKBSXln)y9*tLP9#p*IEmRt%w zZZ(%k!$u;g{-(t&Nydm%WRquow%%CFeu*X6`^RRym zXx3Ew$sK9R1H;Pw@^7@{rIxBWvnd>iQGQkO8yB){{z%4UIS>EUW}))1oGJ^ijInzo z>&PKfkeZfy_GseFx}Sv^eR*2v2AfK=$G8v{Se)zpp#e&bv<8BmTw_oz1!RYg2FcIv zuREcCvu&u3UWzIIG`%igw=V0>(0n%K!XD<(b_}{Tq7{#?cbrMO@~WM)7oY9e_7Sos z%hTe=b;BR6js2m*V|h?^DEoD)q(3wK@p}6>J^b-?_K}XIUAxh>&ph+n+QSe{60+qJ z>7q+tri;kK-I0rj5*M|Hf;}p>`k`G09*}1ewvyLA+e!kj1!l^uak6r4%Pe>7aal1_ z|I24)rlx1Qtl3Y^6BVVdYpDpYOYSE!H*DyWa-Zq8N`Yi>1_xfFuTJ^bE}$#cXTycp zOzf@Tgo~MhC8gP2)E&(3(R%B-AH-K3ICQ`9{VnaSo6b^?+0q|(tdjpS(;8LWXSK3} zYZ!2;yX^{xii_LY9%KYLn%9Gxqhqwz`hoPxya;zI*cqb9EDht;p=c^mlZZ1(W(8!aLr@=N-c-kQPVlo7p>1Jc`t<0paGY8dZZ z0NJv=yk4t}$WaV?dF=T8!!5zNyWIHk%gOa>{P=&k*#Be0EG?L@D4<<*(i&U*vGq59 zw}qJj(^(3K$bIt~DjfGO)j`wsIdjcPJ{5hkPN6WlH9ekxd`SpMGgSYm0SmOGwF#Iiiptmfk2_IQP{Qy0ScPbpamqma%MUj1F$>Y#{jbIws55Fz*BJy zAnUH)1RqK!xTX%-HW_+ z(_5*xBE22`S>Eu4&l-sAW94-@1Jy3pQbxHQWistf_i+l)o@$a zvwZs6d$-nIbJHvPXh(MVyJgjKtVNvF;WufEXjFV*B<;t=@f5jO(8EgeM=Qw7bTcmW z{N2s?_gjaR=5<&>UZ$^6Hg(v#=J(x>xM-^;SwUW%t^D@BoHZ7;s#j%2_6L07G?^?z z)V%L4ZovJh3*wJ#$9Q;`7WmB=mG3gMtx2!<+NysU*uzkMz`iP?S#s#6J+RB6e6L%1 z)_OF1p$Pgs{K0jUCgCZZT3y29bq~-X^a5X1$9WlF&2dt|)arZSvNO^ReGPZi&2Y)Rq1k)Jkl~5+p=NAcUo;iQhqXncwHq>gukKp^>FU{Gy_>whi-e59 zC_lS;mb%83ks4baWA8-r-?v8o#S^IiUdz7|5_ODBL;Iyp#g;i?M!|aKI3er%6=2%q zF2+47B3yg?6{Z1U*OyuoY{!v$S^p?oc~v)zV?#VN|zh0`9*- zD3POOTeoV^Sfk70-iX{VJEf`JaE)`ircb!@doH;C#nd^{=13Hp2z&YV$+Gh@E0M6F z7k(e|IUll1>}qp!r>}E-(8GtM^^1KDv{Fr6H-$e2MOR0F>=tP z4$A0!*!gWIZQV$>1b+3|Vz^`SKDO{4``+807!ACswHJDAEYzi7OP)urw9CFCymwOB z=}Oxnc^bkhFe$+S-QIfh!te_n#& zjiv)TG$M;=)40t^?5X>+SGd6#F6x@^L>XxW=){ZK*RsB+C)T*sj`uRB56P=D;8(VX zqYn-V>90)?((t_PsY^%%yLfvzI4s@IuQRsj%7tr2H1@qU#O8J^Yi#oclHNO1T4c+A zvM$ZZes3a_WBwmfk7Y$+&HVGQv6goA!#l2Zg}FMD!yNIMP5lYBQ06c?5?gXkDJmB7 z$m^rd=-Fg+dZ%Bl-mA(_|1JB?PB%vij#=-W3h%lT6bq@1`}^I%-CXy=7jOTuSF4<7 z;|=UNI z+nda8ziP;9#{AwEH`~`Xr?!E_wVS8!=+P(M@wuUa1ops_E^bB)?Ho8BW>doMZxWO4 zmMuJRgNAq9OlCG98jQFfz8hbYPKGb-bBp^wOFRFM#yi;US~;88(vJj7-Bj#;x^2^H z-BhGu-C4w;SF7k_E_Xk$q8ZOl!iF=1CYjd%S$O&AsM2E3?LT17bCY|`9``PiVII=K z#I5i__bzs3EpMUrF79i*i;<&97=Ry$JxRFd^>GfzYKjtxLow3tV?f5-kT^KG<)yCq zkB*90B$ROk?@7qi-Tq5t`Wjl8FB3ZMf${6M>VR4wy)eVRO{B)(bVsLl$$$4|L-$T- z<|gq3=W2$nF>^J0U-Gi0meFne-e#!B3HV{<>LIY&67Og%acZb}(NO^Uv0;uQ_PK3@ z>w)2iTmX8%k*G;WSPQ@%YYD*qG@fztJSvXIiJ;!E)+{RBNlp#vJEzj?tTQaVc85LZ z&QR0p0ekeEudihr0@qEuZLOxQq^6mew5=}uIB~%qaaR9yva>q*F8Kqi;)g`s6vf?9 z8NzQ|&C(6KBiMX+GB$IaaL`5KTJtxYxox3%y*m~4Or)3l1G+tVR~kxqy-XeW!zW(h zCZhM7O|Jmw+lDX{^g6;voRG|eM!3RR6|VC^{ZG^hv%^^RBiuVco*AaSHVNl?e1h|(R$+7O zlVB z-p8U<&pSblzBieMhTOxGUbXlpYDe4Qv-rK-0Q>xTB}?x{$xFVd<0-nVyJmrlU|z`G!K}OM z+pO-^v4U9uBwT`%o}aWm^j}bZRyFH#uet_RySc7}l%L7CLX7BjJK;_^X#v?v9YdGk z3UU%up+W$nq|m?AP*ld=b7~}M7>lXJ;%LPerPcwj)3vkmuY_ThFR*|-6hY8yQ0{Gk zdpTuo$?p_t(v?=ff0(SQ;cWlj>)kuktUMp$=$_8$^dn0h^2TNDUD_qmF3Q8M^6>r` zTK;;KDXv&ec3;ze9cfI66f!Uu2Q@W1l6pB1(pc)<08g>`GEl5!ldn8S*Y$ULEiQNg|BS^!cFemeHx8@&ri*i;HglZ|45stqCBQ#I~%e-j;oXYapIFs>3uQ*vDnh^ zW{b(-&?Vtu^oXGuHUAc}Vo|bCDKv~@0tSSqA>LWo`vuHG$R}sDqR@j*d7W5l$54hn z$^oqjtMagdaHW-T%7ilh_I{QAxbYP7-~9Wesj0S61!_jr!-IEu1$CGMz_&Xv^=elO zX9bM_Csfk+6gJ4a>47T+VpLuu?Iw0C4C+EsxQb|FmpCquC!sCe?_>c*;ZS`(#Ov}r zCt&c$Os6?PU^V@Aqhks@q@JqB1W59-$t6NEQYM+H0b+bpM-k5Vi5Wu_)Gd^IvUi>@ z`OtRh8wUA##R-$N0{Bsp)J5#psF}kgR!})dDY%*Iy`q=TGz41CE*fN>Qa4NwjoRc@ zr`3w{3WT)0N6m%ld2Pw!1=>X+V?qAwzPcBJ6yd?n#oUraM^HW}NaLz>59+4t8iN%ByR5Rhrt*E!O4#S2yh4na zb8KD0>Qx72`4!0;v7+VbFk@_KBw6_i)ocXkz~!vz8?uUR@neQ8JHfs|luag>$Jzu- zM(u12{cu5>&^6z{&)qVwVr%F6JSrdH@|X=G8Vs}W%GR=Tat|z44_~`+4}?PeJnSAI z5bhqt;7pDLO720vihGbJ_W%;HFC-e|-r0?KPM^x%a$a2(;UIK10=XKV4P$dE5G^+opd~(##$~L9y*h7ockcwi#BO zFN&Y?yEYMdl}ULz8Ikg21_ylf@=_`X@=Uv+Khj?-XP_&uL7pvZi&^_$$#JPCpL}xJ zDcHJ3#}NNz8R6-(bNsU~^*jF6UFa0qdGHrL&WATH6Uv z;fHN#_RWfB=f@gX0w&$hW>s?o5bCcA~jEMDeln`cK5LSvE zJaE{|j!Oo}MwbqnF6k-R`hhO>Bx!@)67`gH}Quxl!Npt^j?OSNm2_2p z#_U2S5`<4_h!Rho)tEleMWx-=D=NV4UEJ>Qa8d3`J!2Y>BSWphHnSz$!+kGPp|6q$ ztiu|u9ApfkQ#hgZOZ>!qest5@51>0F(usPgug$rJLaW<%BP?g;a(8roJN zGR2}}X$^5aG#g_eG(%gtbei8I{Rikh+Nr;0VP66Q{MCY0syhxuB-s#0qJ|x*m!mF)q=ISNdiW<1rYqV9=U<9-Vgs6cnTm#}RATW_@ zKO_SYjFv!n%tYq07$=mTR4RnRcm^4yAh( zI@GQ{TeEtWx7}!1^^j0I=cqml?dtJNpzJKi_KHrn|Chkb?~^t(L<)}HtwxJS*I1w# zqG;Sgv%AIOHs70UR4lCV`m!eNr?#zoQB~Y>85?3_w$yt3RS3c*EY%ce06c2Mm=1j; z^LoNE1s)9kVFitK(a6GQA>>IvI6^u{&C5_Vo${z1(a2C&tZKgFM0{N-nyLoQZYG+& zVE%DKtU$@_I#T)kQeXh}duGAB8NDZAN~W)xJZiN`P-)+!Ft90c>a$lkcsZM7mB&s;dUn1uuV|T_DFvF=--ngMFIkf7v&0ZH&a?cD zCMU`(_-Jx+*!G%d2NqTW^b5_fN>WfAy?t>y0t%-U(UvuAcQSvR)gr?w*i!_v%@{O4gk* z>(Yd*ORHzSkE~qGD~WjiIDK_A$}05z1{r_NGyckW#+B7GK0wCjdd3UKGctv?T8;OU z@qEu{DmE;;%d2M`oSi?_^PM$bVLg)}R#`9IH;`v$fZS;I}Afq}~&(V$6 zXVy$3wK~gZwF*>mgOd+89B~JF$Bw8%PWK+&I}rL2Ayz~ZDnoE4cb72 zI&AddOKq852Y~_DV}>Bj{AmF6-A{o-*c>Q04GWr+A--E=(+LRl$FK00c@om zM!T%97yjU5qGaBpB%t0a*!qO^li?d5Tf)fOBCGn8v%UKi#Z5T8L-Q2-pg!cR*rBj% z0$MT1XG=T&gC=rPPsn5JAIT7V#h+r~Uj-jGRyGg`z-zJ8-fcN^t!Ebfi+M)2!K^{2*#6(rdUZ9y!2**5*0}rN7)6jc6Q*un@oi@<@JK7D- z9GO56o9E1DoQa`wbj2DU{-sVBsUhsrQIo9;fygz>@qjf68M}~LyS6~QC4Uyx9AG)% zK_yn%X=2X#@}$8w9^If%&pJDQmaXRStI{~V#YzM4{1%{~0=06Lm6b=%UxZ@cH2!^C zZceZFT3G~9=0Ze)PN0n#ML`CkM*6b`MGLj!G<`c?*G~$yIMpXGLydxjnsq9U8h}DA z0Y=n7*ij?rC~6_=y)9=xugy|F&_VJuXYyk_r1@R3=U>U0^GlzR>mYsN6~1zEsAkU- zunvqNaApSm7|g<8+BfA_FijH}pqtX|Oi7qMCH@j_Gh>%LK}oVy%A(mC&2j;++BLK35qRx_EiQebxoPZ+Qt8`j#=|)3VnN&vAA%C35xb+@wKY zB6GqOzs~(%VyVl&kx*52F6ce66Rt3=8W`6)gX}p}o;~}t-aEQkZ;Y5}nrIgh9r>c_ zT>5~lrWw{$pAiubnTS9HW+Dd?Tw3$rPd;jDD24#!exZGHtx?QY>R>;M%jZY#Pi^fy zHyR$}3oRh^smOxZg}BTXi~jB0YBo$=iU)6t1=4{eW&rBBKbVtokU1HwOXdVA1e9_L z>SgM?VhC>LWUetM>z*^nPeYl^oL~$vEfN*3U_yl4oKRjgCq+dq-D;hglL#T*nl-$2 zPZIY@A;#5=%HUX?@?~O|gKBV_I6yt1R{6n0l_IdMQs$ti>2fkp1hq49(Op zihI_zV(n$@?Yt_e7^~cppPO#3g_D~F;eC7&J19(CrO_Tej0^=>Kh>DY!?`x`8sWUw zUpBlD4dj)sp3c?lDJa1Y3A1MWvO_PnTJiMMio#o=nvgI}XY{=pu_$a_>@8T00$q5f z+EOPA5lEJ`+9+$)p#AiO_F@Zdr|Kf61tE+T@VK#g#Av%Gka}beE&K5O3<8@K>X&AU zz4VwJU8k2vr!&Wx;unM?Uw;MQXKj~_E!@UJ)A+fHcju)9&ZKbobg7;tbU2sLK65Ui z1z4J;E`LX2$sSBcY`Bj9)K?=ky(hyI4+W{<8HO!#*5Tz=1BJ}rWle`e1g zF!+5hW-<&WluZh zruVkM?r5j%Y!|)KPI*8ZA5&>duWl7^@1EAn!S>6Zm$p*w_*m=ZK>Ouj`{hn8_ojLt z_+0Z+-fw*Qwo&p6_WYOj_m$#Q_)d%R-!|TT!yvD;=ZEd@r}af9h`9;ZKa9qEA9ABH zazq8 z^0lG@=rQ%KNp1`qcB371MKN)e&_evqU5G^p%7grJbs=>@4|ZB5rJOcls~k%T3v}4> zo7Uj0{FZ*p&)DCq?C)ny5pNV~<$LYR7fpO#YR{ju=TF%4ckJ(7_V<8)F-jb_zYp4% zhx8X7zSzEfKE8d<>ez4Jepi3B0Lq>g_dre+(=vH!|#-w((85I4vdPC8}&mm-ZQ6bNglf9+`w!gxi zg63c|vY#XF09k&@x>F6#GU?jd`8vI)o3dNZPg+j=DROo$e&ozWZ=Gc59%bwOD34q6 z3kkYYoqG(|miv0TBqWN#CiXrE=(>>x^_JxENJqJLQj+AiUD#v!dDU`iu$Qo3spYqQ zqOP;0^Fh5Ym=Hdt^I^UGOm;v&0j$o>m;F)x_($~kw9cQVFHh@yNRK@)vUlgSBBj#_ zrn~dn(~)FWz6XNf?k~>#JE&Ataoxh_lZq6`kmG;=^uC?{JVL!`kcT5P|9Q~8<(z^O z@)W_#`^6XWx(VK1Z*yI8E=Edt`1ihiFNb={aN{X-C)L1^imVo`11w!HJ7*Xf$G_}ZUdy`;>zjiWU^{OUjYn_K@n^SW@k+I1aIbv4z~ zO^uWv>)$JkLEu*m0Y@jH_&iWJ6j4~2fWj-@{jN{ma&+EtxP2H0)))+>r3MG0og)s- zx4rglxY~%>(rc`R;I_H*>?GHtEHptr4TnFD-tK?DYZ5hiOW4;Lo zN|<@7vfhzt^f``T_M=N#^bKx1fHzWp#MGC9;*py-s?c|948(j9N|m*cwJ zl)BsojkvO4mW8)Et}L3RQunt(Bd#|J^hU>ZZv%=fkKxLKSQg&vxUwjgO5NQCeV?C| zx>KN^iF9p1m)f9TcDh~);lR?7eIsu+ecpEFaGH5QeYoG707z5_AL&ciZmB zT5Y$O!{VlFumT7>v7+$^n%Qo&hUKQ z_4a&R&wKs(*i7%X%r+@nM@Ta{c$%Arl*^VQxbyzY@*e4;7-}=!A8vp3Zf^tLH3j{2 zOs7_#uZp!W?P6p({!Bap$h>(U zw`gg~CU5gajR~}%QKKwS%~~PH6ord#2vLfrCTA5kLMEG{usI*XMVJJ9q5S#{~CduF-yM9ZeDnewZm8+V_`e>%oB z82Zl7G2Oz%)VNM$uMe&+HFKbbM0BA&B(izj*}=Nhgif_iP3Tz@dYZ{vr;-T$vQYRw zlkJ+H2W^V4C60`~yqi{5B&PNWCTQDGjuYg2x6cq+O>42sOKt(WZ8tmrnQN`y7& z0+`!AG?iX)M-pd>YZ9if>tRY7rRiB{W|hzi+MwugLZcFcoP1*Q0BX-N)x3e>V#WR* zMr5Lro@j<40GDk6UDoU1Ku8DMTi^fNDuY?^vOm@iWay(P&e{byPyN zp??MJ&L!-1gPheiV(@PQ$Hqt@Jtu8>aHe-S%VuJ=Cgmu;h!_i!kczTtbyp&iYi1Lv zhfgl$2%e;zEfIZjTYDpB2SegajZw;H8YwptnUqh7SdwNY$di;$x21gAq+Bz|HX(-C z*kmsBH2s#kCPqreO@4YGEwXuQSuH6cV|>L*b;Zh+@E5{UwZkria&qYJ>3Pg-xQgOIpqk zMf9msza@BD@w&GMRMyA#%vZ!^VR;t%YPeQGNSvaP3*J1_U~9{aloZL*N~X$~=8l2h zzh;G{fE$wcg>@2rQ**Y|?0^HbV?>8FKTlqm18M<7&`FHs(g+ql#7hvj)JTzB6mg^M z<_-(M=Ecmm$Z44ogu9}P7Kb8T)>Sh;i2&)=VT;&~kUP7L9^e(}k#kuC_^@mwG6O=J zM2~!7M%z)~&~_60qQ`ti-VW67i?{u1eKkKskG#SVup5YcDw5?+ue4EctH5lgt#WEz zb-jJ-R_o0KYfW@Osk4J#twCb`fST)XGADe5+fcXsicQw=*dO#gkJ5X>tqYQ{m#l6I zXn^Y-wK0pezM3*nv%e#~2n9euNrYI)3UG;JQLM8DRK(bRq&DPo%QX*LLP`{?=Dkvm z1;ujpp{a17n5wI|0GhI2F3af)14`NnW;=SwRWdFxC^AnF5f6;hptLF^lh`&x#(~u zAKvc@=OSGDDtB#6ZI!HjV3rws=ju&HF62SZr4 zvllpG&J5efRes%`=wh)Y z)^LmML>s`?WMRg;R_&Eznw6HTRoX|l;Jys1Lbq_6JCIcCd&Imb*(h#w!DyH>l30;` zZCBo4PFwK){r2@w>=YTdw2l7jPEXTGtDM=3LjD_cvfP>G&L(C^_7;&ti(`NRLC95~ zdeOCcJqCrwD)l0?IF$Ax>yDGAHmt`0pzS*b^GsdIvdk}RK&t1e^}eu^cTgU{*Rzwz za&1t1H=uG7d2>3~Rr41yF}bk8sw;L3)~ng`)p{8X6jKFTUMm;%q>sm|Qtc55th3s& z-b!6y6W)fP9fc|LLP;T4{Cc&{eYiQwDXTf)DHZg2+CX9ON9C@kA1D88^S(*%wo2>i zoAq9%^w=y}yg^?GsK5nw@b$tyOD^ZMOB*BEH)-2`XR!J7ct{#N>6J$%Z7#uyMe_}d z40R9`i^{|zC;gns2&BXos~416_D=zcNnfd)e9pY)YgLM(FomYTJf?JE9@wZ8$57AJ z%!|#7Je)OQRVz1CJ!2kb%9tlV9;!#?^~AglRBQz|%##wdm}gor-D2K`1?(G}AjQ0x z*^D5}o2NipDCYHR<}ncPSelx163UvBaBjBENjNv#aB@r_RhqU#mf>LJoLn!QH1VqZ zy4gzEwZ1&+KD)-HxfN&lW8R)QKO;?j_WX>l+ss1oGg+zJpd+sx4P^FHJ1cF!tGxH{ zq#cp!mvJso`8h!-A!dpYldE*;?^JwZbZKx6ulK z2;rD4n%HD+t+vVB2%}h_MpiNbLx_WCP4C!=Hw?R5teF?@0`^mU_?Ucq*AY| zqz$31$+bJNN%nEPzsgRq=cf~Gdj1n}7UU|hVIVmR=QAq_3#TFr8Ea^tA|9$l#D3_y z!?83eK^I=$;<{6W<=B_^-Z0Yy;|_ZqVh-VwL;eef3*GNRr@$bkp}Rj}5^%=|nr0JN zlcsN*22<-dbn+RtcF%Gz#oSz0Xt-Z&?QE2m$z2r5vUr+!Hk@MUyA-7aU+=_$&UE-owV=P_uN`0PLpuwiEV-Ei3)d%NgE}*kqDDU zaYHSbfVT4CT!$|CB932Cg3j{D1z3=tyU(0CqND#C{0AlyZ>>%+fek8$n5@Y;lBK;D8kmb z`~SdunU+O;)4?4RT28yAy^C$1x9ax()v%)Dx=YcSQjwxFZ6f>JtrZ=T&=0z*L*Q<$ z>%tLVxc5m7GNfsXKGY&I(< z-+ER%vw=Lg!OD#(UDf!!o*&nzl6W|rUoRh0qx4)sz#iD~A)_RdQdXa}(FY?gV3n<%_R`9F5HbK(XioB&2CIfjR z15xTt2FTyHINIJr!bt*-FqyRSxEaMYoiXhaqmJ6_DLn%H!%=raEQh()o3-N_3297O z1tfFMF%u$CeodKL<^t=O)N(V>;B#Cvj?8H>bB*QX!_nzfRSiicme4X^K%@1ke6k8z zhdUNM1#blj$Lt6juS;ti$ESPGx324lSm9q}+y;rsdcH!{KxN-FbGG~*;{IO+>)1t* znpRg7&8-KSC{w?K+Tp`YW9%Px+f&$RjHVam-`I$$2tDrF%vk%}WYbB$jv_lM{;@is zX{&vtB$Nl=qgtX7 z&FQ!gX@^scLuiL6rdH8lWnl^sdpa<)Md#@@n!|iL<)^eX>ma~wrq`%Afj~V;H#~?c zPMxO2Y9Ip$x;EoGrB9n3SDg~O8M{p5mS#+xmRQ`8q#}??#E2$g>W+{Yt10y4*Va@v zqHUrkcwqwpLvGQFPzNU5!24DkwwN*qRpRdMgC1IB<(@ORmng=k~rACy`Obt&`8fHIp{JLSj7{}3sTE?siCXT`| z@&zbmZ1`f?05HHBb+i&>p00ZQzpA?xv2uqkeUrslQDEJmyS^wo8U8>Kp3a^gIflsb zyQ8((l0O~k67sYe|J7*3$}#gNR!t||>d|Yp_m9?)MSUJ`qL`n0z8`f}<(QjB4H8`2u6rLM z-Hwzow|!`|s_{8>ZwfEk5!R_fUY<%#o$^g>a#2PMq`W;FX?rAy8t-C9Rli3}c+F%09PNW;i^joAR)g-fa7tox^PH0$>n{tG zqmnF{LbXy-T3kCS)JlTc#?^drsB@tWlD)R&^C~egtPE*UsD5Xn!0Z0KFI>GurH#Cp zeuNtz?V#Q!*>;O4_18IseKXyvZ*T(JL&z9e&Oz2)ABT0*z|+i=S=UY2}wXq z7a0E2eq!O7I71}F$H9!B_{I@ZhNwPnmT7&vI50q5w{_wg3f>uWhB`K|MFC+zhiGL5 zdYRcbc`wV%;RvK~5#$VDwB7n*hHX0UuT@^IcZU=-(Yg^5?XbBo8(&oT2 zEPQMA|6VPX#QwkhJvGhSe=hB}V2&utaznMUo|SJDki9`t-ru5kquQDIv$kFFZzcL$ zJC6?Yog=qsb*=31r;q%QQ`s3 zOQ}YVGu7Od;txfeV?b&!1Cv0e{&AL^2~F45hXo>sJaEIiGI}&RgP+MZlG&e5f%ct8M2+Z~5{Lz*;`CFELcR7V(kY5I`G7Dosc~y8 zoBSRD)*1xgHPG4GdA;>zkeRZ~O8{PdRqZ9n+kxoBd|bchB}+;f*-@n_<8r|bko8`1 zZqPy^)#^X3x(ocC&pXns!cE?Od<}qKNP5BOR(O zqiBBJH1jJsm~<%J7kEFLZGVnBQR0LkAg&Qp=d+h+t2fkReNtV|4!HF_X*y8^v8w0N zMO@&qk~Nuqt9wtKNDVfSrXeJ@(_N6h(`#18xig>hRNRMT&E;%iSPTyy8i$S-ym)Yk z4&4mS?@TSwoKfv(Pd>N3KOH-csL|2lnTgw4(aXx0s1c_!`NWB@9LGSJ9BRiaTZ5Ux zq8?)pA$(8koW?{NN96%ruj_^B%OB zIi13$1Z*%bL#L3`=0B4c9pgL8+_tU%cC(H`l9=#ZmLs>ZeSIIb) zvbvhb#7D4IUke@*yvGPsoXnz`&g6Dlg;#rsjlz?Ti~f2_i~h{( zoLi|_ynu7agy0NpVmzG3tplx^rfhPPll>L-Ag#%ixY3vDtpu~~Q(@wAeFV@ClK8+X z%k~BZcR!U)n$<$R#tjj2!`C>8-toz4`Y6qJJynx%wAJPpc%>7xZP-3{8u9SS%De0joAx@E|6(Y%%@e=uWd zJ#@T}W8baR+YH7sSlSypxHKKE)BQs6;8wKwKEaVKFBT;c+O>OpYP)9FBtXZe6G7) z-8vOQQ;?Arwm@gH*jw*?#S|{aZ*rs8Z_0uR%!;M|)6r5*{o+hoH=sD}cEAXPP1*qi zBcF3xc%E&BK_s&a2A%DMm;Gmn409A(^^$bT+sB1Ml9-TW#`nR8AAWdd2L`f#F&P+O zpj0Lf51qtFDdVpKf98rs&x)4N`)3~k2cBaCCpU)&<2MNH?h9;*d! zRLm)AHY==Dw3G)#Z(}|)R;cQnbR{#Xon|)G)|uryXX08bRg2T$$83n>cdd@tYvcE* z3=hVqfd5n?Nve%cCmJ8zBAMaZ_;f-CSi#Sg@ zMq*P43NsRS5-Y_>$UjbEDuuu%f4(1zo_3cx(K4GbAf5(mRsdiNV8lW^f;LOLO!Q;8 z9!JfqP>Pi2VN#uZ zLeiGGFiS!TQ40wNJnn9Z4U(GB zS88M_gEdr5T~U=y;DNdyBkaJ&P<7q3r6#m-uuTeKR%6p3I0-Ard=cR-O}Be|sN1zS zb-Q`E@Ay!+drWZH)&~jvLtU#JZ4wjBh~}~ztb@`Z>oD1y@N11@RBGDJ!A84&?W@H)8ItR(`5V-Ai{1k|r0_6xeN(aX1b?Qj{@W@X?= zYG|*C81iLI=vt*b7ng=_wdAg-vkX)Nu^;(^>pHPPR+LB|SwZKmNi<^vel;gl7%y4D zH9E>#Q;3lVQH61ZOR=mQQmj6#kzx~Lm>=neu{U9d7n)t9qTYMNXm8?(@Sv;4L-l6y zD6m`uBUxgE#~Ni>Muo>qGg<)UNA4v_R%S)ob_i<(#I04I^$H&2Lb=vI)5?fjtPj&Q)a4emnPOs>`}mG4)7>_9i*)Jz zliKaveE_{nZs&t`Op>{tu3MJc>z&NmMOwoN%=PY3hRb_z$#~NM-roIjuaf-nrsi>f z^LTsnxZFG*Y#t9akB6JbmFDqC^LVs*JnoP3m6tvw9Cq1XoP_+rUZ?kPbc^Er4}nHV zKzOb08NWkYt zpayeWzDujSr^<^!z<9sg4vA=ofc7@Bf!!!?GElx$BGUVXPH^TM-~A($LUN)^oLN{V zj?y?1xkOqNk|bW|6i1cTJC~MN4JHlk!gl{D=@gMTe`c}EznHKHHJ1+)jffh=Vbxk# zo>ScJ8C|Y9sza~6o%CZbatQIi5qe9$e2|?}?Ef%;0TQW2R>*G;9Rv8N+ z_T+6pVjnwN9f<|dmz`N0*UJFts`GD8JI7ypXCoDPEf>-IyHTh4Ahl73b?}p{O=`}w zdc8MiS@xooZ)@lO_8qYAIpT6{x8K^-Vk+Xq3SLwtru>8aoZ=TLpV`EHDL@I4R5SL7 zdY6Z}@=C32sRK%?hES9L8qxgh{CU0dFXe;w-n+h=T~QF8k^N>A%M}7N=964%!hD~& z37zrMZ_;D=P32tRZWJ?+9KLgVgjl~VznZ;Tps`yrgIw+Rl=5L^!I}cRY-KD7j|EU> zh<6gZm^QPC{Gpq(hdz>VLgUd`p6oq2R{T|3vQIPNY{Dz`{cr@+h_X9e!oip{8#Y|5 zd`r3n6u(f}jwo%2uYxeHa@W@wW9Ng844T(TK}qVX`7;a7wQSU9Ppppb7qUgI=EFI~ z-k6e+qvFqn5M{~5k}nH{I?00Uijv4iEYf#dx~A%+cLmGk;~!$-;5yEZboQb6TS7 zRVSIf)Z(c6OZn#9mierTKa)_Ict2uy5kp_Cr|roQaf+-x%ArYp2yD7Z0^sbw-9cfl zbO3*+z&X-BFB*cpHYDJMz+D3xN;f(~q7GUDg!KaQkwDz?Tl!%AFF|u=4}b$lm3z=D z=73Excd(u!>{HH!zXfYJ*h&IBE---NhrnT^#UV>HL1zQz$q)VSMJIdcZVA7qP!UkK znV&dlnAXa6~;-6DkaUBjQw1(Fjh&CIetDb=g9j}Rc5 z2`v)YCJ^P>l3!zJiU;;2LSbvY*?Qcg^k0Qa}FWi3P zW6X0<8fzjoJLHpapB3G=YCWeo%ipXi=M?9LFMbH0$#S`urP=!DF_AaV1=c?QG9L)_ z%&XapG#Hol<2l0df9kZh{seR4h#ThK^}JL8v{=s&ELEHGImeft2vpMSy?hS zmt8*K9;xFJCoq_@=qK;}>>C*1HmI-#%Y9t+v*^ZGa~~IGqu*ie+^u3bm4nq<`5bd~ z$HCI)y36%$deEY(?~ad0RGpn4)Dr1?<&hCP!*ezFjC^@6d{Sq$lClilZ8TDK#(Pfs z&HZ!XhA&7+*|d{DHDz4r9xXzFE)(W-I+C0P{L9#JEi|psWENs};S(xMh>u3wbm>C}E2xw(@t5@E#w7^BR+*@|(LRR&{((%s43p&te>T)LR znXJEjfxsle8>I(REFkO6i1@B*s-=B5JUFAxAQX1d!bw%pN?ACW(FYMw#?Yf8|7DlA zlOI=g+pmgg;=}=G|2XvH!6)@NgHxH_ys_#PK1c4{;BDE19JI+f_lPg#~(P9)eD?>A%c*_-< zNY7*u4ZKI}gHB7yu$GW`lLmO3swe2@32Z{=r>st)=Nz2k4$&Tf%F7oNE7iol_efNa~ymzCLY-4`A4l>{DMd^caxgh1PIe=Zcf!Y11A zgc%RJNWcyli-)Y0Ry`3A2PgH!Ml1bHgWY}tNa*?`2z+XZ?sWN*bi09cpXd+_19G9B>LyR{H^4I~RJ$ zj%FFQC>%!(hs(6ad*Bt>+Og&!F^5MI1{=>S_J{$>3*sBA-k%H}e}m)99K`O3^R=_# z_(vRPAd^)LD>KReI69$VwQz}YWphT7om$Ec88=p~8dr$JRE{HKIgSuu8*w0`kg%o9SgISL$J%S6zc|uQV!09PsUP~ zhf6V&J_NfzmSTO~P|EEyVaYrn#4nYSN1IVIeiaJsO)VUw-Ayy$@Sl4N_oh-2nQCUJ z?mgtMW`{oQo(WgQM(s`+oiyVf;8LvK`m>=@cFly(M~z-;N~t!U-?4wcwD^Ye3fppa zYWoX;$-g7UQs2?(By{SsCtJyt>G1a09k0~jo$BOvk%!Ux>T&Haho-~5G1sA#tD*PZ znNQn%`xW4ktWT|ul?fllxon8hN(~TUN0{>4xjDtZS)>L@y zz1}`nLu;i{uP5Q<0M)7RRy&-t6Am>1)jGyEQ{i_$>sgnZ6jg8b9M5Med^MK6zYP$L zKYhwn_>UO$_W}342>&&fuzMK5oCC%lMR;dKa%mXAoM5JS*^L_kj&kO4O^4_!;ahMo)n~jF zE5iVXycLJ?aB~DWGz@Uq0hU>vj8!ZT1FS?kF|k2mZerA;~UOxz9lNC&TWp(tsZw?vBCkriQlc1lg}#-W#RW@ zRXUZ~@+4!mCATXc7_C&ff`qYI?nocVc*GxA&cdz9?xf5D^4Y_on@v9!;dDr|Bi5^( zGAnDZ${hBTZpy-^BW^mdIc0MX&elC}NyfA7;Uw*-DLTA4WizJ^7tm^38qc;X3wK4e z)3v`!j*Wt zCyw`4N?i8D@$N~92R(7TKO#}S#8LSYjkj=oD*Qg3 z>WJM^Z-16+R;^hq%^a?>HCIl<_NCXf!p!>ex(@1&CNfH~1yE@}V>`{U#U;-{q2(2s z0}|K(uY~;aXivt#;_ZqF`hR(B2>s`m?yFj9>Ew`V*C*77Vq^5Ue`AyYd*Z6iEOo zA_()j)&h}axf5RgrK{@@Xe;UDN-H&}RRRP<{aUg=8Un(bYnhDPS_iQw2`;TU$*4(k-zA))I2=KN_!Pyy7{=}dokNar zdU)rNx&aIwyv~hC4^@&4S?1h?Y|>m~&h&*!BS^;%J+-}woCAH`K?-DCGO{P@zd+3v z^~Bv+iQ&Ya!A+Eq5a+Z$rWx9dv${BE6v9~~LTZZIZrc=uiY-?lrYH4!clJ1UUa;{D zhJ4Y_imG>}n&c3zgZQ9aJan~6h}H}&_QR%o)2W!OuV~_Qft3fHz)>s;&*A?hq^PtG zQDXzgY|+iNgQLgp2F`4GEt?U3ZeF)w+9Ra3hLVNjew1&nIoD+_9sHtQnRD7lA>3@+ zp?$EUSc!HjZ`PEYDS(2=*t|kp_@7oK0QZ;Xu*UR3fusr(TBk-dNDpShf);US412C} z%BQCK+H6^4uaL=Au%B`4wcR4&nhEh4Z^{MpKMy29jvqEWj~|Y{L>JRZ|eCuzJS)pH_iCDl;i|)(;6#h-F7?m&Q2^}VB@Ya z5{B3ZoLL}kYn|3|x3jZujwN{RV`b8?&_r*cWijq#t=K6+U%>P_Y4E_qye#BZ+wWvo z*lDJd(p8Ra@Jq7-zvxqVQ(^AeT2Z`U2MY(&&%VS=k&6=%4ljhT5C$T$2czJDSbL1_ ztoAs~h8Iyc+y9vToR*sK8GS-33B1?lrn#`dw$6&f(v(LBv9J(8K%k=o4|PuGCeE+q z2SM$@E0l%_Y1^A=Cl1IU60uj%#OaGj?-3_V`8t{$v`h&pS-TvM>Y7RFvV-EKm)WJ; zw|213x=Fo4bF?7hJC-EdG)y$aU1oE(mKrSjTa`(p7*LpiQ3v4;e)a*-UiX~UEjeV3 zX|AbT=alhrV%-3yx^>>ak%PKtR5uJ#jXH_e>#iv%$`I7tm>$I7VV!>0Iy7`PY!pRw zZfI93BB|6njP7Ui_lIAkBUXF8 zD+{|8jQX?i)B68&xXV0jSG@0)$Jrc?GMj*Z4j> z!7^L*?bqU7vCdlQJ#O$R9~zI9sIuO* znZ>1=<%3sRj!oNb?HfkbryNb93SD+!I~E%_c5}%+!}K_8wB=fvBvcI+;l=u%aoOY* zUGf70X~VPcZj+|gl zYljHW*g>s$>X!U4<~LGac=&%x+l0yFK-Qw$?dJTy%N{`O6D1|0!*Q%IK4NAkWst_1 zCyWSn>Ln*l2)IvB4oK@-1%$|2754l2@f@vV(%L@AzV|kw9*L+{*7MQ3#CNEf+i8E+ zCCK*r!E;zZfO+S%?;Qg&VT^U)pd19=ptN={IY^1lHsyI8O)-^asE_DW<^)e+5}^95 zRoN&j$P#+5pJmuVapDc^t`F1W@RD@MWVdm;x_+3RBR;9q*S;GQ3Geh}AO};{=^IWQ z+@V(1XEvG+v^#y&T>Ctm^E14hDL+jl%A8JZw!X#>{D_@C?K0}AOTd6)xv-BkOFf(9 zl=N{YWfH!A#-w%yW0bXBE8&Y;N(P4Ur3)Izmop|UDBpAh?*fx4v>pLpaD+fkTphlE z2-RnFLbvl96OkcOg*q2ZA-Q;HWWnD}q{P%lq(qB~4 zQw#)mG)0g1!pg2aVOBzp$qwtHvfx)~+xZ3ZQ)EoBbbT{{2~-83su$rDhX648weF&3bK~UlCxKVTva+wkeB^#pYG@f&sjbZAq+RcWn=?pOmu{$U9UNpnL;r7dk zVe@hQLiK#ICV=6-sx1r#%lbTKl8YZYgB)N0r!iMwQ+;qd1R-Lzj_& z9cTbT=8~!|ZG~0$OhVtrCIikv>W8JBbT&d!9?*V;#nWxls2rEm#%tl&!>?HC*tmh- zlUs~r#B?=<%qv~F_{o@6#Zt-4MR>Ce#C#^Nuw)}$KUU3zntUyN6iyevESB#U}!lE8^S_;5}`g$Gh3O`G478R;M_i7{O6;63!gKBDs2D9e;(#M2X-ZSLK;Pll0yFvS9 znkmrE>2bfv0-_+I-(+)SQY6OK=7`$fB^SonZjXa?f#C*L$t=y(`>e&zpezSpmq{S>+*!yiA94>&gFmf?>duW|ZXc8PY>fzjI>1P#u_>Ps%ErY^a}Qr@nVe9?Cy zMrE$|5a{TWZm)cuLU~hLw&VxFT5@)st}bae@`xGfXp0-tJQzI;9EQI`a%Qq_pW6Kvs?^n%7?mpAk@{cX= zdV2x4Ke5*`zA{&Kt9{s5e}H0B<$n9PdFZ2*4XXvV}PYYwXlgt?Z z@O1eW1L!?z9KwnyZ}#*FtxAcFf{FRl*}m!TdD9{ONBmZ`DRFxqmq0QrRE1CiC7eZ!xq0V-46* z={*k6TQr$^czRo>e23$$Z{=0$VAeV%bq$h=lj-3d%veu6HBe~Tgnft zk@l+1{*N|3h3z+KREPyG79}4T=6o@?$BpuF zBr^I#-`Cn;8pjg)_*?V~9qSuxc+nli60s6Y<-WrQ@3JkvsN%~WT4*}Cr)sF9i1o4d zSa$~M(DF8F)@LwaAP&=8Zem~d9ef_cKg!ku^=*Fr%jh>3P^Z-==Va)GdKLbLSdT%d_SUO8T$ zg2B}7= zi8`hQ+MpiIJ~*^XlM%@d-Ig?Yit%kQW%;xdp6uZ4r-o>0$6R6h`$Puh9>Or^YQn{% z372SPu0MM@nv+g!9z_y2w82AgnzXPIUAPdKjlKYjv;NneXVYbqz%xW<;*b6n-;?|1 zyrIT%_bYIHtN{TMRtoHh@&Mkku_mML*%&=EnR9_H?DhVIR^VpC*I$Oqln!mu^duzY zBvO}W3Z_hZsWQ1(^eHF3q*3B`X10tMs_>`(jV>k@Lm@|%pDEX+EPUiEbqcNNXwH*8 z9@q)f3ja}8#bAX=CiO*lb>&_ep78=mj|CjI8al%GVDosVKWY;EXR?*}0>~kIG(a!9 z_pNThGB`V8AQlZ~Zj&{c?;?-e14}QwP&90{;TQ*xnH>bLH|hbTl|}TH2Z}q0CZf@P z=wC{#zn;udfaN`sV=TgGYL#z0ch}Q9O_?bh31_XAuw}J`YPEz-t0k1HCCsjpFbUUH z8jkdhx9fjoSUG-NX&PotEslP;OoRUwd9{5tM`@49)rd|D!Ig~rnx)K95T9oA{@VN6x%o+a5y zsgfR{rANeChqTl-B+2)!o&0xeCx3qJdbX36!7H>)F{T{OI!Q&{^LZyKSFM)kyf>+_wCinLuMs_=E*A%BYeDp3{TV|5%Boh>e{!8wf%Ew)6O2e#Y z`Z}xLkf)Z1t68S8e9C#ux@=hrdrBT_ulEOvZxpWWDKOu>dD4ze8jg`EEv z-rF#Xti>+tle_M7*07|J;*pE>#{n%TayUBeR)a+|hDw9aLSjzmfcax|{n0!xaCn`- zvkigGC(S~Srue*J#?3covDZ1VG+I$ZmCAy}Dz431K2LOh@$%g}Y0B%a=KOY7bAG$q zR&jp2+g5RYyW3WAe!JUNaelkoqVtP{Rb6vD(CmzM4whs6aA^BhCS}2RK!6|uZUAp2XV(Vih;dgMjd3f!J(lR z^~<~qBQ|M-41XNl_TDjL0Y%Nk-;_`MwW^fp5{LnBbgP~&U*}NUi^I<38?HWXG@@c5Uuz2w-eSjKz{GNF{sIuuVw-A)hs}s zEWl{}`J~}5X3?0b@VYUKe^`}|*K98O7(US(9|!NQX4{F+G^0-th5`nsY~m(ddo{f) z%O)uxYpkO0zv20twE1AHKx@xbGx7e~?ugRnZKZX4sIk$gmdZky(bI#?BWadr)Gk|o z@Cb63n<0S;92<;`05lprG_n|mid|pZ{Tu}_jb01DGAUJ~);9{oJQ$ z28E^$*s{IU)d8|cK792O#P^Lk8=~XnvPcB1t>2uuoz#^LYh-!fa9wDP9|3ID(VYC(dd0?I-g?D+W6(&WW{r4@Iv;l5M-{2@s&HG z)!1votBt0oY(tHUzNYSod2-3u3adu5c;V9GuYMdoAgaVRs8w8fEFXtrv=?QTa5|#O zlzUopMf!lIq(iLkM*fd=XV}kK6W(1&77EU2+)jL$o+_P@@22 zJ=7?`BOst2N|GMW{5G|)%@hhV&~_fJRH7epIn%Us#yl<5d6j`(<)&cjV>nQb*FBxbw57uQeq^8I_*V^hyVesTDz5ta<4 zR&hDCEw!TnV|~CVz?fK%0*s0ED8QIlj{=N|^(erYSdRdVi1l!4XWZc!1sIddQGhYI z903^N!f+>K`_?D0Vi+o}aJP9i3NXfsQGhX4i~@|YViaJE6{7%StQY}UlNA>3@k8PV zI$Epqt)t_gy62Q~+GLsLHrg{<4D82-LxQn^_)sK-&5G!zwdBYVKPf9=(*$wc?hc$K zAS%&jC{mpgy9!vfDP{Ij4bNz`6HHMj?|b6@w&@~Pu(eq zHDa)QlF~;Y)8VO&jLx*}(GXM>XJ6L>FqvHoV9cV8RxxJLMghhw+9<%7MH>YevuGm# zBNlBqb%HS)1sLmGMghh;ml1#wUJV=EXlU9*9syV@`{z+XfY;3x{XB)bX&&-0fbh1R;Cx-%bCSm;()I*4i#e-YmDT9fdq+| zwgUvk?g&wE8Z~1_je<^EY5&q1H7bp$nQrJt7lUb<2E@dg&-eG+`~182y?T{Yf`9U= z-n-|Xv(MhY{oB9&`?r7lw>$4XaZgdZmMp7I(-c_3Tfe{(-g*Uk9Y=4BrWCdJXTX#6 zG%}O+cy*elz*5Ki1(rJAE70qBM^{=S$uD3MeoumaGiiPR0m0m-6H2lGVt68&+d zX5x#jR&tI}L~;k4H~Q3^;RbIf98s;=#EaEeaW`l*v!$nG4ZgC8oov0vgO*0qebCZq zx(`|!P4_`dqv<|qX*AsjEsdu00B*nBiD25UdSFAh>VXZ}iU%zmx?X_J1V8E&Z#`I5 zyfYAW*~fnu-qX@_k`U@3_&S3ZX4d_9qf%bz=1FZ)%F#Us3 zi;mqGHxKWfQH2r}KVcr;=Kw;W>8AoH6o1$@oqVL+Z^1(J@+wZhz>-IzUtq~2(J!#% zk?0p#@<{XxEO{jQ1(rM#y#l);VTD7W`+7eNvio#}pSoY*3^>d@D0Syy$~-uAw*qIt zVF*>*t%ft;P@!wnf6*3DKCuZxCN0Kenb_Jd33nE+aeDL}aBUd7PrtgE*x8PyRxROl zs-eKrc=QV_(R9DS5>59DER9FMz!FXO3oMOCuRxEcyH8h4?0$hWAR$>M%6<)JKtkei zlRJ-8;_;Ka6*vPD5)tJ)@+E1LvdsN>LbH}hlL}4Z?E>r$)Yg*R-8kk-I4Gen*8lU`1b(W16OXFnT68%}RW<+d-EoTS)r?+O* zs5#=;K?Oj_sj{}hmbX1D-3NyIRc{#1S3NLXuXGKe z!S;g=23rq=!2=;i7X+up&)SacpK{I-LKe2kFPeMILUy9et8LrRQv9wqD57+~-Zlc7 zN9MF1vWcEzPFmVWGuzq?-?qNz43ug+=2&yLXvmgW&`@_!#z`>SMSA@j4|X8iCv~^W z61X6Jxf5BJ(3(y-p)pZKjS52v?}AzxJHq&u56<+x9=V-qkj@yBxN^3Hc*9)=EQTa@ zi&UNPDoY~d-X0dJJ7e11y|fwAza7ihaZKwjVkLHr!PbKo^KiGD;^uk=dHX@f+H61Q zG|+lr4Txw$9AG3G#Q+Ybx05%$wch7M2g=#lq02gfjrfiVLG^1bDU|J4>?wU! z?(!9@!p<6kWk3O=jh)fBC;e>to}p1hyBZf0-VVbAMeY3bw^~DrBoO(y71XJu3<}0> z1&m|wR=~vNZUvTQ+-a8@b{ld_*t1wcp8ZCia46VG>7LAXPo9uT@;lBp+wF9EdxlB!z*Cc?c4;7% z&M--ybn@;RYAa%p`vsOLyI)|*Fzyv#eogP#%+?XbRpPtWvyk+X9Gc{;WYaIX?>rNT zwCb4W>;1iF62Wu$u4Q8lc_{D67M56jExbQyy?<}-nYQCu1`iTl$2RWE7CM6?MnSjE zuwbF3_iRn?kD7Nslr6@3H)b&z(YF3IazUp6q@=kf7c9qYaMUj6a%_>@ZNWLnq&P!< z?9mOrAdTb>uP7rho-|)eayjNpUhN6oeR@}GicWScR!)|k6`gu0uq4O&1(xJkzrd0l z>lav(WBme4a;#rqNsjdj^rmR{>H4z#=oRS6kM7gHLeY8ZM95KF+2ZdKuEW&5)wU9h zs|iV;tG{HwjGaDm139Niq|v5IPN%6kDtl6T_&#S(0bpC{YL!dJ+6da+TnEbsm|<7z zHswk5Y-VZ;PE6GWX@zYH>SUB2pmaj{vh8tGAw14_2)VDzw7>nL^#(gtS5-(XY_CEX zqLLw_REMKd+7Mzc$2aU~hAt`vVSL;`2p6p@T(Q}zeq+xS!gA{hhy58kw#OS)>mz>==oFR-Mm_6oqI zraOs^`yb2fJZrz^54UFLQ)1&Ov4N_BvMFVE`uSnV8j-bZU=o`ecq@pzJ+ z;)Ypr*>{?zz>=ohFR-NP_6itZjozm$J0WC*Y_(ABO3o2IOFQ_9;$!)v%T+#-ra&LF z@(RVL4ho0V$-^X2R{3vY;WL2Zbrnrrt2`}dRTs(gBV6I+vYL1}tGn*R8Q`K{VngM6 z-|@5FRKXx$)fIlrSSmfuD7BT7epTo}yZ0=}0T_48$xw6s`=^oX-+~cI;ZUPVP$0w zaaCpO;3+@~j?|B5AyI4b=avE9&re~^<>%2Soz2sH^~I0kF!Pf^)U-eSw1;GcQU^Pw z<|+6Fw;ZWb{rabP8Pl}bDt<$+9M)Meb|Orr-hJ>V@y-=*P*NI=#utP_h?3kkRDp{x zseU;eeRZE?W|bDV>t&??57}T7QYD9=r2oZ+g4ZSAg=%`E5~uo&N;VtMXFFt@xD^!OcJoZ`)CR)%`!fWz0P%hNfL!d{hT-pxx?= z_jo&&l1n&!<{%DYuag{a!xzc5N5}NsSPn?3JxFn9^ju&zaJERN45QH z>P%8?XPk;uC6CUM-p?X=bUL`_H>^~t>$_Ulx3{jhTi5rut{-S!Kh(N@*sn!Q+aGoy zxV%}H(+39REf=A&PuiaCGX`hZWx^3om9?OR;>tW#?ZX$CFtVB6uqtH!F^aK5UP_BU zP?RQN4>S`~uP=1|6fg4HQFN=lIgC?BKpy3xifKC9*UZ~w1*OcZnad9l>r`uBA@aybKl;~^`;$2nb)x9b@@Ej2H?d<{1}(HwXL3GKj^e95j~yoHSPRF z$zkYLH8iPCIhZ83_fAnB+&3K(+9Eow`%Q-otX_u!i?Q zU^y?H{xFQ}p3gL9teQ`^M|Rq2HMpL9V}4?ma|0#`+3{}`mBDFgUgX7K-mW{I0pB75 zD%H#3rbkJ#$M|6E&&NWMopQ}B@W;!x_Quj9u6!E+AgmnDLS7I<<~7nSYR5j($X?{s@ z?1QWqzM%8t`20xtyf1v-89ra@k6-Q|S2nG%hD#Hw{UNP8Kcw<}xnE!I4`1%mm%GB3 zZGG7eUmi;M@`~_^uAvEs^mtaPgINHb3!*wk(4ij(4q+SjzbttdnwRKDqUHM@+}=(s zMIC?qhzqJaVq|FjpZ@3? z$MQ0}K;c1s_%WY18ULkI#(~Y5p<}BwLt#eyP!d~WfIEQqNe5C-Tq<zqDq^(YFxRecLW&oP_#(7K>)*OF;YiBOX(=g?fona2IVdSvR2U>;O;->}41$7^(iJDmwrUVDm(eqN6;!7Z=xAXX zDm$4RnmQ9yjt5Ib%@~TLk)W@l$DHY1ZU4F`8rG3PfOb-)j*KCnrvSw2lfF}*?v#@5 zGpY43T!F?eyr)F+druA5Q4dpezs|TY?Mu^zc0xBTb6a@0&n7YoN)KyR*QP5|VDV#! zJ5j~2=B961I{gMuj2-|vo&s*-h#7I4<<%NC3Ws6KT%i)@qeZDBQm8a}xyHHS%#aDg z*Rck}s6Z46IB~-CVfT9WJmQ*r{|Ky~O^eoqP-s{_Dd((4q^stsM+~Ay!KSI{rZtn{ z&8V9;EC?8+$~mU2wl3=1 znM$OqYf8LVsg;|_UfuRro$tS!VRG1!iSsl&(bfq|F<#W7pb?6n2%yx=0S!6OTY;cA z(S1_xFub+iq`rw2qT79g*rYrrWvbJa?06Y)paN^=5z%3(w!2GDz2n}06F-_IM{6Ny z{*;38bJ>JN3Yx?utA|g2%_)EyAawR!XVXmgy}o&Z7D=bz+=?fqcIU_e8X)zitfDAy z#YIrGL@E-4jo9<1nCx{^pv#+@PH!IKw=wiclGA2Z{0EoDjy17x5GjswinCy4&t-NG z8m#Y8x0ng52f~oB2mDlO%qVXOR*vZ5QZ`WHhNkF zI1N-P+L8oOeK1mIt&p5g8ZwLE zm_?LCW{5JsbuSvO)-9RO5+yd+tuMxbyZdOE#7OQ(1m)CZ86j6^1C zwwTpiM?_MCpQ&uF4W0L_j%&Pfm`0V_NC~;8<}yCh${Z{6Tu)#p#y>}fd~k>opI5Jy zVz*f5>Uz7HK&1S>crjrr5pc@Yx~@?8U%VLWiVWT_UW|??(R>Aso6amnmY8!<%;ZS9 zexw{9DJi0HN5D%q6w2d`(hpOR8K5~x@1l>!w1NO#rv)msdg?^rI>wusj=rFi%B4dl z&Muz9U_HK%7lTQ5LMo5bAdFBnDE13I#$!tDxtw#s1(CLB(3mJw=9HgY8fXv#F_C7| zR7b9xogqg_ph4tJpuu%!BELp?11OIxC~pAeaW&Ev$DF=+F+76mn2H7`d}I#d+ z6ClRrT%bdPB1LF06LC8Y28FGmLCuf=U8e;qw0Z(9s}-tibXM3@8fb8qP`Lf2elp>S ztANulGq-CgIYf&Rxl|V(mZ<<1W$(4vSJ-GZ-l^&f+qY~dEgc5vu5#bi^w;xnta7V3 zMZ@FPsJmif;4w*2>VjUA75`bH+0ev%&cuRg-z__&z9@p3DF)3m8}ED}FO$L$nt!F6 zS`?G*pDczjubk&43p5l~s(;?jbTpaSpDbYMSLfJ*F+RSz~Do80K(21L^y8if;M?ukVcOUq}~ST0#Mb5LC2fRkM@1 zsms|3=nXDwHw_@r7;ae00woTslvmUKNSCn{hMnXW;ZkF%alnnC0rFAfN~$aJRN@>p z#+s4_?$d$s^rl z^r(a;)FZD$ubM(j_jz?;1B-*p=ANG_Y!s>4=p>af3mrxw$Z*qIH~AmJ1QwObjy5`% zCXAu1sjP16Jo7T0{(W1bEBV$ds#9V`AA=iC_FiGFEScW?jC2-9m&MHd63&U$tVRQP z;{$e8{GmRXvtjw>n&5#xmc8rG?}9H6tFP8!8>TY2FLK~Xw453cHCaQUlW88o z`qx$)$Xd+Y2gVjH0|byyvQWy%2*xOaF|rBN0t0=Z3x;ku5Y*oVLk7UW#Fqf_<7`I= zB@;wO8f(UA!f8C~qB-&?%8b*=rqYL4DH<`w(bokcuJXhR4Gmy<#RrSANK@$`{TQFn zrIAV~mtE}AAa+UTS>1T5)g{E5y2N^bxT!QPZg`jUU5%KtUSbT<&IeL+Y-lvU{9*`3 z>mJTWQ~Cg^*UOR0w1%am^I}*$WOBxFkS^95uc&8`^RL=@L$>Pfs4T1W1^Z zdnJ^tPbj+4CKRYc-M&pr@U|byMwU?+*zQdG=A$SCIVR3(KqcBVfKtcefI5vbDF{eg zj5HH$~vgRx3#%%;OCPz$CO5> ztxv6S+j)A)AtxQbOOOF^3X1hP7Qqx<%8xxC=_FBj!n0F|<=H7mtI5QLU`GwN{P?ZWK%Xf;!?mH!1HjX|E&z`r6UmGv&@m9@topX#v*5a*cITZOa9)&;S%`fz`SLMQqoX45*P5 zn=rTO!EBGBbBrP_;Z3^HVT<&!kc43bP-KLN;{Ve`m?1lKhv(#-8Z*<2PwW2S z1`>^Ulz6H)=n_34j!6g0I5Q-u|LtzVmg~wTa93BZP3f?(y>yelXz6=g9dz~Ne3l}R ze8V=SVVl~T5i=roY&RtdBSP3^@))^EO^PZKH9>(*j~Iq?R`rd&s>RRt1~3|;0G0x# z`61tM1X$35=9!Q)&<94bcmtCF%xQ9Pt~}Ulh-KCy7UTLO>Zopi3w8^+7UHqXqF7(B zM>j)AAPtPZP+O>XvF?&k4CmEdL2Nu5Ejt8B;EH>bRN&$Z`U{9){Q)uE3n^+^w>2r`r66>XFl@Pp7BE>r3b~)mf|(t>DneQ{FTXn1ev+eiT!V2UP^C)qHgM zZl0I5%|SkyWXM;|Tq`<5Z>WCi|9#VT(%AXDh{i`=2$x#4canWC>Rh6b1-Ur|G6QTq z02l#_UQz=q##`cW6|-bLzz~CFsutH}?Js8WTJ6%lbf2fcXU$hi z-7S-9F%zNGt_ub~n{QxDY}%*^PYd%`3>Gqj^Ap1T%*|3TSSdDWI(KRj5y(0N$n}%` zaiF4-B^4tY%{bm05tqVNia;|AwRB2=yQJU%1M(Wi4r6pW6B3I5Qf1_oVl+PvscLwfeq02+(8NpYM{s1YBB79%D? z*F;T=Lev^GV5t{dHz6Hq1?6<>WK}Q_6u}t^RdE3a6_G7WiNM4Sf`s8tAOl`RUh?PB zBqKPI(H+9{#6lzj%uz5Yr&nu5Z=DgCC$zs_jZT@l$<=FVhH9cuO7h1V3Jhh)J7xlE zy+lOYEo*A62*KXB)jhjX2!`J)6lG)g4j#`A`qhQUvkU#|s8)0=_J<;sg#ZB(=4D{0 z#tptod=zXJe=0Q`8xy2}kCEIVpxjmoH19;g%sVEAIr*l6Na?WAXUK~4AI-DFQ1sE$#{rxwvWS;?8s;>KfG`K!2V+MaQvB0 zH#Vl{9pq;^olU2QF1S!n&gbXw(+XOf%raoyAYIdQn?A`@WaKqNzp-v;`9);GE^E-{4 zV-z9+>lvU(mA#FQ*&2Ho9YfN=4*cgBNp1MgF=`?uo%c5s{x)jP`Ouc>v(p2nd*!nO zk)^=u;Z*K?fiap1fR2>Pt{zB{3bZEP$+}ZRYiVRRzTndGpTb_nX&M{fRt1gIh}F`D z1TyRhu7oGbMNlp<%*=-+>}U8Ktgu>=8`uJC&A=*C=$=~AHhg;~Q|E+j_#!84!-wtY zprtivYBHY{PZ1Xw?1+wf7?4Wr=4+A3Zc+(L^~_QUN}$q%QVH4JvsL_8DI=oZ3pEz| zo*Ik(Sb!Si;hRq+YG}k1l8sIyPY^d(eDxD6^58>oEwo_q8FzoQZa`-!$$Ct;@wLH6 zgRgC#H*gUpTGRamCKvo+z2zl^M#xu5fsQt&8|^7In^=o88%?!1aqnKcMa8T~hD?0M z4lQC50rVbPT&G3#59Zp%m5_QL3{`++qJ%@1sqCJGd)2ghVY1Co3|tC1iT-1^_} zU>P&se`)AyujL00qC$om;}f~E21MUoc{I0s7fy2x8@j)wa2n8#%wdO;_bjj^DfhxD z+r+q6CcG!D-I*|ZtE){S7b_wWuCH#nOGz4&rcENKYjR|SiZS% z;sU=otD+gtt3Xr6QRv-${O2f0=) z=!5e$*sf-5pXs_1nzz>*Y+~=VuX~&=YTNeyx%uggt-s=6JZ*2jdvsaxbUYa5Wq|#0 zqvmPN%r|bPQhQtzkb{YOwaO;mXinBBE3|*9wTO{Rww$A?ZJQly#l~LY&g~TkVJ@)Y z>ce;mb1gSZ?}&o5we;YE)NW9YbqFGO0J{2lTZhQ%bqF5?9#f5bU&?&?e^1lNYPU>@ zlrXn$H~5M6=y$Drh%Y|Lhelz07>NZ zC*>fxX34;p0K_MF#}_eZ{01#um>ozG5+Mx7e3@8`g1nq6&PYOWhRx7DP^YP9u1y2s2tnstup@CXV?+jt?`DE; zHT*uT9U&8)Z>7jTC_{b?i-AR|B43%;;=_NF`?E~<&4@wg;KxXPnat5Oh&^i!5UXk) z6Pxr0C^fR{tZ^i*0qV)vdLM#zQrJ3Jx?+WCk4mSp&{i}qCQ_I6O*a!wBj(9xwBFTi z$@GZ5c~_}JM5yI$5n-lEdoBG#TP6b+?Ej3r8Vpr)A!u|1G1N2&PZ2nZF1{{ohSl2V zbh`Zy*!mPA*)JzIQBcMVM%zYWb2>jT3wMf!V5Km*>)$Ih6E^gZHug)cj4cF{^V#V^9uSwp zhKsvZ)EvvJ!SlQ2nv_RrU7IIHX)+kBjYerY7z{2NA}I6xqUq$|dFRhAI&k2Ceh;jV z*Voq%UBC~Y>+4TDe1w~u7xHt_(Tk+YvLubzk~brxM{Cu6pZwl!X(&88t#l{!YgoNY z5vD49{g!$*yI7Ndt-AA1>$0zTQF!I+>=hNQ-uEwgODBp{+qQx{tLP}q8ZdnmL4V|H{^AJ{39_2Mupk8>8s2Ft*|I&4g*i-6yYMQwPn(B zsE0OeKaa~C2dWNxfiHUta@i99L^rGgZ8A~qWV_KWA%%+(%t<2zpfKO{5q)%QywRqx zf$TfuTW|`#kDKrK-PiCzgy(pfr5=aC9n>;#Ya%=+Kqn5vy5<()1)Tw)=Z5btyHn4@ zY+JX@)opeMvl5Hik=@}*7|GNo{iEs|+j1TVzny|rA z4AdD2&#ix#B>LmU>Lq6Gy!r=^j$!Y7QtfFiullo9j0=nl}^Fx>h!j5ful4Xa1)s4qYC&ieARx_sfr+A2;iseJCG5u$W8 zCqHXZYBK21@;pIh=}T5PP3+6^JYf#)I#1vZ!_GVzT5K!x#B83`-BF8O!NfeNCkQY8 z^_U>%oN0ckCWtZ3^O+q4ix6Ah6;?JE0>&jjhLvI@c9d5(jVv4!$#tE?!C6SFu}Lc; zZPiXWYJ?Q**q8@Q_w0oftXd-JM(N&KJp?EMo=<*hn33W7pxi5Yl@_0qwmmz~8IyEq z)OVAG%F81U9eYUoi#}2fOKxQ3=(g=4l|;Mw($C7Pn_SJ19YabT>mo##VwcuS}^^3NE%r&emUTLf>b6(KMz)Q8nt+;x7vGy|;aY!m8MWtKc@Y9APXh zl+~Yn_?B%Hmn%FC+R zvJ!9R9j2D-s+N^^dWrP0!D>4%7sR?}+fhBG-(> zlj|K`GGovocQp6mox7Sb(Yu*N?Q|Q^&o1|?D~@MZ_|=uivn&1TdB?No`PB*KjJEooe>{7>U%lvf_9DM} z>GABPe)Y2B*~|Run&a6u(vEBIms#~hTbXET>0o>6d@wzl`Upue9o%=6snQur28&}# zPhm~4YWWQtwwraP)#{QectZwE2xgIwk9V5l2tvZarqx&012c&(Q5k&@pj=VDxv$I- zd;@mt4RoLDgIpgB*Ozd8Nw~g(>npozc+@|=E(SP|9kfD4I2zf_F zWf?W->!{i%i`3uNFrqfOeLAkb(zY8iUxhvH;%yCenb%Z-L-lv1oa}i`6}c6jgG|*M zyr!fRl;3pS7oKwk*#!T!!Z#GrWut5xq@U6!pG2260tTa48Cp)i$xYcNLrceI$3?8~ zZ;CcNeuUzU+D&U-NO|udEe4V0K&@*gTGu?9Wo!Ij>*c1guLH)MlI*|5k01|xUVPDP z?19_{dIF8|!CC=9LrnkTFZH-Crq`ElT5rS$svo+=ded0tttJ#cc=?tuHBWyawH551 ziyoWaWwtyC>UpyOtdlT=iB-#yX}uhoMu8odBjHSNEuD-3CYg2Q)iVhV#;CBA6QLur zCHbeH&J8$6y*W&L!4v?FCGVHlq$K6PUpbWKN+F}*d*nu86V>+iO%^7~q6rYdSMSz# zb{fSwTHRp~g!O&+hUNMN5Ejq3$pfah2}<#dsvTlT_01hPT(%uJsXK7W^z0D_TCz5T z@CrOVe*-!S*epQTDq5;wUvS?VaTAuk@$RW;gw>_fw@%Y>42NK6aPBk;haY&Ni5PSc zMn>_ZF^Za?6_O2kDmO66I@DnV+Uw2v#&^#;1jByU53qPp-SKw*A}Z3WNv|on2`8_J zIXWUY4lI9wcwq;MJ<(bhHIT_Ac=A?^w}ow~G=Vm`#>~Pc1O*N|ZZr-%=Itn?m4oJe zHdu5{Qv5efaMtum^oUGf0qUp)>IhKLtQ}P1tpcc)S3~%pYcGnelz1BoBUUhrt(M^; zwqQ@aZCRq6e;E%WyNw(hurE$rvmatI^b-Pm^TBA~ff{~0^N-HokufpUU(I=!nGA+S zsZq7s&QE~S(9}1F%nRe{&czk?#=aB=cL2tyR(<0!JilCtvuEG#NUexf$_qB#N<+Xkja$^mC8 zGQ=WayRvu%b- z9psE+)YdVw{xS#^!c}>>=BhfG$*d%4Ib0PiNR-(TgHQQo6OoY|;D~t2DMNafMliV` zt%Xjh+DW&`?8pX{JIr7{m%miyne}qZtS3)ccUTdOlrfD%acKP0%iCjryM+jA)b$B2 z+k+dXA<7V&kr*kuUcXB(qfY+92BUOUD-pUo5 zDwl^0z%XnzWLyGL>tFEGS+<5o{DX)}=J_g+7l}M919In4+&d_Aw1F zpVgQqK4HU{!rXjJ`Cz0pri_$b*_e8|K_g!B5Y8#?<3^!+++GoKc)6;|fT0e&!pH5E zMimU&E14vUlx+w@&51CqI5YpBrzH0^hMv9a(-I+y+CA>qg30Dl1r6KN>a;eD7{aqV zR9vG;R4c2i-)+iwq%X|@E1>gZ#z+$?x>GNBoihm-Zdnms8dTQAboxetWK*@nFV9XH zckbZP$t1OXD@|WlyG=4>GU7cPyN#b9#-g5 zNRM(?Mk@%}=r1k}g8>GV$Ni<@ObOlK5FXdsCKtI(Be^j743BMMNqfYC@>LT{B4;atah7WfYK{4QdI*gS1OYe($*VQUZo?xvt`^nzY-33c@i^hX?5^oS2| z;0iN?6}1eR+0*G8Qa@fsf$3E`PxBLHDzscbr{`7r5)%U2B4K&HtAo`S{_C4aD)@Fw z5+<|}`h5RiHn$k{uT7o<#}L}k_E2)T5){;6Vu_UCZ+ny%n%sQn^H8VL+d;q>=6)dX zx7cAqdNN}=Fgo;QRwXug++nSQ-17==n-r0k(?fQsa=Mn- zqP}0246kwr1K-x1_{hK~ObxHTDnyc??PXZHcCZMz8`U%_&Zddv>6EG0cpmrYl%h(m zMh~=S#Vt0}BUo?+zHSZ8kFE-SE^4_dxy|oN>fEl&;^VSYi#x^S#nkF%m9;=l3sZP> z07lSoh<2>*vc&8P*%M%%kK8r{+o7SvZ|b(axENi1YCfSq)BHq9n0?Ght`vkx^LoAJr3xzLn>R}s4}9EH${HrxreRJ zH^NcmBg3ZQOWjpG@U1wgiS@Ni@0L+nbD6InVO4uGOrt7xnO|XSlYpV$J7zir=lB8!Z2H2-Rn22VWilCmR1o-r{4XA%9jj zcn&KWBXPZ8T|4cHp@JJ9G|xzFyRHG-XbJufFR$1wq9J6?h5Xb)jS5^d-+&zH<(PmE zXjgm-+S9s{LC-0vPH9|-p6R+18$fH}YAT56RLRC(j=$0e-aXC1ZJq>I>3dIKOh%F$ijRpQX#&2+gIrk?D%Uu#+j`$LLjk3I46ebOzD=sl z_!Pr^`cZ=S)EBnbGGfM(NHcG(K#+P+LW>z`oKL| zYV&hLp+2+c5_R>o1f{L{XiUQ9h%jq2fMH#pm+-eZL8d#;OV9RN%MZ)*!tC`<+1WD2 zec;s)RPJt^q}tA&o7yI>l?R@0K03|skq|>@2rX~rQgQdU`#mvO)1$*<-4&#$Y4Igg zy5`dKF`J%IUi3{nQ2>>tVVt31(+D-lK@%+3TrUA7U>!S9ZP&$gX$m8^^@^J>2D}M0 zMmUHzNvF$__v=`MFl;8RtMiL(^Ub!Tm!1dy#$Ynu8jqxSQ1b}N+=W{S9P4y-t9B;_ zg}{>dJJrnub_K-)ri%Qs{rxTjKNpB(=cuJW znoMA%NPNDq#GMy!S6N`oL7HIg;j)NzHH9^yieFVjj_5id*4}sN4;D4vG{e=))OA%Y za*6H!nTEo=fyL{8k4qcuW0@@nfmzp9j%6RzJ5nT$W%t?TK3(2xmqjBEn7h`=~?RwB=i_aUz(Q3rcjB1qk z7)2&lgcDbDRNt*{Y~=~PB<{)?cr8r>!NSquFoG7+g!$=`JIAt@Qd7z6=G7#_RE7;N{1Uc@(uG4JgI)gyDkKSlqf@{-OzCZo=y~>5%tv&8X(Wg zUj3Y`1O$JRb_BMXcg$%v(N`DtBdJkR6!m-&I!Lp0yVgyYuoZMrl(C4K(3Yo(H+av` zR=J|BQs{1~bkvw``$~|?g(|*8f3D^GC4vynYNM zb#&2+d8mN<;zzCdo!O@3fw3vp*LPi2>9qLIHe|)e^-&LZ@oOe#KfF=~w#NI-Dq#Lv z@tk*w=P;VkV(=^siog7AD*+@)alcji2`^Q*71XFXqHI2cbOL6AxD$;?4aL}zNm$bY z1XKKlV8--Pa8;Br-2S574x-AbC727bYE4+_)2QVW+fkC95`*d9(CTOe<`|-M#z_bS zpNU0iJT*>E=q9940wSS={qmY;C8=#@E?P*Pq#7l|1nu_2cgYs80haJOmc7qh4+p#m zz*r#uf$AvK{^%^}{cv1>W%L=lO2@Q#tv18HMt@$t_2@cT?EguYr23QTPYy@?an3>D zG5O&&eF*a!2@RY2_vprWeKMVGZ0<|QqM~0)FT$h2+He$ahewYdp(ENQWwP0JOYsLk zTzSBbl!~@AN`Q$iyd6sXBe#%vWkhQ!7H}-PM?Eh-DY}>si_eQEzv zzgl5wHBiWf%!AA4z_TJmByhg%6;Xec*tsD z2_WCP#8U82CsZ0DLcTX+6}I>T&AvDavN+vDkyjVikjkT+Rqy*v&@C^iFXY7-n|X!^ z&b4Yw+E@`M&Rq(@TclR$Qhx}d#jk2F8;8^NrP8iiH)p!OoSR%oh!9~b%kfwo)oYY* zCmgfqCmuMpxp5$$v0Z7dHbY@Jl44#RbVFtV*lX91S_SK`$I+GNAAf^m*UArQ?_RHy?Q52CU zl<|GvB9wH{6lsMhAvvhi>AG!)qe}>&nG1{X z8^VqJekn-xOwwU%Qt;_AgdnEm9SwV zaRS(AnJB87klf&uJ;EzBMJ?3RJKTUSC%@w(9vODU_J$i5QuJ^`V7+QUCeHBbbj}ELMdUUu99v#j8 zo+~GMD6Q?!%R8I8-e-4n-MxddA}B8Jp@0yq>-%k>qgow|`iLa6Y^JXdvA1Bs zM%P$+oT|Ywac64e4VM?PteDufG5O-J1Te&;wvxbhYaXCB>UYGJ!{QrQrfXKy)WysX zngo2W#0;(9Bauy|o~BK#)E1PN<2;UGJ~cRxp0&lJqT z=xE_qz5ps{7MRts%uavG#F=a~v#^S*HC$@MQESHz=YjdKjx9nV7SxaJe#E|u7u>{r!!=Q*u&dQn29NnjaqsRdfFrIu;u)OK`^ zBv_RHz`7_IbacVV<2=xi5zWRy&mteK0rRjlCr?=t?yRpD7N?Dr-kBzhpI#2q#z>Yy zIH}oIy?&q^TUH~>G$AtS3b02LSK4dLNJO(PSz->PqNmT}!SmFXzM!v!caQnIm&SK5 zUG=WCmdmHN3^;tqi`#-QemE9z#WK`C%StM@Jzp-=f(q6Px0MQv%tU-WSv`_|9Y&`~ zK9=Qy4Gol!qt%QhpP_b^tXXN|g-dqn0I4ct6&sdkf4=UBe18iv>hN#y5)_95;;KRm zpeXxxjhOi}V{p6A81h8J)PN4(?6Jgr=&bkXy8u;IL#_=@R`=xj7`VNUufhw3;XuN- z2f}7!7zkK>JrL?u7zi$%yPE%w{@6fJuLBlFf|u)&2rp|SmR`1zko6`k1LU?;TY;+^ zZ1mEoQWvDA8>RfAd@aSejwR;TMJpl9!m#Hzq;x`-MVU$+HL?h6TB>5EkN}HX5$ZMA z`Si!vh&8uigut#?czB?3pfH%4n>HF{`ci;{HQ5BXf-Bx&8yV$Jical2o5_SD{up25 z!Sm>$)t|y6;SZ~(p^n#%t60AFDMn*_Ah}hd-Qa>YtZlzl7wFCDiU_3Q4>kX^qk#3)mgK zL#*d`4-fFLDp@1**Pd5D!0)dWNxywerD)c_Jzw8W#H~`p>Xmqr>!O!z*-5%y(%0j# z?WAXkrs2X0aAgXtapEva;u;sY075sELd&863@ERofwct^wx6I5Rcd=3)zCo``(1<^ zYs04?U4-3awp~acKrCGZ5bWv@h&6S@x4b}Q*aMMQqG5?;ibk|hIpZ2-S1dt)0!yHB zYSJI)CR8M!h{$?4{l2xe?54qY5Dv#LeEO|g`;cv7dMDk_bZJ4~kIv-R*x*;^RPN(< zojc)h3 z(d|Ary4@c>Ix9eS`*$&xYf0W1yCBPqUx@SB9iraxOu4%Wo5FlXkk3i1zZB9dm>0N# zDOB9h!MzS8wkVE?%n-t8;sTR-Yf6$xqCDHRvE1x^=ENbl3I-1@m*ake{W?G1p~*DR zqzF+u12l=627zlM!U~#%{+4JG`dgw&Py=R?4ownVFPhAC=s1ZQ_LJC(Znj5y(jOFV zbO(hS-9h0-cTkj7?g^;0N9gAU(kFn>M=NM@T{I~drCo?P?Lx$97tp9^QW*jvQ_dJQ z^F2Q~hZ&a48)#BPrYz7Mnp6g8XmVU~+AWb$eVRlCKrSuOBoS04zYR^|kD(117IO80 z4~X5sQH$>tuVg)n{vU}*-j-HU2l}Eu9DJ@_A0L`qckC;)GAI>1 zw0p6K+4l_PW@jk&sa(b0kMp$KC_Rur1EmYZA!ielvrJu6iW2i^0Pj5Q^&+A835tgv zfJt>EwUs0>AOT9hN%6n^(3FyIe?X%Kra`fTiR;iS(B_5#+esa^&QSdXWQoL(9vMk6@GP)(-cs*=f z!40c@pIVdZ0Xg+hb|c+g#Nz}>pH&rS=R zZNW7z6Qz#lu$6Nrrc@I0U}=}dvLmm{r1gI0S6R1sKGJ=RLkL@O|)PLfUIj6JO_t{vUF(R zKCOOA3yeFeusi-N?@WO767vuMHoOC{+m2K^6ZlUQ?y(nTA_iiLeWo6HpAvi=zpCt+ zX8Wm^2W`W3G(^~xpq=S|Pme_&VV2;xG~0-gu0$Hk(*Q7%9R^H$@}jxMZQ# zHn4KZ7W#NO2$vd=%RDo9SeLA;v2J77S$LQs8|Fz)WacZ7vd_6MS z6(u{8JFQ;lCR+?zNR4JS7ZtPnk&z#cZMn`3bP^Ea8Kl=&dg#l8Bboc!ymL0M@B&=Y zWdMT2Wk8ewbriO01QLL-Wim@J5`f^g10fTf%jxugCH7vu7yRm~`@&70AUUz2Wyqxn zK}i;H>qKK6%_`8FYTyqVW???Sq)KXDJN+Lee`*R$8VbY;iWDe$=Jihhu|Y#%nBDz$s;4@h4KBgtr3<5^MvaepMLKbCz+Zvx11znXq(m~O~p3T6Lzj2ZmMUAIss zDZbAfVRhZ}rWq*&p)Rx8ATYR4PBj4zKUc?Fzu$x=NX!MoGBjxW0UEdrqx1*A3Ymr- z94_kIu^~5r{95j+N1L5i+q!?Z>bL<)FzyKQLoY4TM~M{ zIUY<9+#TzH9XVp@EHpUBmnbDl_>pXt5<{bUAdnO!1OTdQ1?ITzn{5EvR;Cgk1Tp_R z?w>0lEfgG|!&an3$!7gSDS{--;7yC+b5phZ+OV>OPi4y&mJ(X7K6_e&y}ngFO8mmN zdeNJpwny~Uc#cFfOcDMh1ra5v*3yMF1KXEqae|&ST~B4{0bvU1M<}Fhcu5HSEh=_WVwUfvLCe8!O z2^!aPQ%nr8FPX-Sn<>TyHS?F*Ya2e83@ll?0p%>Hbl0Rq@t``nAXyN3t1LYz-grgM zex8xB6;LLe9Si`A64X8sZC{dhS>+hqQktdZ1M=9GR41C2v7SFC0(ZO6CWs8aYVF7_ z!i7nOkW$t>6OS7P2r-#B?&%L+S8a~s+d)dLi=GO~O$5Tn1Tv!1KJ~J0emvZ?PYvzy z>|Wh+s6TZUy;P&+;@o!5+PBVKqRy#1WrX~*0do6vqWq+8(XWY?6zofNW%XU3skwzl zTI_sW+^cy&O}H>_)9RkO+tL}{_>PXw@ZA>5KQ3%bfMcc(DGw9~$x0B0k{VM8JnR7o zv}VH5M#5e;T8l4u%s(S-lB+SHbLa%IVL7OcP#~Jd((6I}M{n;yP5&a@0S;F4?V4+# zCs>D9aEZHPY`wKKP)sd$RG|I zmVy+Rnl>1gFw8#cHkfya01Pwnq22KzY>lQ(3A+2!2G-cM7L~%z5OO_CU)(>ijYwxu z_wnrIUh)e@9TU>Hgt>@<1TBMlHht(BbMzZsq!e$LvQd0U%@zO7{{FK4{YCrxF8lkA zppXQ0;!@Fe(LDq7ow9EH{1eQ`Ysjui1ubq4k48t3?OU z32_pcGtC1jkP@yk(53DE2_}?7`;p_hYe- z>VlyNcsiav+!Xq3bNM;DgeA*8E~I?1d3Fc)0=#dxOJIw|zQ1{PZ*%$6q1Xel*v~c3 z9&9duKNNd77W-)P?6b|~=i=ipLOo_VC`8rhY2Q?YC1QlrF}%eOhy)2_m4%LLAOy2= zmBc`nyNyWiAEYx|+eZN`sR0#S-so4IydLE_lk9cnUB)Rc{J|Ff`+=*u3iy^IK)C_3 zD!aj*#L#jz+Ip4gwy!#gliAjUnHng^sSW|c$khZG!*j;WH`u%-H)G~0k_=YKc2ma5 z<|rm>|KQ8TjC>(dJD;6yE;hD`PssiSjP;Y{2C=2^0&tUQHpQ{dc)&|UDG#m%Orhf& z#p1FPl*D$e>r;vyxONhAYBJ}8W?kOW%4NTjxdAVH8-9y1=;C#asiFfqnh_I)?$0+K!OCK z1cqiMf$4~`Jv?**Q>;(46VZwezE}r;E!LMh>(gCWpSmY`q$U|U8#L>jR*^QsYbJm(iDe$%)93BU`;D-z6nogp_jkM<#goP8WDMg^KZlF~JT z;ya=?&~)P|CzKfg%xr**w@I!^wy&3-p}=(&PWp=L6}TW2_+a}DKmwB1u8d8a0t&3oc7I24P_+oHLB&Lh9q~;{}F@y0y$c7D~UZI`k>88BsOk>GWsPm=D*3bXjkx z&r9d3E}0q?XmN8X_cN0eC04Aw2 z^g}A18rx?;sB=2~1&(xew3BPi+zSYWnYq6O8h|-i0`;;4Hwhs62oc4GdNNP*6J@Go z+=!OeV3-Bg8Vu%Pe=tmXF-+<_*LZ`^dN9_)VCXXrhSs1W4$~G6cWBP!T#XgsPs=S1 zi4+h>WHXrBX<9o+u4ddG*f;eRB8p`vUc>WRn_cudjf$FCWjgB4!n&HF=~h42giM!5t_tzsm)R+1)L1LYC)={$xS z#P5;N+(W)+Fff!!ipZc*r$Rxyb7TKbyMQ8FU{)TmW3{@YgZc;XLTev_5TDYW0JGn* zZn0kFK+zW6YQxCa=hgU$#Uyiia3NB1lX#m70=vGthtI>paH@FZwpZQ!)b6tFEC+z{KKii z4!j{r1LsH*ie-_}3y`;N&`$RXt*<|uOMt!!1FO+`R?up3+GLjGyP+EWGmvE}3J3W3 zPbgQucl835ODaN!iXc*us?4&nfYONY$E-OzI8?=dJ-Q1deL?L2(;bm7OVS3gG<7H9 zAw)d_-p1#zuNI$}Xx~+fFP_rkP0VZFoI#8K zNTj&hX!u6`F%qpUtDwBRI@6wNpp8n?4h@`5f3lzk>r-kl8r^vMWHe;9KY~bFcJZI& z@RASVy)>(LkSaB&Xmyvv6{+&yi^1tpieN6Aoug17|^pkI|-A@8Myj^@%BK&W+IIN2N^ zLvsmHsSw3|vV>idTH;7jM%X!lL?#RtW8eD8a&Pf(%!v#b>ikgo50qU58#$;S8bP`l zFc$>~eM9ev*z!oP>_qK+3OJ|lRMba(m8e5Lr{gGS|8icu&B$l^?=E10Bsl9XuM-%T zsfWh{%K)4xM35HU)x@5a8x|vZ8a4KezEO(S#8KL=LPK*r@xacGIhyC|{9j+QpVU7R z|H!m`R`DyW`$HM)v#|&SWEd%dXLZseemLJ2Oj9Mk>Io;N$xAgT{bBDyS@|X*QM~)9dV0Y@+;OY%>&v?fMp=0!4E^Go;tx_m_sSg5Vw;rG+ zw|n4lOVc*}m2uq@+#D20Q4O#kF2m?DtL6h}9qmZ_L#yAg^TnF8T(m?@-dIjSXQs)q zzu34=!2%r-W^}`1%wb4odnRWubikz@Ud|=ub*cy-V|knTH1@x=SY}lu#4Az78k~51 zibK>W&G`c|aX+PX=`uND6rCs?R3rqf|IQWh+*S4`fq1e}AkTe^pkzPOOuJHkzrJ zws=!5=Iv^E1K~VFvQn`qX~6+nqMVh~J-l}7#ePx`Jm(Z8*_(k+zxp1FdAE4}pHlLu zL(IYF^DQ5QCgZ1G66FJfLz_aO_n-qL)11}qW}Xm=X= z9c_7Khl5W{8e&N|@CJLK{dlApIq2}azX2fcdrA+p;lRc+-dQAJ?ls!p%17m%;Em>?hY2i5B&BMg;b_M3TBwX2ty`dLt6r9aI4-1#}>g z^8qmINpg0yvShdfW(Ko!o1^Y|v}j<^y_7D#NfZ zap7E6Z~NmnZOg}6Zq?hBtljn?J0!aki&+RJ?-1BgY9VZi{*bU8OV~c>!Z8S2=>{1x zU4AoUC8d^x?MF=5Qc%J+7HovAJ(m6&B8XMVQ4_2m(~CA0c=nLKFb4M75z1y`5acBF z!UW|_Qc0F&D#Fj=4itc}qePvwC2BpUHomIzUI!`4>sTdXwaRo*mOW=x&RoliQK;2v z)1(FAdb3Vz27Wn|w^K{C7Ae!dGQX7ENtbVh1?}&0AAL~Kv36}WSpMdHQn8iL2zQy3 zGPETrW!ZI$T>96bdP7vY2ycy-P_OhaKE_(<<&!=taZ-qc^-8Xz0zbqiC@^AMroHe{ zb3HSgQ)AF4eO;|p;B@*bKM1))6p;{GyM?=hCcfMmHNG5F zc&%s-i{fCJy1Oc8RD7}c+v@;Yim;+Z6pFN%aZ*}jy)$ov3^AqX;GoH3cr`GHg*ZwkfuO`9RDb{AJ zQ?Lm2s@=?fy}?u7`M09;!_!aTx{R&{R<{Pux>PFGYrV8(2#)695LhulHtLCy=W@Yl zC3WA|VS90t*%>@CdP~kOV!z6v!W*x?PU}hZM2-v6STcDOFjmJOk*a(uhemu+pE}3J zf{xtDfr1g@X|R+c*Tc7?KsBGj^26fOaWSXJ0RYJTIAM8^V41j%ki(dbNLvVDsA)$- zwnVT_uV7uEn;u?`#-cY~G z7B?Rs;3%*WaO`I5NsU{rr?W?rkUXh0w((e~&Ovctkqv55MOLEr1sfYel%-#m`qM!H z0|i|uNhvPh0Z3nOkj|J7z%Tj#RS#$sxY@iuE>Dr_)QHkz5j zS!e@tm2WtE+Jqx+M)m~H^_EnPM`z2EKE2wGpW+xbc%4`XFcAFy_Y#IB7~+x|fLsBekmFh4nfl*K#7dYKKuBn`9})|p4H2jkaT`d6)LKlw z9w#yZ7B_H!6!aMC&0dW9!RisSf|+OarOOa$LhP*x`3|fJNHgqb!RV(2whp)UmjD2i zZ-LUbJwS>dP)JSl5GZLNMw4VmS<{{j9TB%KAW?96Cf0L?N;Na~SQ}oDnyiJ{=?_oY z_u$lCZ%s|+j3hML4slm>3DI`EeYcjeX;BJ-8a7>$jUNwbK?>SlSx~~BZp!CuA^uJ& zyv~R#N{2Nzy9HvB;%D8iO5y}-K7}|UpY;dtk*!bt{k;7%_S1aF!*S|Mm<_9Vy^e(lZ4`V?_Jz6AfBa+eF9g#X-6NjLp9f^Y+ z!4$M4SGPuZvSuSuzzv1=+c@Jes}1B?yA4$FHkfCuqMja(rrYA6!58vsyZP3xbnisu zm6|prO2|8~?VX}_t%lQ2cOQvf7k7Z>Y%$fU227cj=Ur@1HkPk~O(#=zDYsP%GNs<7 z$lU?sW~&iRqTn)ZpKo?418Bq6>?Nz_^B>liX0C5Lum-RSDBK8-TOIkWaJZ% zGs6*DC54!MwHweaB_)d>VCQ%)*x-F3-2*OpiwG(4`EB7!fWEBw`foQkGdsWeeJgdp1@K# zJgwKBEw3KW>^*Pq3sRt3E2&}q)Z4S-(>LVg6Dj^}+~iNMbxafp$Ve?NEPUL))5!`A zMbbu57Ks>0W(Y_YsYTby4G~IzgN%FmSX@*n&9F)bVrsefs6h@s^a#0DJwL!=Xf85# zwH4Yf!KXaXR=Mj>tl3g{c%8OqN9|6VvPl_Evx6wUQqvdBBc<2-`+QQ`)=r;AZf*O{ z$i*nQ=e%tIQrnq2=5519XnWK+W95pKNA)G-!)G(2iB6PU8&Er25w0sbWPiL+EVRrZ zuMp8#{F2@Lt9@k9Y*IOvg3Qqh4>ys z#y)@-Y#b`30LiIk8n{s4J4IR<4&m+c(#4HjB;av705J8uVCX|9l=(^#pkme(D$dbN|qB$sej{I&?r7R-x(ugk;cMlF8JuQ$4|79Y0T zT|hqec9h!c0s9+gvj9QLFoZU_amK*`{pD;KfuGg80$s(bPsVQ=G3LD#R~gzy3~=p0 zM|8thIdV}FYu7svl-8m}PBq7&#raj#>pYR1ijFW!u>6%`BBcpA^4t z$im^26c0F6O4Q0YNB7g7>7@EiTc>YwiYB$eCM7-M%zdneau+!O6Rl}WX=_Rfa>o;> zid(g_r`qx#^Vkm~!InldC0CSZPi1Q|TB$gIzfAU2TVRxNttDXG>0rm)>Vh0aph2B!8l496<#e))6E2CFunmIZt8$IUlny$&9b!ZNUyD90 ziv*tt-X}Sa6mDyXm5MKIC!}o(5G<$5Cqy;Dr{h7dsA#{U zam25pMJd);mE(_=jV`9YmzoAFO1a##U&Q14G?1-x&(c4YA_ z>JngVIdgJ;UQBN4cjJCDs0R!x>B%kZITN0$`{W8^h>ABVl26u2!XX|ZH7e7nCAK2r z=|sC9O`Bc)tlp(dI$o;Gd{Oz#{EQtS*8xJrjl9M3e16_io#`&? zU!U_YGKh}$Sl|1V)wsIL{zmY`tlQ-HeBuBaZ8UdCkr{;k&ult}`A%yLo!C}Ze8!q= zZP58ar)f_?0E*Chb8|oGEfoIKq-s3PGXVMMEtPAc@Mg0~&^> zF*A-Fwp;gRcPj6mI18Gj>CP||h?M|v9VZJvCF}vedbq;%EqM1L!e0yrgHmlQLmQV>r=TjYFP7|f+AK3*4rOdHj< zPh!+u@45D@|MdVVY+N@oA_HuM5WFSY0tc?RMK{&^$b9r&-PUfIxjIMhGZXfy4`#z* zOpqhLHJFnym|xDEq6*^9($Z+p-q`QSR^T{W0$}~7>83~ro|*$hLX(Hm}+hgv@MWyp6nbKHdrI36~wo&kpw=c z?>vg{#Z09hUq@Y$Lr6{1c3FTV{7G>?wp}(6E##0TVRJQkjzpeoRmtoVd9H~(wda-l z<}+i};4H{9f`m4vJueD4r-K}B;^Y~3+bXGo_hLd*)_+52028bzQi7bwdj(Tl5zZZ$ zY_nBuOmB3a9>Xy7%NG*~fc!2Ech{-KQ=)Xw~Hin&c_7KfO-wiIUC z+iUxtCx9zY)Na$mzha6;@~hceb8Wr%evS+o;~Z&9*&61ar+tuq)t42($V zU*6rN%BUEekr)*qbymcP+h!(J9Q8sP;>X{7%XWgCs>AQYY4oNON{zO#5*(XMUWvKp z2nX=a(X`fsjQQ&ma{Bch8JWguDoJ3c+=q zWt%sntuXALv>*?5`@Pml3(Rv6&K#1hU|PB6exv&GUak7N(QOPCK(!()ZDw243KNAj ztTVS6V+C!~RV}T;OjziQL9=#qRIPJUp%9rArG?Vh4aws-boD0-yj(D;luZTicyQf8 z;Z;haG*`IH`Olgw0I4+{uuh*c*S&OCUzOVi*5Uw^`96bNf4(^Atk$=!b-gpOXRn;A>wI*(!Ft*bm3ejlX{b=+kjRe&~AIPt$ z+#+3Sc2s)4+faBRA`Fo1**Fdw`rZqchBq~B(c+Fqv{=hE0 zefMMSLup);RJz(T*uuw-p1}ic9m4&DQ5spjP>yjz(_n&UP`hoSXHdc7(KEQ&?kX$> z6+$-NXubwh5jRDTY-~Jks|>$ze{4KMeL#6s7CF7hZ9Ejd$UHLep21>Uiv;2|$^+lB z@lY066bfpG*?5`w3wBL_qi^G}zt~50;Y^>I>PMzTyHk@#if02y4Z~s}8;=MV4rmfS z+iVLJ=Ty)2*&6zpb{2^(w`N%lV#^#Bs>HSTfU1@`yaTG#(Z`A^OhP&CBr_m&oG#+q zr-T6GzXZo;sLz6yQprmR5DJq;oy3l|LAQfFR^qn6ko#kO}PHf*(qN+$%?-r`7t z28^E6o?~q|t)-;su^ve=M=2(DlG*Njz`Vw-X|)%xv3U?4V{3F^N3XFqeg&`bdb@Ax z*GjK3mBmSetGG>s9j`OEi5wEBeXMulba7F}(A}<4Tf}Q@({SW^LOkL}3b2vA{19t7 zEr!V^o?Bnmyl&vc6T-$+fk`r&fQ*;g4z{aTqj0mPc`oZp8wT3`gYNYWLaImCc zJ{YBg(M8j>ake(TsF)DS5WC=8y}S^#w>a1Z0aX_;nU+z7hTbX7 zf#HT&#TaPitBVmd^iFBY>^clQ#gu-*hV3}>saK{_##T+g8F2+?IXP45gIOn!yf;Qc}BR;?q z8PF)GJS?FcRzN|!CMin-Q)Pl@{xCan;D15#1{Z_2$Whf|&Gzz{?11A%6`kUwPnzd? zEtfUZ&;~1+_2>m_hU4I(6@j2M_S?2*Ac2;8&KG4j%FUW#!C3<+wG3;<0v)4|r?XLI?Okr*-HHTm+$KD>9U6!J!FZ@TBJhHEc2i5(>H z7+a%>9c>bHvozQw-G~wTrQ>8`_rw;$I#*40Zj;ocr0ftiuL3ubMZ%Gsvc(@;(=5)h zS_5j^26e4wnlel4n(0mCf*Jr*cxa+xfyAfqYn$17V|^JLlU*WZjJarvWy$4H}gC#$KPlz>IoGCBbNEz-ygJvew>f@3r^r6&PX2OyylG8yu8CPMc05c-ilqnv2M#J)C~<9D171 zIh;0UPdR3}v+bBUnQyXpQp*2Xvpi!e{ z;Cz4o|MR?;b=jA>Bb;C(6X%1pa0Y)Z)@)n1&E<9CD6sgZJU`2*Rd)(Y53{$*;J&X5=q zKa09W<1(3Vk;dv||q}8=4QZk3Q}=J6RcHh$IWfJ`KltBMk|O z#o(eL#)W=OLk!v4LZmsq;3f#!yO5DA{{>c8Mwo%w8e@deL)HdlznaPSwr;5oZr_`+nb0>E{J*r*tu zrMz$a#^*o(1!Do>a;pY5sxP?uBY>*BYh91Bp5nxZiupKlhhXY#O#o|H(7M1#&Lun8 zJ+U2HcSIA7?&X?XdchX0P3+ZbJ8fbHacrydKgVfJ>FunY_tt3520Q}GcQpCNjJ4IV zRP1~V*75Uq+OhRE#b|A<))e^KDl1%VN7J-1PBBBb>a77^>-c#)?YIG78^f4M%34LBj+Bel&%u@Z-|6s=W4Cu|*t;38EvK}qvdiMo7%xX=!k9-Y<Ho-l-r*|+ zX}Czkq6zuL^v$X>_^d*mftkfZ5~gSoi9hsdTrPw6>-4SewYD10%Bym+*q=<|Clr}c z6{R?$If)F;;2jO$P~gMPiiV&4{lW4gToLvWLe;x!J$}erZ}+kh8b121*R^$TUWX|{ zjU4+kJev6Tj~aHHspo`RDf9DaON47y&1RH{6ofiq9{N1?ZMsUtmqbumS6HReJ(>-w z;i52KTIL%I6Q!VUPFtBi)rPd7ZT+g{LT(mjAs?6Kqw%op687C{JQ$fips*i3Wa}Q@ zejxj{!AG=ghR-2<^?O-~@OY`Ve(QidEvK}N^5@@-(}(O_(ZtQEufo>>2T zLtL&BUjsNa_!7U>O%4e?-dsQ4;*SAhT9tDs9uTRhXS1*9?kyLO9LVknbt!pQ{b4HXSZIuA!mQ zf;zN#cnI^O`c3z;Hhx$VX2~r}TokrHJBH4D2uSfOx6`bg-prh(nK>Aqd;|airqDwN zyxU*`yp4te03MH>LX=U*CWb=;b%Z^T1?@K;2P6PMdqEMlKsr9|D{=yB!43gdtExJN zmX`zGxxvF)I*H@}N_Mm?I=Pu3Y}CzNKm@G^FC49ix@``$f-BNS0T)jRx6%jB0CYX6 zx=$f|=xDf5*nXOXegYP7`QUzT{iu=9KB;2gR^gK;T8{7;;RD%yL^RuroVdB@^nPxw zwh(M$*BeNyQv?jufX(%96?|R`M3{8G#)#=rh#?Ug7lBHIvT=?Rco}2@ywbsc7IITr zPF}l)1ZV}wKqa_24K5M(uN{TYr3DQ|tPA-X$8mP@8dPKVXeEb?#_BOdL>PQb3&bo# z`{LNNf{&8jnCq1XB?=SHPVTrLgq9eq=NU(`r(8M`pZDo`V}nz2#o#SYtbd+`qh|$P zQ;0)Xr84)_wnL$O9MUWLd-2}Ee^Cv&)%PjPmO*GiO;$*f3_t*_=gU*=ru)-#RK^c4 zz=d^+k?b>pJYWVOl+#86?{<(GR$vb9)ZEJ~Fhik8itMA5o@id{o|eZDGyr@!$56ZF z{d21N(`A_2h%zs5i5-_?U^>Y{ z6urz+vM;3!1vD;uVf3tzU;&2O*t_K$yk~F67%ueeB+mhrL)A<T?Do9(+{G=+tcd z)GmPu{3$gg^=*v(V7~EC`M>SM>X3{b$xNhQ-QgcuSJ~jJ-w$DISwTBjAXf^>f?O6m zKKPutX#XaS?rUjW{d2+2Af5*w)EHSEq5R-|ff539@yx+nE%nb*!|no98+=YFVe3mY zbDg-S;UO)h<(ttj-vm2Q*7csnt?hyk-I~&1sx$97-=49AB3pq1>oB{9kb}T|XGCi5 z6A~z>=`K?s4K8gm3V{yS4YU02BZ@u{ZgxJv%$X?@_YusZz z4F*W?M7i-K*DSumKI)=qXxkxdW@LRK-~R00xwwzkeNlE%k==RqdD%ra%!gU>ATn}+ zGq6cQ!En2fBBn^dHK3v;Fk;{=l{{x7`WK(fO`0rNGc~O-T^*SqXVmAhH!9 z9O$3|;3O^J6a$_0sjk>QL#>$;?Rx|Ffdho_u^hC9)Q_Sy*ZVObs!2$AYp6}&8APg? z#yK-RlPW@=7PX)%Ff5L$2p>7*3IkUU_aU@(`H1($xTh}&(@~Yyf-qvO3mS(eFEnNl z63o%%D2z!Yw-qrw6J9&GhHVqy_6kIEu24~T2wB5MfP zEdsefcyU!nP7q$)BGApMyod!b?50J~;Rr4{ZV_~dQ{}}if)1jU=_`7A#MFY6(!5QF zGvkB;IRd*Li&Zd-pgtL$*#upJ3DladY2k#Wy0UGJ2unotH6`7EIIxUvn16&nf?JMj{gK&B-sJFgu_a=B_~jzao*5W}8Q1 zhtXCmlK#6g>@i;<2Zd>h!M0t+fDeyw7%Z`R>2l!1vH>9-4bhhlO?1Iu<*LD99IXi% z86qU`+=!eKl4?K~qKql>A9)G`rmCWNjScd=5B)6OtOuBx zbU`2)BIzNwV8~OVn7)Q&Q-qFqbPUAl=cYhmj*))cvt6nfRs8nAD%1S=c zB56QR_s@^`^bOSTho+U8*PL}A)41(iX-gnKZ@zwrPuubVJ%Bb^D1VxZ2{jhBfJ`L2 zV2;|Ff(}(Tw5w318Et@Ste`bA%Ae}foz|SaXj@^LqL@V5vei2jzk6!^hza1HHLA<*fC)VEks3*LCrEKwTx7} zUq`Q;dGYq3zMU$tFhp7kW2V6e-2^rs1c_tQ{`9eySslKGhI zOToIZmIJ;Hx)Bj= z!whU(fjemi($03w!2T!e0l(Nr3d~>pwKhtj2Z;37X|VhHAKx})MI8}gSvNT1rslNW zr~qzP>+iG-NjG?c@F;9Xks8ct)>f=X31$Oy`t>N!PUM#5GA!*6Pa~^ma+GLq?~ma8 z8l(6hNxS-Dc+TIr;TW8B%gI4Bjmq;nOb_Bf36@UoYO~ugU9nd5<5b@zFx4o9g_!TZ zTmDayb)Ntw2G`29Dz(Mhm-ZTby1LXD5x~I{c!&9co4PDcj=#h0G_+`2CK}N&&5gTb zu)(J!xlj*=sowl{2$*d^U*To8re4D?;Dr)Vm4gURWt2{@kLEg85~>fx;&RwR4ga#q>KU6$5#wMq1CgP+KU-yoZN2}k%#0?1S9_3+ zA<7(}{OhA=UGlGz{a;nh=HwdnqStS{u8R8r`3ySGkNN<;mpuTo9^Iu}U8vD1r6*H< zv#yl)h}zP_!`7&to~WLltU5|D>(r)p^nk>A|Nr#KgdRTg0FM450cW(=RBkY<5z) zOs#LQaWhZ=DOD>kv?-m%iueu!w;_g(&ROsOeH&NZG+%$Cacg)4AZ|$YI{5vFqoJUe z(FX86RzM@U!=L)^&)xIU*p<#v151X^$5_Ev`IzFu+LpW~@cN)Y5yH+v0f#!U1>>r% z;|e>qjRTazBv#G4sg&=L3dV15G|w$k%APMjpL`$reUZuj48JTCg)`^^yXB0M1|57k zepDdrVwV^oIhdzP<->j+z`wky(b+d)#Hbg>+KXd_B9QXMJbR;1a`~VQpgnT08U`Qt-nB`HIWTW#5uLfWNg@^v zxzoR`Lw0p#Mi%Hjkf87_BS8%({^Q@_IADIf3Iy1R|+rTwIWvb92SCp2_Dg!uMto z4x{{ zLE%#T-N55&EI;jcsM3cI{L>7T;hOr|*JRboWozYaKf0$!>X`*r0(~+X^$tmv zkIr9awnNovg(#XxIXE(Smth>3(_^gsH&6-T)4{a=@0PP=^y2`QyB^_U&j1)<|KszD z87Xfr+*NHelNw7{2s;Bu6`rF%`P$&^pJj9hk6rieM?WzP4wc8}M>q$2qeTyylk0F1 zr)kmqZk`tOY+H>XTMm;&@t-|RadB|BwhZN5Y}C)7jM##rPIlS?LY1vR?NZXsz<+Ko zGPD_l`-odDKZ0_`FzKd0QsYB(j`&Bt?J2Kb-^E@5RIhR1wcF^udU=7N5Vl#&fA?NF zJ-KJ27%38!uLv%c=|!9dGYA&T>wJgM9_`cYivUu+Fv|Ad;`N86q4K@`4|r&G(HK?i5m!RV*ms zvO~P1nq@=x53dgiHDzu~0h*e2nH2rO?};wTqu;Hgqf!Mnp12LBxmfOHB}+m~fCg^s zto*D0G?f>s$|L%4&T`&B;^7LTHv*WB!z-T{?K)93PP9UrKP{vuhQ@$|!9B_6!wjPx zN5|0^XfM-MUo&W-a)r`lG*FtieZyVMn>}5NZJNHcx2&-OxGV19x7bDaF@ps7jhDEAJWJ6r7Gn6aHUt8*U2tYA zT?SrMKK`i>Lr?q}{Fr#~nQ=308Dh7OJd3s|$rn`zk86`d-xuZdQ-ePg%d+glN3tcH zsz-|nTdoI@>l3Kbll0-IiW1WbyNz2TmDXKYqna)ZZkDJ~ukq>SEt#2mQ4E9)_KGkR zZ0ozc>*H_RkoskD$F(YSulD%QQt%MH_lC(?x9G8ug|2XjLuY+Z?-zHDmLJo@O1Dwq z(5e;o+QZa;S*~FQ)bso(;8M*{L%w5FNEp70Ys9GEQK0=sHbzjRS8W`jy$%hqZF{&( zF6^v%+zy*I-It_2c-mZf=EWUR>WcsL_~|0tq>MiA)t$AaTu;wcO-^p~Eq$LC-OJBX z*0rR+rD_yBraq`+Wo^I6Pf>JyM7BM=()Wol0sddHuWcX8*_xgKy&I-NFF-oM?eLim zwABkbYXNTdZDK&9kS)u)5TL(Pfyn^fs+Ai*1D^)K3L|1^L+XQX^;jYw9=rSHQy*@n zT(#~cX}l_9E8JedEVRc0<}9GWzqx>R7$!tB2&Gv-ZLGukz-mA6-CDpd3rO&8TtM4m zXXUhj#K8Ij&iew+6GjpjaK2i=`PKr?m$rcOWxas&r7z(8*aB*wpQ9c!PQn7}j^k+y z*#B10-0C&}Tz ze}oJW&JbRd!2weK+n1Dg2z?!L;XaV^-B!8(GpRlx;9w6xZxQD26#{^V;gy8a<4rr$qY&UjOqUFGd>20&5 zUN-9$-o_?@L{-1MQFD`g=)>mp`Dj6!-jPtDSrz8VnxwWRGqJ-SJjKw}F0&q{ zu}#>GckKyMD#hOhzyA%#<1rDF)3Ssx!J_|wR|dv2H(=~*9=AcV|C&J=!8eo>VqN=Ob7jhkOo z)zjIBW(U4HgAYl?9cHa8770>dAI_wZ3p2=sh_?n_>qg%RyKYe*NH?z=yeApr-%w86M0)XL8| zK%>qz&I6&!yHz64fP16Lw|+`!c6uQFVTbg=q(TZ=7LmtYIFTwIcHw$+PI09_X`$i~ zwZbunQ_dA@ zC}Kxr?1QevKCmpEeT-4fFJ{t@om(7PuPy9fy<4Q{;_Zh6DY`rfIKdI`8pL<&9D+%r zZfW6awif%!J9N;LXRKg_8`c%>m_uq6sV`rVtXk9MN5)_^&XJ3h4V9k|tW9CBC0|(j zwxkog+t=!|M4iEqfo(T{Fj32a((nIi8W{_0q;gQa;}Zg(&+4|Z zSvB#xlHJU}RpcrK!R43{+#C`XwoYNSqL}ZG=U20c9ks;0tKf+8SS^b7#`INjqLn3% zYVD3X5^7qjK-L!ClyMrn~Dd@tsrjex$|jt?b}mw9<@%?)XWxgag_6_=WN5 zMJ~G($QZw0v)R&04?boc)&o&P+8jDR5>F80kr2D(E$^Ziu@CtT{Y~sEAxBz@<-k|BOB&Y-od{l9Jp>uR-%lVBF z+|0(`6a%vYS^TZ|9VM3zmmNcf=ERgP=H9OnQu8&6kS^aDo>6t{$i6)S zD9)(xmX+}FM^tO`WFb^itTeT`O5Bxhq{!2UIp~&7A11f)!3ic8c_IL8bHDQ&9s*nf zfl4gSH}J`Tdli^NKlgTZZ>g(CmpA15tveM{)pSB*QF^-?IgHX+)M{B3VpM9tSjnov zYH57UcH>(!RuDRh;(fe&W$y>y=vLzYjV8jHXtO_C^UWh6ROl@lPT@7U0|NbOl{cli zQ!j|dO!~o38hb_Wc5d06PSDubrfclaq_k?GC>X;3E0xw)5tjC$1J(yeR{w^M&Z#vg z*?N(lX3H9JV=Q-ad9j^?io51$+E#JHs*iac8ms=qG*0{VRmWB+CUlfdS3UA6m|_5W zRC*&4cyh#+hWDe4;x1I2wj&p0&HHU9ssA=H!ECMVya}%jl(~2AQ1J4Ye7^o*S$gS<@`t!pv*DDJlF)wFuGy7x zxHU?S6=6&J?xvkI_Co*gyH*`H{J9bb22?4oQlRBYluw|oxHjsde&9DOI0JDJ9>I?5 zv5kCA(lv+j;Jo%?jLC6rqyIKa-!Vr!2b1rWT3Aop-7OoL%a5hGZbYt#MUuf~u88es zwR#0-8~;RF^c3%D{pt=VUpHWe*hT7ImaNnmKVyRP>OX|@dz-9sZM; z*p_5*r8m`K+UP9D_DppC)-j8tMF^YLe1GLTVZY~bx6SG?$8pA#rhnVCz2MiIO@-4t z|1nWv6A!r>DoBbScLGHLcbB1kQv;p8{G?~pZs^U{qr(02$seVwmHstx3Y#y)QxO6u zGrK$L*_B&O=bOT~5F1T0uCTUzx9o$J{tq_S>4v}!oOIYZ+hmYwNun)h_2|CzM%Fw2zu8VbS)fQq`5?Fo*@WK>HU z8J_djiZeq3<$V(i`yR2#Z_Ok2R!b4&KxFHRk9x3O8CrdZDxcqok7{dUA5A$f7e~|D z?yktk5o@N1Y)QD<(A=EHCZcjoI<`Y{fDIuz<7|!VlWIqb?h2h`h(F<6qJj%ReYg!5 zsO1BK3vtQg_#J@ysyd^*Ju(EB!<&-YjOH$h&0#{`-ENM35@R&*w@{f5Ogz^qtfO(l zI_2`nE5mrNh?TiP_E@_EJPl(V(B)VMbUD@mU7BdFyS!|y%L=~W-2?3|sXW$YM2B(; zd~a=6J`wmfm+PUEZ|=JyG$XC~%0#FI4@8_}l;C#+B#U!Aw@F%2H4xWI!$L<*D{dZ1 zTWDg+=i4(mHJI|+IJbyGVQyjlgGX|Usopa-)e9S3xzd8~p5dgg_eVkD)&|2iBAPtZaG14w^(cgAB$lZ$ zkm$Rtjgn4qF4if%3BzT{tfE8M#{cbL(oP_v1$m~NLgJq z1g%nDl;1Sx%%Mv9=4`(+mqyBqR}DcMDd(&jf;LjlT{Q%4q@2HM2--;bwpByWD&<@9 zHD`N`l#5mkK^rNrSv3T0q`Yp`5VVnU$*Lh}BjwUnLr~{ig@qMHKDvh+%CEyE!scj* z3i@SN-pIJWopE24aozQ;8vouij-}xipe^nyd73Z#!IMbj$hWb(k({0UWVj6)aw8dQ zKwi4e;C;Hlq2GT!j)n{eljt^lM~`n;>a(Qra)sZ=2W9ckl&}j)?7obctDCC{sitj< z+)Oydl`2|amvHqjXecAtP0qkIg2evOFg#*3DksxL+3)I9LAAE~aaqbirr4S8%vhZ$ zu+*)o(54t@p5<5lgG2c`?opi{h}5Z#!Hl47zn;uIoa&>z`B=40=S@{sO4!TO4XgHH zA@o*UoAR0RqnJW^vtd$zja&-~SA45R!TlH9XqB!HzVHwWq0`+e6E57h;){jwms!F z@XI}oh8}7+)D3N1wywa|^3iw`R_0y~`+#O`j0-R! zo?izvt_w$r%KLsP1~#yrKt}bx!q+5v-SVC)|CL}l1!4lZI>n~N?vbo>0wB(<)7#Cr zYBwKiH)1W6i8QtArWE0ij>d|BXY%0t$H6abI$S8y8GK165g1xftlMs-sYu)J|8&kV zkrP3^$F~Rkup~>-4$zIuc|?HS!%mH{n%F(@8tJYuh--ocWxlhd`RkA~6un#Vi593> z-mlVxZ4}(-E@}$mKVTb#WSz&(Dk`NubfC==?sC(QDie9V!6k@r1U+qBb@+;xq`NIR zD6#eLaAKyW2kyGlR|<6TC9w_3a8U<nM`D2si zlLoi7PA{5B2;GHHuIM+2(JL_uYnx|K?(z0RD@G=v{kVG@8+^OMavMY5A(}*JV9ldi zbl{RPKtoc5Z*p)pDFWP}RQ4s$Dcc)7CQekv*KS9CXXWQ_cA*H<10~>nEn1j?MvWmf z@#y9@X7n3=vdV@HP{U6)<`u)?GUgS-H+7xNF92W*S01|m;2n$u)H{x@nlPCE z=ws6tZ;aA(&et zK~kg_siXh5s|`L}=+c+YiXL|v#Yxj;16$|+m1dQzyh`-5n`~|(?CdJhMOq}^oFz>+ z(v&J;V9{$`B;Ufo8h)x+dDE2=&Equ;)R8EXATbLa#fkWv#QAy052%@#RRdlEaxZ8Ic zCQOj~hwrEAbaFq7^E?XF-2}#`=UC4J4&t*LQ;NGA&PWH3DFnI2F8bdj^0xIDe9Bl4 z6g~|CM1eZy7|$=SyPK9)`i-51aa`EZKFzQB&`(Sl{QAjM{*+h#52pw((WJ~==g4%h z&ZQNMTjx=eBC8VTsf+XJ=r@6XAHeVDaYg({c7iSrUl{8ze? zq%^k|tlAchfUHXGaNQu(ZI}pNeQfEyhp2dmO7}%wv8k~P0YGIHO&kn9k>f05D$(E% zT0B|?#pcKTo3C66d3l$HDW)Met`|isVW{%b*a2!v@mS45<`HFkgMTSGRr5SEBU>e-VL5i@ z5DC7=+wV<`|I^MLyE}sC69!M4z|d|siqkksH|BHMdNmpVt}ukP#uKV59<&!!-mLf^ z)7U!YUDY$$J^Wa5#sX{yTZFj*GJ?O?-5M!;k%#!Yb?$u+Cs_GelIP~diSE}Ji(A!F z@bPq?KA$37vg2ONShsP+?PEMq5dm6j*d2UHR7+6oF2=c}wKh$;HGLd3VQSpo!GBmu zDBI5PO@xYvMRL#;B^b@GoFs?nnYkeg4r~z!!uJmig?yF9jO0LmkvIv^I2QaV-W{sB z4WlVcWDerUh}^d_2TcwWuKGRNKyXS8gT^@$bku5Si1=DN2m^Gn--gWFyN&Cm;N=kt zfhmZsy9TWWr!WI&$|uAO(wZ4qTwPFc(;y+*k{Bi+Uvb0%9-Fd3OdzY70CJ+i1Z>|2 z#2}SY<4i!QQ<*@kq%i?davBq`_QeDYP~~q#;tz1EAc~VUFkdXP9ICDf98kEb!(A?h zzU}Reh(%%!n^EzM70Sc%7{i0g88846ebs=vP&QmO3@(KD010%5I=dqyq0?_z`Xy9c|&T}qOzQ(|3!vh zk!2haj<@)z59e~nQ@!@w-Z&{^Q;j*wSjP!aqb8VuY%N;eA(Kx{Al4&UYb-xpbgNMX zCND^zIFmQ!{zRC((OfdiZO~%&=d^6p7TYMpLJi(72YdOOPPv;^2u_uD1-8f|Gt#Y{ z56qXJ@s>E)_&ff@ZU6BOxS@s03h!Cu`r0zq8!Q3tQ9yH$n78}1VF<$O`6;<$!}ATk z(X!UfwQk|^GtPDhZ>$|%e+8={R$Va(T?dsq?=$|S8)6!#4&@r`_>Ekqe?&-$ql#@~Nr{tm%G*L{f}xSKRucG`&H(besE$Ak5-w#JBbNjs4}mA_e9Mo}nV*{+?O#-xPfce2WtI7X zcTP;@ud2+Sp3Hoz%KWv-%;Qz&qm!9msWRU(iG5$KGT%J8DjSkncG22LCTqUA%6!ix zgs!bJe`+%GEmh{DlYHvBD)ZBm2zGsy`Q^#Xw^o_APEO@*Rpx(~?DL%t1bE}S{0VXU zu=r~os&<3dUm5c^f7;AESHr*d&Zoq^VUySs=TlD#&#(0pavJ{VlkRqG^h zd-Z?boXb-^rZD`TYwKp-H@%t7M>9V5 z!45%ivv)cPn;)7!nw?JS{oc&?*FLH$5UBi^!ZPBWH#!Qp$yMRTn?+UT&WieAdo-2* z>t`s$g7>RlFR85fiif*z^&{3KoJ9Mtthw=adyk1N=TSeKcP? z@N=?>BL;p?P9O0!_&qZ#?u?`{;zz#LN9^3cG2(l-KjJ?~iJq!trt^luBifjVj&ZaA z^iI6u`0y&X%l4cu`f@~Yy5zOf#lIY}J*SJx&UCs=cW`v!CC2Mwwlhjt2>SGoIv4+W z`@)2AwqT*Rol`YLmTa2B87GJs(oBK1SE4= zi+MZkibD6(>lzljikirJ+gxBMkB6|yc9<0zn}=9YU@W|Nrf$MrXhzi!iZ0ZQElIOaz}Xm;f#NcshqU01am=%#$vR5ws*V3ZPZP#P;z{9Za@? zYyH3IRW5r;;%00@ID9saR3^L$(2IDLt@$5^<)p((LS7D5ROIqy`mjW5E>eE!>)H{t6#QTJd2q}uuZn44Li^^(*r2PUuvocKKsQ z$AK95#0bdE+1?n)&zFR!?ai+(^5*d__=*o6mRah1Aii#?Kc^bX~qmP$B z4=ipPb9jxjAe5%(&-M-HUe1RTiaEiit7ATP**LTkAAz*`VLN!;FCOBOPgN&SS ziWQyu)U9X;plsEQA7B|@(?AhXV}eow#9xwf-huf|1M80mP)h74~#8>+HT6x2*P2Y)qu?t+@H3kw0x}_3V+{Z~JjaPL0t9>X&9Z0Zs zbS<<`nQwhM59^0Gkxd|a%HY}EAv`PTAih?edx(Gw_6%PU*$y{;e@F4x4wT4x{H9X1K>MT1}#Xm92$-Cfw=bOf0zX`EaUG=)o=xx`3mIUgD)! z(YhMzv;3s%2HpiLD-030GiK^Dnu!COPlraD7!q3<$B@m#2tya+FbP-|4whB)Nc>Eb z9>ZR&2Mq*z^i5fqkM`wtEV03PU==ZRTbxI){z0+UhVgX8$0)Y{*I6XBFkv&1WQ*~2 zk)#imb+^MS3^km<{(mKsBGJ|&>4&~9k}6HeuwuGMih$dhNV=ul5=nfoEefb>Dt$Mw z(}pLhN@DKK zOO=pC2)c&Dq5c|%*(^n9M*!SHChnf9!8h#k-3`TMd=-LByxarmS~BsPsK*nv=<{@$ z$kkrbQC%ixCnFPQoe?xF|DDB_on}xCT6?$>#DO@ji&l-g9#W(6GiJ86kZ)2(R?|Rz z2zU{&ty9`VTWU)Am}2tT!nR9B>0u_{?yXI}g|?DCVe-`oQMDXQzAU23X)yV~uwW&g zn8{b+!xWQmrp>q6nglCw#yYfZ#7LWEb#lJ85yvd-2^+BnciTn`^yda~CL0mueMdIp z&Wyy!GHQu@*9l4Fh|~ecqq8Eg(AgZdiSLBt`Zi9rKrK78T5G5Mne3OfYg!rOcIYOn z)+UjYShKmEuGw^{9~Wna)UN>2M*bh0Ye{{5vnnjZ)#FmX@d1ReaF@64X*laT?dY*R z?76cfaH#v>X;A`BXhh|mTk8bVwTqw=#F+Ynb+V;! z-~>f3SmyoymzG*;h(S3JQ@DpL*4vabRh>9zs>$pb(@I+Czb&mKAo$i=NrVUe}OgK#w|mzuP+Q<1wfJt;D^T2K0&6Vj6+nK^K)kftrg$`16Tpo&GwHRisb zEoGWyslXhQRuvL#rkPb3>iln}gxW$g+XPYCgnbfdGQVRqnXZ~ee3+q{RS;>@?1$#1 znmOaUY+@7OvX-ohSK5S+s6~Zjd#c#Or$rSz6$31PVr$Lp@-`sa-kJ!A=mxsJrJ}kR zk!W&UoNalu6tyv3u&t=Ym53BIrVGxdsGzs`dXKrF!m!5#W*qix5@HLb)&(b&zf-Y7 zTj+xOw$cTgmjaICVbBFHouUg8#TE9P+a4)GS8H9cb27RhmY*#}O~a42mKoVnxo=X-9J321)Q1`k+FE8{J+5WSr?j-ZWA$NYYG&k@wVL@C zC!}V^g>~qj7Bw?+jL^l?pk_uM5_+uMU)#_+EB3JPUR`g3m!5Nxu1%sAm`)_--VteU?VtZ*z@SYXFF5pWLwW|}- zb00k|dhTf$Z~2p3tG#2&+fLNp2-En*<+zAD(}KtJ?oGAe*kiCq#`W%PD#b_In9){> zV;50}7}LAA)RCv^-2wS#=-myHPRs5liuP$hkuCJ@Vk^D7XzT=!(?w8&-Y`Y){(-3J zjQL=@O})E&GI}?5{U&;M{{v?{lZtnXF1Mw42iiJCig%FIr%mw=M6Rv2U zD{C=@8~!3E2x59r8lc(=Jc1Icnh0q&bZwWc6mo?$7h9|POKnLy;rp%8ylOf4e!GzX zPJ^ls-JF!FzXj>+MAxs-w$`e5sOwj#TDNf0x_*V8b(^)WACc?Sp=905G&Bskfmud| zTNaZR#h76^p|{o8*0v}DQ+11?D~n>+&h@sPnG{hJ)F#E-r8HGX=(igN9`VN)<+PX- z5y3(iPlHJj(J%D)^qUlsS%v{re&Z(Zl(^MR0N{^d`QEWmTZBBd= zw80HUJGE)*>l|A~O(cRDMok5TmQnMCh1#fj!-P@uhL%=yR{TJkFG*BgcZb)Y*q)G$ z^TcVfaZdm6%e%HVdB)V}lQ4PW0tAScam9CL0gahpJF$S`0A`qA+cb#AOt4K2qS#|p zyaM~&_8x-UM`I>f+dhh2%rLi*w$Jes^LBRz?J+{ zdw5{uBYyux7!KEH1k3HD&bW`6Q^B6wB8IN~sjUsyF{^1)!?nCI%x!13=$l$PdklMv zM$|3sHn(YB66tWuM;*|C+^&kfIJR%OsWwg&p_vl`^cLn8UYX6mEYdu6FpfV#hE6+m z&wENICq_qwL$w0DL!+a@o4SRQHaaR?soSiLjv7DOYI$T!)6O%TXr$TX zd4|&+X%_iqt(1S^gd)x2!Uj3eX^WHD;nzDj&=6NXbn!GO2B5 zP_J%!Dt~%wopVefZ0nrmm_j(4@>&NUwp0kWR4lj98v_Y#4+>i-gqVh#D}>F^2)zi>ioT3mzEsiuWRIyp6MCk$`4vto0lX%o!YLTRcgxvex!;>G-q z-Rjd1nnnbep)*w?prteQ|7-g)O2{oLP4$&YVV!n*8D-QnPOX+SrrX5p#me_LZ^a$I zjMDv(TdFWyszR>9%+z!$KsEQ!E6r^Sodum|)QQYzw_)G9%(RMhLxRtX|8PP^6lL~rbxyw#cA(Vgw6?&wT%NV;tMssfL8uZL##3J$z>vv~F!Q z?}X1`y#CA%UscubwNGVk+FYdqjgS8nH}^Mtb`k%^7whYb{WlPm|4~I~OYPIpJE6PE zT{}*9msPC~+Q$@5qBBf3W1(RSz2<5^P<6Ju9T0Nr`o_mTz3(4PtIqeV-cYktMWeKW zQ%>Djs<4c4pntF)%f8jOH^=gH4UH2a)4}wGymcXE<2wQqUq-lU;+RDhpI~iQ(F>>6 z`iz~FKeL$^-a$UonhXLvwzY*_h}7ELF64}5^+k#pvk_+!0qOU}_AhONGz4zO zWzB)3xH?$dDIPkm2 zB}5GRJ|VuxF{W99=Ei6&mY1}<52t_kh3-$`X!v62tkHb98qMq5qY3ARi!hqgH@Lak zgZuGnaIb3*&g}gI*=iWv(>B)m*<<}T)mUHK9;^8S4rKeoSf8n(*EfWgZ_g`CE^@bt73H{M>KzlJx&}njSribTS5qM(L_O z7O8z}H&pojUwIo9igfVvUS%UqGp@1aOAAka^{Zcn|UwG4emAG!RTrBdzFSMHP&}V;97OL_=r~LtWRjRL+r@2Zr2mv!%YUiqE1HX zcWEsE#Ha&MS%LeL^@GWI_KnH&*N-nHWB-ljjx%D)?O!j#qy6q7DScV;3jG|&{vJT! zXE$$04`hWvav91N#; zlE;8#C$!8$2pnC$o2=it_2Imr3(T&vgq~mw#5#g8K-IX*5p?W7u=X4+=sCCSOJ1!nelv@5+*tmE&;_ zFy&`ekn_i)etdBgo|M|hyI7oRycn8Nn_z$^s9u$%oY3xtHfz>QA9e4P$13dZ_ODOX z7{D@m7S4fgq(C>Tql5*6mJVcl_yOtzkq9aPZ{(j3;jO4=o_AY<=!us>k%gx{B~KK# zHlQS`zbrYx4~?l!um!qV?e~97!#Ldofp2ax5V3W>$~DroVGKs0ZSK+UKc2z2HO-!A zvi?(an7sfw;ywj_M38eTr?d-}^Ce*4EfN-}S!(c@n6}o3lF-|Q%ZxHCa~SVF0gh%M zA*=1phl*NyUjm@6wkf$=&Cp^l4hQtLW`!Ej>|AFkqN;ns8E)K*s{iLW5mKJQ#IQHA>?$;y8-9!m>EKKN+13dQJB%A)9 zr$|_}(t>ymZ{$pXw@p978&2MYHw=SPCjjrUiaUXKfQ7)`0*SA|ETBYS_OH#ViO)Hr z72SY7#hg!Bu%D~3%90y%6qNt2_Xgv#B~a42)g+w8BUQ786{#aV12Uc?wxU(0A=p2y zc#C^RiRc@kONZJc>Z|Bp?nRc@zbV1!6F8~=1<=Ri%8Be`^&_NUud|}531v@{iQSz6tAFx zm=(=8`+&0Z-|* zOr(aSiTZWZLvOvj{BZfukAL>ZyKfvpDb^m>+HHKCb{_l+tzEnf zn;K@#q(kL@CRtrti38b#q3Q5?o5qMRrM+0iHbGS3e#LPCwcUH4@JVHsXG!mIrr$Zl-E-Vk2x z_ds@Y`}L;qYQG1vTidUu=D82F3tK9=_j~SVLT)H*spLNBxetfjP}ow*eaLe^A96!sOC|Ra&wVW9 zhQgLg?xUXjM92+=EtTBIJ@=`Q8wy)0xlelTb${#&8VXw~xf@DmK|^jRY^mhl;JG)4 z+)&t3$-T*QZwC(g)Nob+dcR0kQ)kHD!F%g?!6&5 z6t>hl_nwezETMdpbBaUd%HdIGeS~Db-SHhYuXCup2oC|6sU&HBWr}m46R7Na)=P9< zF&o(3lOiebP$gaWO3KI5S43`jlhQHj21Qand%b)-Kg>h_;=Q9znO`~L|D?WsMN*Bc$d8mj;RvHmisaB0 zhc9Jp_Ii(sucP8ZDE27DlxBLP`FenPYk>0_*%IT#lg9vMb@`xpS|80bVojYzV6-+i zisV@DfIM5PhB)dnI;Q`o!vRP`zLK;*`?v-%%mq%pI{15KO3D1nBctwNgIcfXGHJ^! z=FB>kqJ%mr@UiaX>t_i#*;sQkE~U%}n81LcTTeVPE`u2mRF5}n03$$`7RjZ$v+bDB z&el!(CgWvhLmC{SzT^y3Jr7Ln;$gRHqQcQoC<9l%H3i}~}BZtcGSRe9v4zht%R5^-%8=CZw7NEbHgdT;!zz&28tiY&KczSdlHMtHHg zcp|864Tf_-9CYY9Cd}&rYGNQ-3<3$XuDP(#FcR=-n)4Auco2rnU*L)37_#6PLaBfu z^ICnmZq!7;ka=N1SEKFL7y>r7FvQ;57}BHhYG4eaW7=AaUI8jJKUWScON3{$D2;io zk8tl8$%z00UjUkT1LbHl_GWxcs34>a!>hFv_UVdqnFj5#aIj8Ry7-lA!-q5yh*Tq0wb8`hqXioCR5tH?n?Ml^MX zxsd_900zHa{;IToTy2NNOd&Sla?XKl;|V&iCVIbyBE$@=)f7ar9N=BdF?*mbXT5ujy%~}!&&2g87s}HJEze;l^-5Fxhe-~CYK3v6+Cq=!*DsKrB*usvYiZ8; zp&Gi)IJPy!OkQo16~DK1CN4G_)oGHWWpR(H{f)67fP&7{GsxHXO+q&bQ>nt!HPhW>y{ZxFUDv2lqBil(E=(iEuc_#bAWq%X+BAk z=3m>nGc6nturWC5N(;}51r|WsxEfZ?63`&Hc-IiW?Yp}e=p?kG>d?VLLu7E&9zf3i@GweWK6}uxw*mKWRV;hK~{;DvFI@} z%keQV9%+tyG)8G5&!aV&4VWl08vq)ZEz6;pAMt3G1Ev)k1jc|&B5D3w-T7b{jI_Tu zn%8omqPtG24*E=#b*D;>m5_Tp0WE4%NwDzYNULXRVB9d_UNx(r>CRXBZFgM-M6rSF zsUOr+Q%7mbxPddAz&WJ1MwX?H!ZJ$%3nsVgsU710RIL<5vw?&RtQ%zA^XAFsH)aPa7(lu00~$_a@%V7whZ_!R9v0`d)LOrLOCdR7Yi60 z7%6*w!tz20j|zx?k9rBFhz7>g2HyG}vr&TGVi~(*hLK}lt_Yb~grakWd@iyTcpWnY z%+{%Z!&Hs4R;&dtgjSYO`tQ^cL2Z_uFaqJ>KXlfk z7*=!WGg!@e`9hkWK_gasU(ubUkJGFq$E#+}kEX1RYEg)#+F-;j0m~jAQved~ zBQau%T^9_V-IK;r8Y)wULhuFN~=6rOB%~!aIOGGOm9)&N+$*3n<(Fz%D z>BpRRC7h%(wM82?5^+>5igtlHBx##cMbdw7FP+zxR?ueTf6M|QrX;2&mo-U(sz%*I z!g2+-lb_2({)MgYd@<_oB*SDu0BCh_X-C8(+c{A^vD*9rhr zL#zyuKKbFedv1KRHy zx&}cj64%yL8q2YBuX5_p$F$ocsXFGU3oQ(krs$vAnYU1+Xc^|rBV30{w47PK!gr`3 znp_ZpX}U-u2G@&>oiMmIHL-VUjNOJsL*tBH#aq=t{8V#3sT?w&5V9)G&phINr@ADG`Ln`oKd?eEh5EOqv{^%m%_`?RF58QsUcD=wM-`pP;$58 z8R@Qaosu?CngRoB*D0!n(<9KZN|7GzoeH8ytP#;8`ho4!zg zp<)oAJwZ!Bg-*XUxGaNEM9+xpNL@{Q)M2SL;)1!iWC8dTtZ`*jvH!9t-6T?K9lpO8j=mrpc>Y%ENjtavJL3e^-400xh z<+Cs>&TIn1YB01hY}&d(pOIm>st_015Mvv1LkfROZorjh%MCC~!RE#iQ)ebrCvipk z{tm>3RVK#S_5G&UfLr<>P0R&{#)#ku+o16BC^)cEWq5)czT-1hYyeJt{P|kZt@Qm` zY=EsUHfS~K`>J3rimLgJ_E?D!=dWp*a2#mCz(5&RNtz>6IGkrR@Ict6b+E>SV}hFG3{|DR^*(exTYp}^}ewGJ#O%C<;Y-K*BmPFQ2@*z*RyJ%tku-S$(xbkT&D zc)wTiP}p+KcC#wOy5y(;!2qd(0WLqxFR=iOLM@LBTH+lskW{kBW!*+b(39AC*|{P- z9nz}WRuW);<+4wV;BlO3U5g!8ak-oLku+pmjoFC@BS5bxGgcmDUb;4NtulzsHxzfX z(!oO#%>`oy6o{iH_l*pkheFvFP}*Sz5;Km;nG5-0hRgCC8Xrh>zF2x!%G-L#T;@P)JHk?lRKn>mV4Ewty#$ zW}!tUf&3K^DPjjjA#Utj=YOJU77@^Y?@~GkCo58} zI58lDCY@34x^EtIU(%%eQpRY*%Srd8=Z5af^OC8~QTNT=SHBJ2m#VJ&QbpLtyEG0g zeZ|H!bzgFV#$iDt7B)ay(0$Ei9l{2r`?^*lm{5s!T_e%^gzjsgu65sv0K+1)`Prj4`>-8YeD;?)dk-M0(^MhJ*k1>Kio zAZ-mU%aHDC8CpaCV>lML3oT`B?kiPcLic4W0q_JpxPnNH44dn|)pcVx zSoZ)5iWmiUV+?OcO3)W*c1`;rqd(L5f8 ziKGSH*SsDlfQfKpiOz9!6NTE;UH5Hbm?7v+FpNRY#IS4@hQ*mpU|0=?Hii{7tyF`T zE)y7r>%Ni7f)e81;YyY6n-5bHxh%b0G_VrszNvne z7>zA7Ly5XCP19C%nWVT(2nxq#lDo?U9_TI;^P5w7Uy-=(3tNogcEgSnkw)m6FI!v+ zV3Z}v@X#Wn=F3nSNWwrMP}>he?&IsGA6zE6yG#Hfymn0Y#Ty`7iv1w4Rk|;wYTXz3 zyY4FqP;&fMG5D_Bse@p>!t;#bDqN$@GZ`uxL#KlDLq zU94PlXwo&xePN&qG8F!l+_dIS<+Q&GXo5=F;J=s?>8Yh`@n|O=ROQTYjz*J*(sIG1 zN01ZcIhV2LIhylyx}A@}GrgV-*aY1z9WE*>Ut_rJNhKr3!jVN4MIGp@zcfuoOD>R? zGJV@ zhq)Emod=Iy_wCo5mve5nP-4M^2kXEBkoc^$<1k-#kFeeE>tg^X$P#aP2QUquG<@NJ z3F~0Th|_ZZFp*!jj4W|aMvr*aaIqlF&exD`z60RBJQaiwR8KFdo?cizePi|Xoa$*; z^~6__Lo3JRkSrD%EGnU#{p_*JXHG(X1oO1y2ydRR(O;+_%N95SIU-Ie4B;;+fGu?t zD;H&45{jS;sZ#bCv|}m68`_3IKv6A#FmG|!LZ1152}D7p>Pyo(2r|8bi|!yumgty_ z^E#`r93@avMg#-3ei%CS7aj z49T(=F|JzKd$W*(!+b0!4>@9|u@2(}!g;Z)SSje4_Lq}XG9XDM3+CpN^!QSmBqY{< z8TU`5KxRSChXq-9yZA%Z-oj#kX?fR*H<0BN8!Z?7IlkQKsx7taf5~E!ECNScb*R;h zLk0UXNllKa&snG|?>uVZMgVh;HQYFs*xYkgmNA5>l<9B*763AeSV&JUgztzcXz3Ma z#Nr%MI7OhcUCcYICrf54Shu}6-f-0-R^kCuw1FlbDm^@B$biu~-q1a{aTZ2V`m z4AyQArQ#pLx98v}T)I8#>!ttqeRiZ4@cqX0#_JZZv%34eu3oGzwn2&N0=5#+B0Uq~ ze_YYW1^9J5$&=%KWXW84PFR=z&-b$a(LAooZRkx3`VUKkO5xkBc>lgz%%{>eKxL+F zVZk!pA>xL7S2f3VVss>v_krfjRDec+7unts-V9d7UsHg|>pCb~uB_wut5Ab3lrvfq zlaMwsT+Y@=GB=wmJ)=w zMJhusl|dF#VS!59DH~<}E-4ytLl<$&8fhQ>N2y2bLB~Z9Tg<N%u>^2h&Rz?T0BE*+||*wW6y{3TnXoCME>C7js8P)LwwJt3JzoB_rU9-nD*cDrain^|s2w==I-|+8#oEGf%gn zmTHxKMLA6)z`nM{Luj)jwTbW@)?7L+rz$>CK01FHR*=8|zaSQvQxm@{SlY!oF&S=C zC5z`(a;DS2A@8uQ@dI<$RJS8N!bLJ!V_ZOc@FmleopH(JG&M^YDsGbLPMaxeOKz5i zHj_}%8QzQXJ?G^Xi*Y>ZIBT`cHSmD(YrW6+a>aT1IV2P)X2yZ7^7$B*hSD3O?s@s8 zUh*736%yyq%U|b-`w?0papAoDA`-EsJ>{CKzazVx1nh!3;Sv%M=5@kr3Z&n8nQCSP z@%}v~a)j~Rh<_$4?}PX55w8+brR8;&_?cw=MVZ|>l%1Unz!Ry%qs4Mgig!wRbYDCQ z*Zm0hsD`=%+#}U>DM|nGrbUjqS*?MGF=#|NmdU|KiSz*<2Y;Y7Ig=#@u)R?pXWS8L zz$zu~#Q?6kT1fJJ7>b~zJXXH6WzxTDR)-ms!Tb&~`>G?`wJK?OZ1HVr#=F=4P1XH( zcqnSKb9T92KSl|u56ku*ZJIWCKv&N+Wu9S{zNsnc!StE1+yilDMb`g2Nw&r$z^?Cw zhW0s{vJQhkay%Acv3J&-P5%vCl28+7u=A}MDgp@B69&L&{>0kg{w^9Re}(?Zd;qU) z0L(!g3!)0#Anu~72bT6PpVkS$LI%hQj;sqBgmqQQcId1R{Z%PI~C=E(DH2C6daG#;2O9yX8b5%@Jez+e}uB}s^ZDn9TZ>iH( zNE=*NzlU1aPo%tcBE_z?X!T{6_q9^qUe~I6w_BFH)Hj3?aZ1f@CZ0&Wv98}J`_4M` zdEP=g__ClhcvqeCw_@9w=h4Tz>)aPiAA1BV0@T2b}r z8_PX*##fZNbftWMBDg);uzm|bfn1d$;`#FiE{o2hhd>)d9lw&TlF*(0S%$bE=AT+M z^C1|gfHcEc`ZwiyW+F4N3kl4QvoB`e4Lk#7;f?6v@Q%*l&#W;iGRz7$b2Wy}4AJS= z(q%3>*((U5lc!2_TIL#}Q=l}_Y2{3GW)hvWfh4fR^G8A2ZH#¬AhGMqH4RixQod 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%0Ag#nloohi9cHJ0{HyQ>^bS?QtVg5 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%0DoK`tDp%Vm}yQ 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

{ZtX}v7q4PBHO!EjXmm!j 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

U!`0sTwf}RMf;qV$~yuy8@VS^f!h}#XJn=% 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 klzsBKCsAfNyBBaMV!jJ$)K7p?ZM}arbRTIQQ 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 z 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¯6Xr((q~;uA$)-G+a%?OKG@@hUe1o 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

mNqxj6=qTBN}MTG|ANF} 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
09)z`Zj%szE|I;@7E9L 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
s8W_woG+Exf;lZt?1;3;E2i^=;Y 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 CjVOyP@k8+^X-iGXl3nkI5Rch}( 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 DOei2h literal 0 HcmV?d00001

{WEf%d*|6gD(Zp1l8U_2x&r&|Ls^Wx8zawQ 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 |QAn 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 z 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 b25UBrjWcU9>855|tK3;lPOgwnw9o%v6@>oZ literal 0 HcmV?d00001 diff --git a/public/todomvc.html b/public/todomvc.html new file mode 100644 index 0000000..c6078aa --- /dev/null +++ b/public/todomvc.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/public/todomvc.wasm b/public/todomvc.wasm new file mode 100755 index 0000000000000000000000000000000000000000..da34b5744a50327520c11265f3f024e5c66a72c7 GIT binary patch literal 3189472 zcmeFY1-Pu+c^co`3mrxCT9o0S$)U2eC6VNI~%~?K_Kthr@mkP8t^M8#F@RD`PFYB zpYmUQGX5Rb*?{;o=vUvhe&_91pUl6H`h9DH*6+oH=?sNXccXD+|t@LqP}za#Wr2l_qxZF2U(|BuQ}ZGPqC zmrn0a34Zx5fm4mYd)Msmob~t4-$?$QLZ38ruFS8# zf;zo8lhf-bNgFlgE-qLk0*nVbFUbO-P$U)%<^qHw1P_38 zwjg;RBpA!#I6FYjAs`3@hyXgV!1shjI14-uhsza<@e;fc&*KS!_|KPN|38f@Fc<`q ze)n@M`*-aa1^~bi05I4YXkf6+8E>#pj=|1^fI{&u04Nj+2SLCv_pw!Pmw;QW-pl@I{r-JJ^<3cx#wgRx)$802*A+?;{#9O?4T*O>#H+k3&; z0fDJt&ibbW0H|Rw6@;zPI>|bzyI=tT1l&p834N#FOh|wZ0n{VjeLHVWFhHDY01)ri z-tSa!-mu`b>8!oKj82~jh!c!7DIfqHz*%|67$9aR`rYLFW>7dKdar{aV2BF{1P42{ zb=D!y1#s#La7yZ|gTe260N5!!$T_!nzRo#;oOS1-fj-#+ImbZWO*&V{xoq#!IJr9y z;NIWwgQ3o`Ag41Z_I(;ou#-9nf+ns}*Pt1Ih28;zc7yjJ!TC;EL&G0u3zVZm4{))~lP=a)9#87R(Asx$my zV61Z`LC!#Q#t{hbYy&y(sBvx}8;fOkxVnA#;EHu|#tR7a>B#=mn0K2X7pybrU`{;N z#l_Xd`O^Y(7Fb9j!o>jkJ;v|<1NI-h{}XT~C-@x>dN00L{_r1y|LBh`e*}gBehS$B z{`U8svFL(?766sM2K=GBI~e86T>h`^{toa*?~YLaXY*eI{`ejLo>2c!%D)2q!{5Qw z<$Ve+f9M`hde6cWK4s5wpR(l^{(Iy6cUky0@4W_i-xVLQ-!uR3nu5Q}nj1gC%fHKl zpTsDb4h;S4Z~of(_#Ds$_2sue{`ME&e*L5OhX%=T=aZLz{pHs`{i(~d0QSS5f9i8N z{yt)}*ZJM%^s)8*)Q{BOk6Y^9kMy07%mm}j7aSSSB#>@@?D;4;`=KJ`qq64X#t&;h zTDCqmeAMX8$ses^A%(_ZvAKMaT&33P3`X0hxcI$a{>lsJ4)6qc0KEZ0Kwm&0&>s*C z3Q-R6AGvGP!0(c3$0$u}efVaRq;63mG_y{}!9s@4{;orLlxC1?b z-atQK0Py68LEmcwb^yD9eZT?W5O4%I4x9o`180D9z(wE^a0R#y+yd?Z_kf2$FOWCL z7t{jq0d)YH01bcyKpemy6ab0m)PlkQ?Vt`&GpGgB2xIMY?+CTw-D8K-y57ZB;15^OI0K=d$kRNCf&(uUHf_yxC@QYok1If7tkx{4fGEB2z`dW zLWe-^uu+gF%o~=c^@aJv0%5_hEl?P27ZeE_0Y}5e!Evx@a1v}5Tn1YJSHhOTHLx{s z9jp;H1DS-)LuO#}uoc)kY!h|>+lRG6Phe-T3s@B74wkQdffZ=o;ofjx_!uMz9s-|& zM8Koq3GjAc53m=Qrx^wg0+)dcz)9dda22=<+y<`yS;f~4zgZz+hKo8I)XbLn7ng`8+W}!P5Xdp;3UmQF0zH8qKptQ(a1=NY><^9rCxH{d>EJAIJG28j3Y~`j z{y+GGKm3P(^v8elAN|Mw$rpe6XW#or|LK4BkN@+3@=yQ#zxXfztN;4H`EUQb|NejY zAHV$S>%aK^Uw-q0k3anOpZ(R3{`$v1`RV`kv!DOspa0F@{)>P4KlcE70eygezyM$n zFa#I|i~vRfV}J?3G++)e4_E}O09FB;fGxldU>C3l*asW|jsYitQ@|PE9B=`+2HXO| zff2w+U=%PK7z2z2#sTAj3BW{PE3gwd3LFDY0B3<~zzyI&@BnxOTm_wgPC@6O8_+H2 z9`piw1G$5Jz<%Iha0oaI91e~F$AaU*Dd1FaCO8M22hIlOa1Xc-+z%cA4}pil8{jSQHh34j4?X}Nflt6^;0y2- z_!@i*z5_pipTTcn4~RF!4-x40=Xx*_HA7hma%4 z3FH)V2DyM-L9QV;kUPi|TRc02&Alf`&rFq0!J-XdE;ingC6L zra;r6>Cg;l7BmN%3(bcXK#QQo&{Aj_v=Ukct%lY@o1mT0E@%(54>|xHf{sAPpcBw3 z=nQljx&mE=u0uDWThMLj4s;K?4?Tb$LXV)w&=cq>^c;E#y@uXG@1YOSC+G|G4e9~& zg89JwU;(foSO_c>77mMmMZscVv9Nep0xS`h3`>Ef!qQ;runbrxEDM$m%Yo&>@?iO} z0$3re2v!U$ftA9_VHL0{ST(E`Ru5}{HNl!;EwENt8>}7H0qcZy!Mb5RuwGantRFT2 z8-xwPhG8SHQP>!495w-)f=$C_VRNtr*dlBRwhUW^t-&^6Td-}|4r~{;2Rnov!H!|4 zuyfcY>}( z1CNEr!QpTjTUm+&k2HT(vC3%`Tk!yn*}@F(~){006Be}lUtJP@7;FN8P3 z2jPqGL-->C5P^swL@*)*5sC;ygd-vlk%%ZnG$IBOi-<$SBN7mah$KWZA_b9(NJFF} zG7y=FEJQXU2a$`&L*ye05QT^$L@}ZSQHm%-lp`t-m53@tHKGPli>O1?BN`Bmh$cic zq6N{4XhXCkIuMq zBNh;gh$X}_Vg<2^SVOEMHV~VLEyOlr2eFITL+m3C5Qm5(#4+Loaf&!YoFgs}mxwFG zHR1+wi?~DFBOVZsh$qA|;sx=Fctf}&J&>MAFQhlp2kDFSM+P7RkwM5{WC$`88HNl; zMj#`RQOIay3^EoOhm1!iAQO>E$Yf*+G8LJIOh;xQGm%-yY-A2H7nz65M;0IpkwwU2 zWC^kqS%xe}Rv;^pRmf^&4YC$lhpb07ARCcQ$Yx{^7nO&~M-`w7QAMa?R0*mSRfZ}@RiG+SRj6uI4XPGZ zhpI<4pc+w4sAg0Psuk6SYDaaTI#FGyZd4Dd7uARAM-89`QA4O<)Cg)6HHI2TO`s-G zQ>baw3~ClNhnhz%pcYX}sAbd&Y8ADHT1Rc5Hc?xsZPX5G7qy4lM;)LJQAem_)CuYo zb%r`eU7#*eSEy^$4eAzkhq^~SpdL|AsAtp*>J{~daz}fhJ<(ohZ?q5E7ww1kM+cw- z(Lv~7bO<^W9fl4^N1!9oQRrxN3_2DahmJ=lpcBza=wx&XIu)IUPDf{;GtpV-Y;+Df z7oCUBM;D+A(M9NDbP2i?U4|}4SD-7=Rp@GT4Z0RxhptCApc~Om=w@^ax)t4qZbx^Z zJJDU}Zgda27u|>MM-QL}(L?BA^ay$sJ%%1fPoO8!Q|M{*40;wlhn`0-pcm0g=w4f+;+hrUNY zpdZms=x6i``W5|#cE@;NJTYDvZ;TJd7vqQV#{^&kF+rGMOb8|v6NU-LL|`H@QJ82< z3?>#6hl$4|U=lG&m}E=}CKZ#0NylVhGBH`0Y)lR&7n6s{#}r@+F-4eSObMnGQ-&$W zRA4GGRhVi_4W<@ThpERjU>Y$^m}X21rWMnMX~%S6Ix$_CKFr$3K}-g27;}If#f0I; zG2yrfTqG_E7mXXiOkf7FL)d9dE4B?gi&?;wVV5wM*cHqvb`7(K-N5*K+`=qi{q;MT zUCcJ-05ga?!ua4$FvplP%qivqbB?+Hc!NpA-eE?*=k@Uc%{fodT|4|KHQpq z2serw!;RxQbPM`beT04=GlN^gE#u~J3%EtxDsBaL`^64!7k7x;#~tB%F$cI4+&S(N zcaM9(UE}U>x41`~7v3B1hxf(%<9+af_+We}J{lj655dRd6Yz=nWPB1n1)qk`z-QsJ z@dfx&d=ROUYzQ_28;Om=#$yw(N!Vm;3N{s+ zhE2z2V6(AB*kWucwh~)~t;W`28?epT7HkK$6WfjL#r9!`v7^{A>;!fiJA<9W&SMv` zOW0-X3U(d4f!)FGV)wC!*dy#Q_5^!|J;z>PudvtH8|*Fi4ttM%z&>K1u+P{R>?`&S z>yGoldE&fq-Z)>JAI={afD6P0;ev4?xKLaSE*2MuOT;DNQgLaxbX+bjA6JAc#+BkK za8O;i-MD_-Fm3`jiJQjFFWKjUBUulP5-JHdnCN$?_g z6MP811V4g5A%GA_2qFX%LI|ORFhV#Xf)GiFB198n2(g4XLOdaXkVr@(Bok5ysf08_ zIw6CQNys8(6LJW-ggin%p@2|GC?XUSN(iNdGD10_f>24QB2*J<2(^SdLOr2@&`4+^ zG!t3~t%Np0JE4QnN$4VU6M6`}gg!z)VSq457$OW4MhK&XF~T@uf-p&#B1{uz2(yGa z!aQMtut-=UEE84;tAsVeI$?vbN!TK66LtuDgag7g;fRo{z93u?ZV3;B7s4CihTuu` zCWaAxiGIWwVgNCa7(}cfh7d!E{=`UPG%z+A?1+@NJXR)QaP!TR70vGRgoG=&7^ix z4{3-rLK-EFlO{>iq*>AeX^yl^S|M$dwuM`y9nukLiF8alB%P5iNLQqL(i6#@>_zq= z`;!C7!Q@bKI60D>L{27`kW0zs8pL{}YAw`j6$%o`V zQZzY++(k+w7m)MFx#WCu4mpFILarnqk=w{ER4(mZLAv`Shdt&=uLo1|UR9%-L+O1dOnlWs`2 zq&w0h>6!FGdL_M)yvcs#0CEsHgd9eWAjgs8$qD2{aw<8UoJr0iXOj!bMdV^~8M%U7 zMXn~-lIzKhB7;b1kJP=Ce##u> z`A>!@Gn7HfC}oV&^l_20LRqEEQ?@BPlnM1ZWs|Z&*{2**jwyYVbIJwfl5#`2quf&- zC?3=o$}8oK;!ho+Jbj#?OjDLAN0dj(DaDK0LTRIPP`W7Hlpe|eWtcKfnWRinW+@Al zCCVCQi?U1Eqa099C})%_$~EPd@|HJlnj zjig3Vqp2~}SZW+Ko|-^Sq$W|5sVUSYB{x%T1~B`)>9j)&D0iZ zFSU=_PaU8RQHQA`)KTgfb(}guoup1tSE%vyEov}*hq^~SpdL|As29{L>J9at`bd4D zzEQnsezXu;I4y>jM$4q-&6P?qdM&-4-b8Pu zx6{k$<@5%69o?ViLkpk<(t>Cav`|_sEs7RLOQglq5@<=ZWLh)5g?>ssq@Gc)skhVz z>J#;u>Q3{ZdDEikarAV04n3D%NYA6^(+lX4v=mwfEtQr{E2XW{c4%9)ZQ2HHleSJ< zqaDz8X-BkU+RMkFk9)Lz+9BK*l!>PhpZ1=GT4(X@107A=pKPb;Do(@JP% zv4EeRdKf)|9z#!|XVZ)5 zCG-k<6}^VuNN=Ne&^zf}^lo|&y_eoc@23yY2kArfVfqMtls-lur%%u)=~MJ+`V4)R zK1ZLYFVGk1OY~*>3VoHnMqj6I&^PH@^lkbMeV4vR-=`nY59vqrWBLjGlzv7(r(e)7 z=~wh?`VIY-en-EjKhPiPPxNQ{3;mV;Mt5g;FgzJv3~z=H!J59U`8=xm~qSmW)d@-naj*)7BY*O zrOXOu6|;`nz-(o|stYrzH-Jx?}CJUReI@0Cp5R zm7T`UU}v!l*d^>LZW%j^TfvUu*0DR-o$O)u9DAO<#9n7_vQOA|>?ig!dxA5?S>mj5 zt~kD2KdwJFh#Sm}=7w^^xKZ33ZV|Vb+rn+-c5x@T3*1HSJa>t^#$D&`aQCcTq-WE567s`v^Me?F}(Yyp+A}@uP%1h&A z^0Ih&yb4|wuZdC1tLHWGnt9!fZeA~Mkk`X#WX>_R7`u#p#tGw$am{#SBs1fg>C8-K zDzl7P#H?nPGhZ1m3@@e+(}Nkv^ks%IqnVM+8m2!hkX6JgXEm{!Ssknv));4+Gsl_X z%yObxF|2r2GAo0X!^&h8vT|7qoO#YNXPvXc+2p)&+_|qD53V=Ylk3F|;2v|&xo6xf z?lpIdv%%Ts>~VHDyPSQ_5$Aw&$T{Jha*jD?oD0r5=aO^7x#m1@?l||HXU+@fk@Lj4 z<&1DgxntZZ?l`xTHNl!;^|6LnqpU&J7;Bo9!cF8RaFe*n+&NY*w~RZ>T41fRD!GfS zHP!}eomIgt=eBWsxP#mQZa4RseZW3sAFoSI8)06f;T~rHnF0IirG6 z$*5v9Gg=s}j5bC)ql3}O7+?%BMi>)}DaH(AiLt_1V{9^<EJWTmju zSXr!mRxzuTRmrMm)v_8`ZLBUxgy2I%S=)&RG|%OV$BI)+_6c<<9nCd$PUQ-fSPXFWZkD$PQu$vqRXS>@apXJAxg_j%LTO zW7%=+cyz*_rHYb`Cq2oyX2+7qW}k#q3gcIlGcw#ja-8uxr`%>;`rt zyNTV*Zeh2w+t}^wE_OG&huzEWWB0QM*n{jL_6U2FJ;okqPp~K1Q|xK>411Qnz+Pl8 zvsc)w><#u7dz-z(-evEx_t`<5U`_}ploQ4Y=R|NKIZ>QwP7EiO6UT|?BybWrNt|R( z3MZA5#!2U7a56broNP`GCzq4Q$>$Vs3OPlbVonLClvBnj=TvYiIaQo$P7SA)Q^%?2 zG;kU@O`K*<3#XOS#%bqta5_0%oNi7Jrm>E{e^2025VVa^C=lrzqmJ# zZU{G=8^Mj_#&YAh@!V8y8aJJr!Oi4mbMv_Q+yZVPw}e~Dt>)HnYq@pYdTs-^k=w*= z=C*S?xSiZyZXdUwJH#F4PI9NYGu&D39Cw+!!QJF;b9cG>+(YgO_lA4Nz2`o1pSf>b zcb+HDi|5Pp;|1}8d11V8UJNgum&8lvrSmd)*}Pm{39pn_#w+Jl^J;i?yhdINua(!v zYv*_6q-;eLl58wy#gZRPx5Pm2>j33UA;79VK_|g0rek?zZAJ0$VC-Rf{ z$@~<4DnE^%&d=ay^0WBa{2YERKaZc!FW?vQi}=O-5`HPaj9<>L;8*gi_|^Oxel5R_ zU(avgH}aeK&HNUAE5D83&hOxN^1Jxm{2qQUzmMO~AK(x2hxo(%5&kHDj6cqw;7{_W z_|yCu{w#lvKhIy_FY=f8%lsAoDu0c?&fnl~^0)Zg{2l%-e~-VW2oMAc zf&{^W5J9LQOb{-J5JU>11kr*RL98H75HCm&BnpxQ$$}I?svu2}F31pM3bF**f*e7v zAWx7lC=e71iUh@i5<#h;Oi(VU5L61P1l58XL9L)pP%mf@Gzyvo&4Ly|tDsHLF6a<+ z3c3W{f*wJypij^*7!V8!h6KZc5y7ZnOfW8(5KIcD1k-{U!K`3TFfUjTEDDwc%Yqfb zs$fm9F4z!k3bq8>f*rxGU{A0wI1n5Pjs(Yo6TzwAOmHr^5L^nb1lNKa!L8s<@F2Js zJPMu!uL2KYyglrn#(wk{`UnGsp~7}ykT6^rDU24z2~&g_!u&r7SI-H=kwk!~RL1(AVbo z=l#MS;ec>ZI3yevjtEDEW5RLagm6+gC7c${2xo=!!Uf@?a7nlRUcpJeMLzF4X5@m~WM7g4NQJyGYR3Iu86^V*P zRiY+Qr>Id>FKQ5ViMmCtqBc>rs76#P>J{~i`a}bwLD7)tz_1|NQ0^+vMW>=;(Zk0p z(T(Ur^d@o_dx$;7USe;tkJwlIAbJ!nh{wf?Vn6Y#$X^^F4ipE87e$TYFmbpzMqDM1 z6i11p#qr_PsEqvaLJkYTznzE5#NfR#Lwa!$)ngq;wkZw_)7dG0g^yTh$K=HC5e`#NMa=k zl0-?8BumsCh5W%ZIqNrPlh)GTS0bVxcS-I88Ozhqc4 zCYg{-NoFKr(gOCzPx(pYJNG*Ox&O_yd#lchP*L&>pZU$P^~mljA%rDf7;X|1$T z+AQsmc1e4rz0z*!kaR>kDIJ&2N~2}*vP4;|Y+kw`U6QUy*QD#xE$Oy&PkJCdlAcJ< zq^Htr>8`}HU+mh|e z4rRNtJ=u}0L3trNk)6uUWP$QX^^NRKb}xIDy~y5V?s9Lrr`${KEBBN8%Y)@1@=$q{ zJVG8TkC!LPQ{<8I7tRU`2=`ToI*+Q6wso6e)@XMVcaAk)y~{ z6e{u+C5lo-l_FPBpeRygD{2(=iaJHHqCwH9XjZf;Iuvb+ZbgrxUoof{R*Wjf6_bit zMTxRNS)|NU&MRV-3Cbj8v~o?cq1aYzD)tlyiX+8|;!JU&xKi9G?i3G-Cq8bQndMiVeVaf<)lrlycr%Y7FD^rwd$_!IW=PYd(~@h^t>{v;AX$>ENH!!} zl5FXsbXmG8-IVS~3uKkDR#~~MLe?T{kYy@T73GQ|X|c3YS|zQMHb@7hW71*iw6tA1 zA?=r5Ngt&*(r4+t^hNq6^^gV1f@EQ`a9N5hUzRJIkya{N6zz&mMU$dSku2X*CVpVad*i{@W_7#_kYsIbNTyd(nSClCW!J+3#dqR+@q_q9{3?DEyGy(z-V#4akR(_VDhZQBNMa=Ml4MD$ zBu$bf$(H0w@+C!*N=cQZT2d!zk+e&?BmLu zOOvFj(oAWtG*4P6Es>T>E2K5jdTEoiMcOKDlXgn`qyy4X>6CO%x*4vM1TA%tP)Y50D4R!{p)eBzdYlQ=Ti&ljq9|wMVX>PQLU&|^eUzmGm1IIf?`pztawzsD&7=9%3NiIvQk;4tX9@2Yn64% zdS#=sN!hGyQMM{Ol|9OS<$!WfIiws>jw#2L6Us^Dv~o_lq+C_*Dfg8J%0uOm@>qGI zJXM}4&y^R-OXZdFT6v?qRo*G@l@H2C<&*MR`J#MPzA4>R9x6|jm&#k^qw-bxsr*#| zsz6ncDp(bw3RQ)v!c`HfNL7?7S{0*;RmG{|RSBv@Rgx-Mm7+>jrK!?Y8LCWGmMUA7 zqsmp~sq$3?szOzfs#sN`Dpi%K%2gGrN>!DrT2-T}Rn@8LRSl{}Rgk8>&s!mTFtIquN#NsrFR|szcS0>R5H6I#r#i&Q%wxOVyR?T6LqkRo$uX zRS&91)syO3^`d%Jy{X*Q9%@gum)cwHqxMz%sr}Uf>OggnI#?Z|4poP#Bh*pqXmyM_ zRvoWSP$#QX)N$%0b)q^|ou*D#XQ(sPS?X+cjyhjmpe|Ium`l|q>SA@7x?EkMu2fg4 ztJO8?T6Mj;N!_e&QMala)jjGF^{9GS-JtGP@LljOOV9 zdO$s>9#W61=hXA+1@)qONxiIIQLm{t)f?&^^{#qfeV{&7Z~gG$i&gcR`dodXzErQP zx7B;rGL_0f83 zUp4;PP;Ia_L>sP+(ne@wwaMCat*7QyJ+8^sWN5lHz8ZhcjwV5St$EQzYU8winh;H# zCQwtWjn^b=3N$sEMopcjL|d#a)HY~JG!>dc&6uV~)2Hdw3~2^5Y1%{0t)^9bp*hh! zYu+>g+GuU3Hc0EIjn__URyDhtWzC|dQJbjE)Mjb3wK>{cZK<|QTdu9px@){OKALb% zq$Wv|rpeM|YjQM2no>=frd(5{sn*nLnl&w&cFnM6L^GpV(`;&vH20cEji)wH8>WrX zCTTOYRoZH8jkZo(uWisaX`8hz+BR*wwnN*c?bh~ad$oPqe(ivEP&=d@){baLwPV_G z?SytxJEfi0&S+<~bJ}_Bf_726q+QmoXjips+I8)Qc2m2h-PZ1CceQ)keeHqvPC$!Cx)fcsE=Cupi?ZzfFz!#||1?MEsq@kK z>+*Glxjre2x-H$dZb!GP8`KTyhIJ#lG2M)AUbm!M*B$7Nb(gvu-M#Kfm!|L2 zdFj3NL3%%ZfPTy{YVg%Z>l5{<`UHKtK0}|a&(#;`OZ4UXYJHu)QQxd@*LUgr^`rU; z{pr_J`e}WlA<2+zNHL@u*7Y0uP5qXBUO%hvG3@I1^~d@%{iXg+|EPb_dl-BS{)Qk! zs3F1-ZHP0Z8?p=qhGIjRp~_HaXf(7LS`590NqwiG%g}8YFbo=o48w*I!?(5CCu zb?LfwJ-S}qsBT<0p_|lA>85qFx;fo~Zc(?aThXoR)^r=XJ>9Vx&6`Y?UCK2jg0kI~2K|zMW3n9 z(&y;&^!fTieUZLcU#c(DSLiGCRr(rzt-fC0pl{N*=v(z|`VM`kzFXg;@74F|2lRvb zA^os^L_ek<*U#wZ^o#l>{jz>VzpdZV@97Wphx#M^iT+f7uD{S<>96%S`dj_I{z3nw zf7ZY1-}LSVPlK1i+u&>PGXxj{4Z(&GLzp4l5NU`q#28`?@rDFLnjyoGX~;I@7;+7H zhI~Vzp~z5TC^eKDDh!o|YD0~o)=+O~FfwVZ*R#*fMMzb_{!leZ!IA&~R+nHJlhu4QGZ6!=>TcaBsLWJR5Ed z4~9p>li}QOXLvEZ8r}@(aY#<^fCGy1B`ygAY-~Q#29J}Ge#OCjKRimV~jD@ z7-x((MjOkFsm3&8iZRQWXv{R`8S{+=#zJF}vDjE*EH#!JeT{*}C}WZ_*_dI>Hs%;B zjFrYJW3{oySZiFcPuLfXOU4yrz@M}mM~tn;A!CPe+}LXzHjWwxjDyAr!W8RADMI zRhbG+#ikNdnW@H9YickxnVL;4rZ!WDsngVD>NfS5`b`6-LDP_F*fe4qH%*v&P1B|s z)2wOEv|w5?Et}R%tENp;-XH9kc1;JSL(`Gz#B^#pGo70*O;@IS(}U^R^kRB7d6?bJ zPbN>ZkJ;BeX$mygn?uZT=6Lg?Dao8{jx~py-%S4IOtYUk#@uHbHI133O!KBi(~4=` zv|-vZZJYK?`=(>lh3VRKW4blnnY_&2<^Xe$IoKR(4l_rXBh69f1aqP}#hhkNH)ohr z%~|GbbB;OJoM+BA7nlppMdo62iMiBVW-d2Zm@Cay<{I<$$7*w}xz5~RZZtQUo6Q~O zPIH&J+uUPrF}IoztbOKw^MHBKJY*g=kC=PSqvkR5xOvJvZQeAmo43r{<{k5fdDnbo zJ~f}156s8ree;$1!hC3+Fi)E2%?sv5^OAYlykcH8ubHpSH|AUOo%zxHWPUKenLRA8 zW>1Tk<=O0Q@v-Z_FG%6 z?bZ%!ueHzGW$m_hT8FJ8)*fq{wZ+!fwcI&Gb?&RXZJ3)V&Jl6Bd-VqLYaS=X%_)=le{b=$gQ-L>vn_pLD>kF3Ym z6YHtf+ZOXhf&I*SWxcdsTOX}{wm0jG)x-8`4Y%J|AFSur3+t`*&U$ZsvOZhgZJstS zn~%-k7GMjs1=)gaA+}Ikm@V8EVT-gy*`jSRwpd%7E#8)3OSEO!2ESMFXW6zV-wbk23Y=gD|TfeQ(R&Fb` z9ei)vk#5VhW!chfDYjHwj;+8}Xe+W6+e&PewrX3At=86TYq7Q3+HIY-9$T+%$Tn;n zvyIy(Y?HPr+q7-QHfx)=E!Y-qOSWa(ifz@lW?Q#y*fwojwr$&vZP#{S+q3Q44sGYQ zW7~=C)OKb&vR&9NZBu`KYrC_pe*I{Bvc1~e?E&^!d&r+he=o!yX^*z2*fZ@h_C$M$ zy~18&ud_GUyX;YRFMF^(&Yo&7vxnKc?UnX?dyc)(o@P(Bm)nc&we}2qwmsKgYTvW( z+IQ@S_5=IA{oeL$^R_S97wu#A8T+h#+CF8Uv=7+*?Q`~J`<3n5c4K?6z1ZGt9(GT= zuieicXb-Z7+9T`<_9T0{J-e>Q( z588+9!}byTsD0c%Z(p&m+Slys_6_@{eapUWKe8X&Pwc1mGyA#y!hUJLvR~V8?6>wi z`@Q|a{%C))KigmIul6^)yTilb>F{!RJA53z4nK##Bft^p2yz5FLL8xvFh{r}!V&3+ zazr~~9I=i#N4z7!k?2TrBs)?Z>5f##`Cq*JgX6!*brd)X9i@(PM~$Pw(eCJQy)o99e0ig$D`xP@#c7STz~Q6@No5Xb$9i1^>>YM z4RQ@}4RsB6jdTrj^>vMNjd4wIt^Oj(HQ6=AHQhDSHQV*zt9;irw_?{4*BsZ0Kh1Kj zaIJIQ|EkHg#kJM7)3x8V*>&K{Vb>|wG1r$bCtN38XIy7pZ(QeHH(a+|w_W#KcU+HM zuN|kZXRhb2*RIp9E3S90_pX6%@orD9M_=81>EV{~)q|_Ao1a^NTc}%vTcTUCTZUVv zTaH_nTY+1-+q_$uTdiB2TccZzTZLP_Ten+}TbJ9gTd&)sTa{a<+l!#bD+rHbO+p*i3+qv7d+m+jiTeRzg+pF7?+u9c|ZjWvrA3Q(!een9Q_aX2@$cNw$ z5g%ecM16?+aQQ{jhm;R#A2L3a{a)6G8@KEa@gMR&~mA38sDf9U%#_@U>+=!fYKQy*qN%zhaEF!5pX!|;c#58eMO zdv5{|Rd(kK3u?E9?&;112{g<|UI!1GU`R_kFLzs)BS=Fq!v~d_C`F z-piW?1Y}bYP}w)xWfM?QK~YgrQBhG*QBhG*QBhG*QNB}msk?BiC zIsfzfujhZ3%Qzc87=A8%D10RRX836Mz3}_tPr{#tPlQi~$1#>Ok{Bx(FT&Fp>5L4< zO2%qNCSwgFi;>MJVbn3!GS)M47=?^-#s)?uqnc6AxEod;-pD8o-^|#;*v9B!>}2d_ z>|*R^9ANY?4l)iijxdfg&NKQLE16drCm1IgXBdNwi;PQ*%Zw|G8;mCATINm0Cg#TQ z+l+gRQN{ztL&jsqQ^qsKBx8yZ&s@PwWTr7Qn5&qX%r(p`=BDr*=5pqd@b%1G<{`#? z#%g9h^HFq3Xj$l^Plv=im`S0NpQeSThF%Z97GBJJ6kfy}3x62?H2isZ0wa-8z{qFh zF{&74j7^MYMhl~j@gVGe*i_g=*yFHL=Bn__@Dk?g@Z|8U@O9zE;TxFS!#l&vnVZ8~ z!*_)54etp*AATwPa(FMJi?M@ojB$a{&p6IF$GFQFVhl4T7zxY@=5t0R^9kb-BZZmD z9AR8%6oeIrm4@An9t!IU9f{r^+8+8iboA3ZpWgd)?9=<7KK%6YrxTwp4^0fs49yN* z7n&QIA6gt*6ifOX#-HU7@=}_l9Jwj-<~tTSw9*sidyu-#z?!g|6Eh8+q!9Cjq^XxOo^zOdtA zC&T)~&W4=}J0Er->|)sEu&ZIiVb{X0husXj9rh$_GAuDXDLf@SH9S2$Cp<4aKfEx! zGQ2*#DZDLwYj}HjSNQJm{ox104~HKMKNCI>ej)r~_?7VC@LS=x!|#MY2p!kAKE^4=X~qEKEaMvE z7UK?Mj4{r5!Fb7tV+{^4{?qlv}9$@w`4>Aui4>Nn2N0>*M$C!Q0 zVe%yH%;=40j)<^=O8^BMCwbCUUj`I0%sjAO;K5?ISwiL4}6 zGHV4Zg_X)mW2Lh)SSwkpSgTo?tTn7GRyHe#wU)JxwVsvB%46lT3Rs1#B33c0gjLEa zW0kWuuqs%UtSVMDtAk$tX-@w)^64w)?QXOYaeSr>j0~Vb&z$4b(q!5I>I{2I>zc_9cP_jon-a1PO(n2 z&aehpXIbZ1=UIcS3#^N*OROQ*W!4qeRn{=;8tXdi25W?MlXZ)An>EV1!@A45$GXpY z5PdQF5$jg;W7Z^Vg7uU&#(K^gXHBslvL3LWu%5AAvf|kB>;(35b|O28oy=arPGP6A z)7a_k4E9R)D)wr2CVLG#o1Mj8$6m|MWtXyx*g5R=>^ycpyMSHDE@qdo%h=`Y4eSbb zCA*4U%dTT@WY@DB*p2Kab~AeuyM^7#Zewp|Z((m`x3jmgx3hP!JJ_AKwcK-@70?UrY3@1pAo~(~h<%kk z%)ZXP!5(4XWZz=nX5V4oW#40uvG21VuphF=*^k(d*-zLL>}Txf>`C?u_Dl8@I}VD6 z5}@T!B9sKBK&em~lmV@TRzsQ48Ym0OhH{{_&^l;6lndoS`A`8=2o*uaPzh89l|vh# zW~c>fgSJ4GP&HHo)kAgAMyL@gg=(QHXa{s$S^+gcP0%K&71|7Kh1#KQ&~~T;>V$Se zyPz&;H?#*j1Ra15Lw!&`bOt&PjXKv!)=GMygHSJY1Ud>GgN{Qdpp(!k=rl9{orTUp zgU|)&B6JBFf-XZ>psUa@bPc)=-GXjI_n|T94s;i~2aQ5EpqtPL^ZEj&b9N--09Os$%o4bd*m%E?4kK4`d;vVE4;`VY6b9=Z)xCgkM+^yX0+|ArR?osYB?s4u3Za?=7 zcYu4AdyadaJIKAjy~w@99pYZ*Ug2Kl4s)+@uXAs3N4Ph+x45^tqujgPd)zzRhum@Q zBklzE8TTpo0rx(4jQg1Tg!`O3$$iP4;>Pjfc?rDbyhL6SFPXQ3m%>Zst>vxfmGP>0 z)x1r-Cf;V=7G5*2owtqG#_Qm1=k4Jg=k@bW@+NpsdCz$-cvHOP{1dz(XC?0lZyj$h zZzJyluZ}msE99-@?c}BLcJQ|HvUvM=M|r)xZr*O*An!cyEbknzi?@r{$ven9z&p)5 z#XG}m`)6W%l4B=03JjvvoY;3x8v`78J-{4{<#KZC!Lzly(_pUGdt&*EqEbNFld z>-g*Wx%@nSKEHrp$S>j-^Go=p{4#zye*?dQU&*iHSMzK5wfs8%Mt(iNf#1k);y3d* z@mu(<{5Jk({ucgLemj2~e>;B%zk}b&-^t&_@8a*~@8R#|ck}o0_wx_%d-wMj(?s%$iK+H%)iOM${*%G;9uw8;E(Wc z@o)1-`D6V1{44y&{ClEt{v-Yb{|Wyg|F-BU{~7<0=mLL;e~EvMe}{jUe~7l3IIF0CPAlQlb}VgMX*)SE@%^U2zCl~3HAuO1^WdD1wDd8f>ODM2*~0b0LfbPzqF`L`Tu>_*6C4%v z362TQ304X(3DyaR1tWqr!Xd#v!Dc~;;I81YU`p^p@KTU2s25)sWC&A*3BnvE3pDg`xy20^o+Rj^I4U9dyYCD<+4D>xuH zEa(*+5u6a56!Z&D3(g463N8w+3a$xm2u20>1P=vI1QUWuL7XsNm?%sVrU=u8tAts? zwZdFso-kinAS@IX35$g#!ct+Guw1x7SRt$wRtc+xHNsk9op7VDUf3XP6gCN)g`0#e z!d79MaI>=f=4?h?!W+V? z!rQ`8;dSA|=*^<%!Uv+u!V%$3;T_>!;XUD)@V@YY@S$*A_(=Fz_(V7%d@6hZ#hqD)b?s6bRCDiM{6%0(MQ6{1Q}m8e=&BdQhEi8hMrMGc}RQL|{1s72H&Y7=c0 z?GWu1b&K|i4v2b02StZPy`m$cqoO|1anT7;zv!&!oanshlIXJNis-6nSaeNvU35b< zBDyKMBf2XZ6Wtd*6pf1>i=K!kL{CM}M9)Q&q8Fl+Su@on*4@pJJF z@tAl(d{f*b?iJq`?-lPC9}piB9~K`KpA?@GpB3K|KNL@h?}#VGFT^j!Q{p&Dyd*)g zT#_hBlB7!3NU|j>B^i=5NxEc(WVIw&k|{}%WJy*@awK_@d`W?%P*Nl*mXt_JC0itA zk~T@Tq()LF*(hm{G)kHz&5|3AZIbPhPRTAwm!w!fN^VJROGYJkBzGnEBx92Mk_VE9 zl5xo+$z#bA$%N#omYQx?Y+q&6DO!3#5h8B5AR-L|Q5>la@<2NH0q&q?OVtX|=RQ zS}U!SZj?4i8>RKqCTX*@O}bs$B5jp!mTr-5m2Q*nkakErr8}j&q+Qb8(mm3>(r)QK zX|MFCv`>0SIw0+ro|e9l-jJ@6jY=O#A4?xepGcod6J&|9Dd`GXn(VUly0k}nOnOp! zK)PQ#BE2HLBt0v=BRwcBk{y;Fk)DzcN;70vrRSuZWap*B()F?e*+$11=>_RU={4z1 z=`HDP>0RkP>6rAs^r3WIIw5@~eJ-7pzLdtv;$_QaNwQ>FiY!&OQnp%_C0i?7C(D)P z$qHq~vJzRTtV~ue+aRluRm!Sl)v_8{t*lPAQC2T&kTuGhWX-Y`S*xr~wpq4CwpG?H z+a}vC+ac?ab;@?icFDSAyJdT1du83SeX{+s1F|03LD^whuk5Jon5<8BTy{csQr0g! zB|9w}ke!hY%FfEp$Y49e6xJNyj^}rwoTq8 z-z$G08<)k&6XdsL9rDMr3VFG_PF^anmp96*Pm!m~Gvuq}tL2&UYolk$G~Dfwyn8To+xto)q(ynIl8 zL4HwwNj@aMEWaurmXGVN$ZyJT%g5voPFDjzAIC?}N9l#|Mr$^=!C zYK1CIwNkZOm8r^6ty8U6<*N!+#i~+Om8x2`MR85BM{!iSL2+EsshCidDUK<&DV`~A zDE2GXDjq0G6h{<06ps|mic5-}igx8jMXjPnaZ|Zmby78|tXEVj#+2jA+sYQj17*DG zhH_YWO?g&vMsZ4!t}IlJsIruUij#^QWv+6Sa!9dWnXk-HrYct`(-bL+WW^cf73B-n zIps=4qGGioTd_vbr5I9PR1PRlDo-i5C^spalv%2BRhD|Ks#V#b%u^MqvQ@px0#%7> zjcS!DLsjdnRo18uEB7fU71ipU%35`Ya-+ISS)oc%-Bcv1l2xgy3gvZ0xw1%Es@&pC zR`w{S6!FUC$|>au4WH3#uR0$yNXf89mNa9 zV`Z(XPF1gJP^BxH6z3F4%1q@3Y(b7>aeO; zbwqVkbxhT#I<7jQ>Q|joomQPu4XDnl&Z*9;22~eS7gd*3L#oTFE2^uiVbwL&b=3{k zP1P;cZPlpij_R)Jo@z{WU-dxsP&KZ4qUed6dbv7L zoup1yuTZC`Q`KqebajS$rFxZmwK`M1MxCwBQLk06Q?FO&s`J$O>H>A4x=3BDE>V}N z%hWZ>a`gsvg}PE*rLIxesq57Z>PB^wx>>zR-J)()x2ZR)x2U(O+tu6D+toYN9qLZ? zPW3KzmwLB)k9x1VTfI-cUwuH`qdurUq&}?fRUc6wRUcFLsgJ8qs86c<)u+^_)o0WL z>T~Mz>Ou7d^+ok1^^p3q`ilChdRTo;eO-M+J)*v;zNNmc9#!8_-&NmJkE!pgAE+Oy z$JLM2kJV4q6Y6KqL`||LMUxo$RQ*i-Ts^6Np?;~JQpaiHH3^#Knk3B%O{ykMldj3o ztkkU1WNOxEvNYM69L-wII!&%-y(UkSuPM+JYKk=Fno3QTW}~J?Q>Q7>6l=;f8#EP~ zT1~yCLDQ&d(rnVSXj(OGn$4Omnrh8fO}l2BX1ivGrbE;9ivi79%{k3^%|*=x&7fvT zb6Imkv+EbbnroWtnwy$&&1uau%@fTF&8X&*=8Wc!W=iu?Gp4z#xu?0UIiWeJ>DQdn zT+v+BjA(9Y?rR=s9%>$G9&08vPc_dqlbSefyf#6*T$`v((k5$HXj8PQ+H~zoZKgI` z+n~$R=4jVy*K2dNdD?t!p|(O>tS!-&YBy zJ*qvSy{A2^-L5^a?blw?Zqi-W-qa3jN43|rBicLKE84r-G3`U`MeQT)xb}(mh4!iT znfAGMQu|UnrH#|Y>k@R!b&0xlx?Q?0x@6sBZMtr?E>oAK%hBcO3Ux)g``Siblde_Q zrrWC9p{vq$>2~Y(==SOk>iTqtbo+GMbsKf{x^226x)xoN{;_VGcC+r9_O|wxwm_Sv z&CssWuFZ9okOqaqUU%DeYquLpz~O(xvE9b!oZ` z-74K0UAAtmZoMv7m#-_(73)fLrMfa*xo(55LRYD)*45~0b#=OCUAwMB*Qwj7>(=ep z9nkgY4(ob#M|H<^$8{%k{kl`S)4DUd0o_^MIo)~Ppzeb1qVAGzNOxIxMR!#h9?7>h9^rboX@+bPsjox<|Svx(VG=-80>D-K6e??xk)@7pITc zC+L^!6ZJ{@Wc><#iau4Jrcc*r=vV4j=~wGB^=tH5`fPoUeyx6;e!V_dpQq2)7w8N1 zMfzfWiM~`{rZ3lT&{yay^;P<6eT}|WU#H)wuh%!|8}-flP5KsntG-RYS-(ZURo|}P zrr)mLq3_Ul>UZjQ>AUp1^?USt_1*e?`u+L?`X2p3{UQBfeXstA{;2+#zE6K#e?os! z->*NVKdnEbAJCuGpVOb$59%-IFX}JphxC{ASM*o)!}@Fb>-rn|5&cd5E&Xl%sQ!-r zuKu2WOn+bhK>tubp?|7>rhl$~p?|4QGsGK`4GD%P`b0yLVTIwbex)J9u-dT7kZzdN zPwC?f%MB@pR70j=jUmgBV_0igXIO8@HDnv|3MtBn+;nGI}GiHZH8Tjy@uU}eTKt^BZh;9 zKErXtA;VTfzu|Q!+FD? z;euhm;iBP^VaRaVaK&)dFl@MHxNf*%7%|*5+%nuY+%eoY+%t?B9vU7QCJd8?mxg#_ zf^oSq&X{OSHl`ZWjOoS(qp{xj!q9ANHMSVrj19&o zhR24xh6jdG!?SyyNq4N-Nrq}y~b|iKI4Al z0b`Hxpz)CLu(8*8#CX(r%-Cl86#Y)uuJ3EYn)kI#ZHsy(!;RY$`F8nyO6I zrZQ8x>74PbvDLK2wAr-Xw8OO1)MeUZ>Nf2)9X9otj+%~`j+^>SS>}_bQ>JUC>!t+P zsHxC&&-BRj*!0Bo!Zc-yGbfsp%#)@S<`Gk-X@xcdUJ!h(cENiHg7Vwm|M+l z=FR3U=B?&-^EUH#^A2-|d8c`oxy!uUyvMxP+-=@xK5E`?K4Ly>?lm7bpEUQIPnpk| z2hA7E7tKTFYvvo~o90{QW9AX_n0efM-h9G*-F(2@V?Jm;WbQMcHlHyMn9rIonJ=5K zn6H|L&7W>MeDa8p|QeMoWXG(Xz?XV#%~@ zwXCu1vUFMYTJ~6WTMk&xgDKuU1?oqU2V;@ zW?9!**ICzFbFA6ceCvH{o;BB6WG%LqSWB&C)^clwb%V9iT4k-a)>&(<8?E)$25XJ= zilx=sX1!|JV%=)pX5DV>vUXedS@&2ETX$OzSbMC!)+5$b>q+aNb+h%7^|JMfb-iua zdd+&%I$|BN-nQPg-m*ThKD0iwPFOcYB-obQMx&E$D{LvYbX$fk(N=0(Wm|2_v}M`W z+KO!DmTX&^ZKbW*nqhrpNwA)`3|dZDcUsTbPFV{gUYM6#k}WBg49hCZTFW}idP}aQ z#8PUhuvA*AEwz>=OS7fb(q`Fg*Ww~RyYq@6`v)s2luspPkTOM1USSBn_ zEzc~^Et8fPmY0?(OPn>{y4;#*O|m9iS6EZ5Y1XyY0&AhQ(b{C)WNopwTX$GHtew_f z*1gvK)`QkV)}z*A);{ZTYrplh^^A4Ede(Z*dfs}$deM5-dfj@%I%>URy=NV>j$0pD zA6uVTpIV<=C#^56FRfG7I9t3e$(CwcW6QCvv*p_IZ27hVTZygAR&J}XRobd-HMUw? zoo%D7-qv7iv^Ck9ZJTT@wpLr4ZL@8QZL6)_w#~NPw!_w8>$L5(?Xq>*cH8#Y_S(8_ z`)vDd2W&mIgSJDq!?s@A5!+GQF1SKyKj47dt!TLdufY{NQ_t!krI&_krt62 zkrA;nVpYWIh|Gwri0p`*h_w;xBGyObMifVsM3hEUL{vxAMASyqMQn_yk7$T!jA)8z zj@T5@644sb7O^>EOT^ZQ_K0l}+aq>FbVPJU?2OnIF&Z%*@gm}7#8kwkWtW!?F1xVo z;<78thL>Gmc5~V7Wp|bhEqlDI#Xhm@*|L|*;_Yqr<@Rm%Bzv+w#hz+^x-8wk(%x#% zwCC8@+Sl3F+n+Ccxa|J2LVJn5%wA;AvLAF-+w1K0_6Ga-vL<_teUp81*^Olz?RoYB z``u+%mt9*nvTStOy=7y|9xQvb?8&kh%i`<__7(Otdxm|reT_Zao@>vy7u!qimG&xo zt-aCSY~O5OW#3}oZr@=~v~RF?*gNgz_MP@y%XZl-?0f8c?fdNe?FZ~V_I7)>{jj~) z-e*5KzS^Mn{FC%F*O#c5HIAI9eT>9eW+!j(v^;j@^!fjzf;4j^mCKj+2gl$0^4#$7#nI z$AIIk^xy_bsn-Gu^+V`vtP7d zvJcsZ?bqzr?IZS^_FMK*`$PM5dG?YDcCc+mYi~=g4*BISL)c zj#5Xtqs_6!vDMM;*yh;o*x~4KbUJoAb~(BndmQ^6J&wbUUdIu~dB-KkkmIUj*m2Eq z-Eq%x-|@il$nnH6;dttJ?s(ytawIyFovF?==St@)=Nf00Guye&x!#%YEN~V&i=5@o z4bBQ@m9yGe?`&{3I=4F8o!gw-ojaTz&Q9k}=PqZLbGLJkbFZ`8xzD-ZdBEA@JmWm; zJny{VyzD&f9B`g<4mz(muR4dF*PPd#H=HBRo6cL#+s=p1d(H>WN6shCr_M3wr1PaS zE;1o6U+z?q2Ss7UsSshsuSsPgw zxiPXnvLUiDvMI7Ta#LhWWNTzwY^H=nxi&FwMMl?ZI0R!wKb|eYFpIys2x!|qjp7gMeT{&7qvg?KvYlE z!Kgz~hogF<8GR*sDEe;nv*;DBs^}C~nk(J4(zVL9 z+Lh^ACDt48)N?m2Ha@Ph|g{#t4<*IhoxN2Q>u8ppG zSA(n3)#Pe+ZF04^T3v0f&8{u3t*-5^WLJhO$F)Pi!;5y{$bscma zbDeN?yY{zr%Qb>4Ns_4M;p*O2RqYuI(& zHR8JE8g<=urN-QMJ#tOD9=aa5#$9DG8)7PB9=o2pUby07p13Al&s@)4FI`iv_?U#4 ziE1$%sjhSs7CvQxQ`YvpOa#W?f8POlHiQnCzIGnDsHaG5IkC zF@-TjF~u<@F{LpLG0icJF-vf#t}F(1AN3Hql6f$Wb8MU=H?be(xo^aazJ!ME6~-<2I3E5T{_h8i(Nceig?bYb;}(D#K1y)^ z9VvzW^^dV1EqDLu{wq@JA7Vd-Z$3gQTlhO@fee?JHc3Oce7e3ay) ze7M~uu^+=X$m2%^?jNP#)wrFdpnD(2LQ8%b*zpbow};mh6tWN67g&8E${fjRCYU_Twb@F=NdA7!dn$BK(*GKL*Br z47U&E*1Cz>4gL)G4DCGV0)hhk4o>94kN~Xb?}h{h2mWNiyCDnRmv=%Ixi5=D7P~Kt zLf&y-7KXg*z66FWabE&LmbxzsLcW0#4-h8w3;H4!8b=uvys#enRYP*{qI&3O;Ign#kJo1OH+HR4OSGB94vLAYT4;b>#Rl?J{jg-OL+gliE=xH1yokZ_f~vT!X#gewpc zt^h>17KFUxRe)+xCIl~pzVk)!BIv^}f)_(ez6gHj_rL!=N#FkvJ3GmMwahIU{~MF0 z-x912tZ}qf2PkodFRMdqV^Z8AJY5Vv#+vTHYJ`mtqPS2h{8G?wutG%oU=!etzIv=S zL~s$a&@ozs7!9IT_#>t#X-HcHHTi;o25ezyTLU(DFdmgUxE&HtfDMLQ!xhtu4Nj-W zCq5t`@Jo-bLnByAFiIh)jr=4q2-q;pk`mh|2!z{CEb`Pu%cBfh8j3wmi3oqL+vL&$ z0&HFzW;b9{OC$*T!!$sqyD7|eQQXu@TJnNQ!T0PiOY#Y3ei0))-A#Q$=cX3oK)wrr zMBI=q76SGc@t(*pzmD}_jC(6vEbtit!3+KsTB7i{xnE;sASN3q%owJ`fkZTB$DUPm z{a=id>xzX6$>f3%0u>41n=$A5+gQX&AUy)C%A8Cm_7SiL`BQ8x{t}=cuLAKmNTL53 zOY9Bw9u{7p?P9i`UV;jJNl-f`=<_N;tLYF7dW{m)LuSbg612#d1ofea1kXW&GU@tH zkf3%lx$`PPc!c)~67=_&2Pnnl0ycm@3S9UxY&fAcaLU-&mb^@|4z0y^fn$dA%KvS{S-nl z3Bo-HhykF9J4h^sQwVggjYJ_0d0=P=V}PoIH-96=tc4%J2Cm_-qyyy8QQ}%e0J{P( z`39otTZcY$^9>~}4h=w|btD4=9B#@K)#0Klh8su-@CMU64?x&21RVdJ3RqqR zxC6jbA(jWoQr7{Jxd5^Rd-6{gVp=zQje(ZnV&joFU~_Qci9r)ZC>cPF2qVHz0zV{) z7BJTc>~KB~443~)cDfFHkljDQcIP)>;e`d;o!@|k7c-22pM}_1$d81^tfUf6Xy6R` z&P)dHJFu&TrO_jmzX78)vQz?N21l8{@(iP1K`IGx5H6K}BuM4I&68CA7wYsI2o8U^ zaN)nq6yg#L&Z~sDl;J`zmOP<%BdA+lLNrnY8yyTZW`^McoE7;hh6`^1OV2=Yn1td# zEL`|8>{uXpKIVgOaZ~709b~2BGA?#mf%E%BoL5Imwj}L10D_2X8nrM zexNmBNgKaOi6bHXN#GnvDWNB&oG_jy<{-(a0Gr%JLkilhcR&P&B!l4}JV+7&a*tPW zxUi7`61YLwWLYUajcY+Dgm8zLHZDU8d-zuW9F2F7UqGk}lS6D38ld!or0Sj+j6zm9 zJz0K3S5JzN5iZU*bQ|btoJZ(#D829tx(a%-zK=%l?pa5I%wY4QZ^fU%l;_(@+FOj; zYbEWgWXV_A_G<-ohRVTYtS>c~;m+Il>%1UH5s&00B5A6(x@k^3z0@ERA5Do``STGTUPmvPC$3d@9fM9pfI}{-A4HJupl>lIP zCKdn1OL*Hs50?!em&E0xT}8t~Hx6iL77@*`JF;FxVMZry?X+Sr4iiVb!UqP@Z3QUDro#tx2DUP|&Ujh7vzwNf zAPQJrSW9mltUa{!(StSW3#?463v&Q#FD)@tunMu3-Z)s@wDi$~HRcPfVXO;uu8L}( zy-3zRT4JbRjbSalaj^E&(no90$Gu_&?0GNN13Ii|4Zs1~mV=>NFZd>23w%dt$)m#8gSG81 ze56o*E|J<%TKZ_sT#8rpfQx7^L^aiK7jcZXvGXyWd*An=bAfQDe#}^V^vqs`1JrbE9Rq{vbTqzvW%(##g76dT)>Olg?Vh#xj zc$ySn?(=_MJxI#+1x7Ar|NItv41 z7ZN#Gde3iDah4v5H!~_vA$r*P9hKuFOJc~?>=iuV<|Z+nnm$1zL031H4>Lz4-ypTnUh9FVz$ncUi`bfLIE_r*_XrcQ~ZbM!6Ar$ zKi0}Ci2r5U+UdL6?W?Qxz6RlbcJ&G^F+@%8##(uWu3n|BojzOBrvuMVExSPvC&8eUVyzH_%-?Ly2yN}OV$$!mr$9_HXDuc-XE%iP2$S*o|Tl6P+2Qom9RM)otCpThii3C5 zAin_oJ&o{$DN zj+~H&REZpqhHi9${|fa#EksT|g4=|~C(uWjOlS-SEhyWAl4mm%+#jzA{+tJ(8f3K} z1hdz(eG>GSas~iV!jM|Y-KT8k_H=gEtjqOE6ky#%|EsXBi~QCcSU2n56#D8-ADJ#c z1#yu4)*O0MN!X}Hv_f4pL?a9Nz}XPFMX2F}We+5J5m|>!t^^R}k!2526f&`e zwlfmdeMqggP@0q%gOU-Eit8zyhOADV09Aw9_Z9!;*VyR~FiFH6xS7XLV+PkjkwwIblIPj32^n;wcs2 zkPFn*Jwo7&2Ob=jvrhuQgE9<#{1zH4ppPG-@dEnz9vU*Bk4rv=fyAm>glG`fdJ8jvPIMh4dUV_nBQ1E2k%cKh zkCAPTFG7MLSU4chBiw1IHwF9^wHcF%?t6s#350r}lV2UiPZ1jCsFRs6o`_E7!1qWG zQJwtR0;s*Nm=G=^3W9PSVJ@r)5WMW@gRc~kX9yznb_D6%*TIf7&x0L#4nr~R0OwiR zkx2y3uTsWeAS8HFM#R8!;>mPNfLI@33F^yBD|O4d)cnVf+AIVvQN@ft$A)JDO(O<2cY0nge)& zLBWW^J5%VZGZn{YY#NG(8w(1eg{st7?e$&sP$i%>UiP?Y;pc84)dSdwHQ}ksQ=#XVc^mf*(g2FI55~Q5 zr%9yIjuc^sfYSvc+g$QnphIL}(BAlwvY7R_cg$CBddaC2KYKGqerpcB0b#l4fEHrh zn&?$o0hk?F@D5`L!X&~liDumEJ~+nB3`8%n(9tt|^hQF8FA|#Pm4s(20^T)$8Suw| z{~Pe13%_*#-?Ps%WI^x(XrXu!8(adx1**V8F4&Tyoub|Th#d>}D@?KBH^8|quq+gN{um18ofAQzv z`m;a%=7%5r$@}jGePij8ci&mOXklOg_)G>=GX+dHL_Wp9%LZx`k?sY)W#_$b0qOZ9 zFu;9A-6w&ILl&X$u|aB=EJVE6V8U^hBCxRhHc5zN7^5Hp6M*C`#LcJ=$rBS^@?Y{O z0_sijD8)RI_c@_aAbFHx9?ARfgknJQ$i+~+{wJY~e>`Lo=KE5JR#X%l{4S0qUsqDCWNfrZnnd2gL$YioF><=$(ljKS0^>4TK#*2s_?$U)~RSALUB>m($qN z@nvjq5RN@NHW-{*hefl%sJ)Lr(HXViZ{UAdVPd}RO9KA$Zq+C{=us|;Kc%qgt>Wek z5zBi&MVa|02s1xGnE4^fMG(PIbPMRupWuAZ#Rh+XKLHyC4w}X|>cfT+qZ=PeHtx(Tkpb6E6Yu^w01opr_yvc#Ow%dWsT8(oB!O z)>8D9qBI-oJ7bGNUv63shnM0#VrSAPW1J zXuGt|@Go$N0cQvf7RJ~Il=(05Cm-h1PiIIOj*yYTV-t$`e4E+v2^JK3Q|nLYwfe76 ze$W}g;J?B#2iDIUN)+q&Hly@23?=$u@q0f+W%j!$Ds*92@ON=k{MUF2DznviKV8Rb z)%cmf`ve8=dpLNMUIV`iK97JYwGZ$p`bnwgYXu%OJnIqojDam?TK^g`t=~sX>kr(Q z_d|kF_`NvH@8b*r4)X{26L6Tp_!FJO4E}5U?;b}JP*X|K9N+?H>#5a>>qBQzu490**#Jof) ze~KE6A0r0iCy2rLN5o+K)P4D8$j?w&0g^!FwObl~f&=azXZ;j^bW6g|@JApCRBp2| zZZ{D53JlIa;;+#foFC(V_ZXZ`Vjc7DJ}CT~t-+y0U6k5hvot{UabWq3f2n(D#Q(CW zV9XTF1*1atPiT2M-UR;>&QTxH93}NgG4I}(LP2}BUcjGF_?3P7Ov$Pc0G|7+Q~wPG zk9LCXzrDr@w*L=cJkvZBDxW_`jNmU&q-kfNeu0ZAFig{DL4J<^oz6X>RTCpvkC!4& zUD1u9(RW{MGUTmP0X$RK4M#e`0q6o7cm>1R>QjzbY{QGCLJWvq|V?fg9pK->} z*&p;(VwTo_GeiM*wr0pr-|&^1p}$5k{-rOBe@Viaf{I7Z{lu6O@Kb90I%3@CiN?HT z*802z{QrVQ?u$cyh21U<`4r`aI|!!;ygT&z6z7Jo(2EpkgV5_=@YiT9+^_Jz&(^|` zA~gR^oHy3{nJs)9)N95-dir5Sp-o&5GOqRTkwOvIMcF= zZ==G%LWF^hzDCOc7LftLZ2Sp$IWpCd#{v_>4xeHq1}(C^qct3?7zz)P4D8hzw`o z?Fy18A~RcGO&O7rYeV@k`ydHd(g9yeI@4qrDl2kCRuqV=C=ppvp~L~6Q&ZZ2@4*V3 zUtqpMi9dnikqUpJ<+U9DyNB1*iA^$4ZzwLKH2Svjy4M%4XUYI!23d_TTZ1rLi*gy{ zgHoo_iK}ISi&W!$0xSA7_!9_HwD^;c2#=V@_^Q^lkeT|*Du=!}Q+WJ7s#7|&JY6C! zSVsbn5^Q;V*Q-T%r{L!;zM>R+t6-ifuzeTE=szqB2r;9; z0uR@90R2QZoU?>LL~F*s4?t%C&{zG;F;MIP#awtWrYxVN6!TzAS$KY*iv_jSbh7ue!UZ;5m;O-EgL z{zD+wRupqE5^E;sb%2Sm{>wsam5L9e@M_a<6wJR?0=pD-TsB-_DZ^YKur}PH`Y;N9 z3M|DaP}F#~0!s-FD7C#EM!}u_|7k!#NCb{?CRsoM#u50rr}J(UD5!iLF`g-UT?{aG zCwG^j7y}HaCwG^Vhsk`Bkb{wf6Su)Wf&@RIqu7VH5;|OZ!BWmwm0r~H zM&hztKTUQcam(w&eE2E5uNFagV}PF##OpR6VCBVh26#>k0)E1C{86UY!$9pux2g3$xOJZAw>$pd2G5gvqKzmJ<8^+i-);p-(T z13OC5eddP8igZ1jepVO82B@$KB?*>$BK-azwweetaoRz7jX$OyX9TzUN#G*D4tOI2 zwD5N!0l@+8la0Ov7jUxCm(b9p`*@lF(n;N(b2$-?p@Oj( zxM-25MQDK#G?PS2^J_iH2c>{?dJleb&qsd~68wYjV~6*A+uP|qIWPQ$CkTZHxQdBV zl*uqc@JT%gG4N?U6tLj4c3@7q&+1v^sfFgmKQ@$13!~>9D7TE-vPVq7IW&}(;ZtOg zmcc1BGqk+ISIcfEHLc}$@jfrXZoyeBWFp*Opny+VLFj;wUqNocxhxn-e?ZS@MLD|g zcW#+tLn*#U0yb%28XLZW(Xlur2)kVx@*Z{z&Lp8w_XqUk5tt-5t?dFSuveDSncturT9M8G8vt);MV^2SfcMTKPk==~@-W5CB6#O4(pPwkEOHCBtYY1E z(c6G5U)}yKumRJ${bP(7i$i{b-7XFJN9^|fke_0=V1p;6gP;@eE>2G;;7y#!6X*oI zHxr>8-usE%f*qMyCw@!ciEP?VK!yJ64^--ZSyX;|rXllBLC8b8NNr+lwuCE$_iyNF)sh15g^Z<%_9Ar!zFKZ3 zH4Cq|r?dr@*i&Vs&{vHeq#E7o!=cm&)}2#pEb>(&kh;=om2z=(c-SpirA=FzM%Ec{ki-{bgadC(OyImTh#BSdYQBf!dw8HB_J+#8>K@kGsWuwR~ zSOtpF>Luzb^F=F=zK&|DAys2kEe_FOw@X8`6aoQ!@bX234tSL#atoF?VkCKyzH(nA z4Njv+M{e1@@QVsAuvPjZ$?e-oB*Dw8$c-Z_s^I1T9kl6^Dqn5XlNx~67Eu}i%ZaE! zR{N?EP(4OUj=_s(D3!wNWqeXy!j2O=0&MBHu|bDkyN7_*+@!_U_OvsqHX$!0c#`78skKp>q&WN<`lTXD z>*$~XSf-IlbRi|iSg8GW3EV6`M8pg;_!JUwP+)okPt1d<1y5qWg61O{2VwNWp05e$VxfwjB;q;~TWoLuJ~aov8PZ1n zy9<160RKBk{tc2oO9kdPLKdPu03&xeWsUR)%<>^OI>N$Fz_zYu#PzSlH~tL;4Sf&r z4qzIG&41B;Qz0nm{=$GI7=(U)GNsKMw?7FCg1_&uNaW#)`y(nRNq~V5w!sMFphU)E zA8~+wjjp2vYf|9vgP~dhf0+$}zwrYtj72_42EiZtb1Mm~KM?#SKKGGAM5Qb9=nz~8 ze4q^$EB8mN1F_q8!D;^sf3jdf$RhV80Gw|FE`cDY4=xKs-bK*_9ic2T{5ALl0Q8+N zf)_&{ei8f*wB(E6cYpu;-{ai^*`G0T*THw_C|&ogMsX6D3<5*S_7D){5rhbY1`EM= z4m>RdF92TJ^904B5TJzrJEltLN7i16 zY`)vs?e(DcE!y?n1dsA9()w-$YA{M|BcldvIvF)E)Wq6+4+jo_i#joQ)()->`-On- z|3mJ?hghVJIY6WnbH}$osN5KOou)8DP& zh3Vfd8}M-MJ2P<(Of(Tz<|CW~Zn~c=RKQSU6ybaV>_mSgFb{B)!ec+#`9H|)1R@7l zjx~YGBmuL&SH-ODHDT74L=u#@1~VHjXBqiKIdjJW9#LCD6*Y8j-6Lw7X<=*hh#F8p zL{*Xh7Px~iDOjNqx3d(4)gQ(}U_N=8r~zl6NQTXq0O8t?i3M&Up#Mb{AYkd~1gIST zL>VIIvvdZqTqBqv?}KnOF_pw~T-I??-D-=uAO8$5LCE__48yrKqhZ)W%dL4Z3}lo3 z)(Ck~Kmhp88q9IvRiK)J>4J{(?_CgXqqjjI48}|tQT*NMCphAS|A>rmkXyjZ_dKo8 zq=vqPw$cKh;1Pk~nbahhMoqwe=58|ZV7)io30$^7tcCUkUOa$^D9#_?qA@AN4L7{R z0~2QKb%Hg=Yc% zE%wzIg4qU3F9>EE)f~6uKyNAfgwzT~f8*qS;^Ik=FEHjOSVvqgacLujhy;NH`iZ9< zh=ap_B}<~0pm6R?%*i0x{jWk2=N{R%rIR`Vl$~r+Xf)kF2R3)oy2;lUeBG#3zAE&?;d_Ljth;8q$PY zdY2%#o=-MnpD?Abe!LLo)!eJcdGo3P+gMr>F$L%kZ@{D*j04(bF9Xh>czCnOkK(`d zl*XV&-5>d75BGB10qF-pQal>2z~&#(7vCeXj8Hv+cDKEH4`US`{J!c4d60V@JAmgdDU;;h&7Y)rzC@nl<4feDf$oqH@kg`d4<<>tms{vo z;otx~wd8J&tPdAee{e-x(qBL$|ZGL=fRgSVlz#XbepFbK_S3yAgmnWRly(M~Z~_T!u5uj9V!en6xA721w)dlB=6OXXBxW2sxOZAvjkEq$}YL zVBH`YI?zaaJ_#$(2w}?5tKRt22;l4XKzCq=@MV^H(`kAG6oO)!Xz|6hguoj-2q37= zzX48=F$cDLk|fwfTq#H7(8dFphJcDjNx06oB7ogBLRt+(cQA-vN0gwi1f75x{*wis z&1As*5X~;2uBM2{b>fJT(oNd9lF-e>lDSj_x|vB3ky(Zm(?kUL?KrZ{q-FeX=@?%~ zdeH~JWdD1$FG8?C zz~^_6i{U<>V3B}{>m?ThCJwQl#5Eg$g~*Q%LdXjw9r;m2_>tDc^^_A)CqNESbblrj zH#w(@5Qcfyb^LfHhW*$#!+<~UCK)yNMqgCA32q;xeJNf9=LEs+<54exJ-ELis?K{J z)iL4z{4+X#o>)u--n}T8>}u(S-yc_t=@jti1JfG8t95G_-Xu}O{ApzVjdkV*3LqH6 zNT7#I_tMRz7k!BEOvZY6P89(}=6Pf=Tt-3!mra5(aR)-=Vz^Bw05{Xfpn{~mb2Gk} z`~jO@Q$gy%oLt5HOWY*cyv`y#AR#^niR+tFMF5f48W)aK61g{rxUjHlE){`p&hwCP zm@Jk$I^Xa*hJ@qfc5xR%2qI=NBy1+}$L&J!aW}=f6U@Fp)*Vw};6hTWiM*Tcr|>3; zdf-nZ^RLkLBsrs>+MGcYoUM7sBo(CGa_Wha zI@^lo-*dLt5$TzQ=jFbAG`<%K=(8SR>RW$#8Gp>=yOR$Lx3pu~a2&S1#)O`8P(I!$~ z=ju0G2#W^hA*V_iCg39i!Z5*0q7~yAVeH^5>LiRN@DTxF?0_e^2toj+P_gN6`sD?$ z#xt;j)B9)uM4j!g#xvS#f%eRE60xnBBvIayh~4C3IKBji&6GqOBiG@tPRukh)Vzt* z1Aldbw%V_yW$z~eFk5Fvu1^J%%bdq2OAiC?t-U-i)h!}&Vsa=eIZ~lp85o58X$|*k=b$p7c33r z#pJlA!6#CHox4vxEC){9H_PGO9Vp8?=vfZpAPURz%qYS8&JYI?xDH~H@mA6YAc43b zJ&YlAK5haW1A=2gF;QM*WnMIA2ckJYCs;c#dj)XpJCJvJ76vSxVUI1uwR3a^EVbC=Whfc=Whgt zyo(&efe}x8498;kF&yu>kKuUNeGJDE>M<(L*o~k=iv!-p42PfMmV+A(v{qo4Dd7UqJisWq z*VMtZ;SmGy;7M*LkN*PfG2A8mm)~Gf1!ke(Hz4v^H@Rff1TrBWY7ij<5wxdXt89*_`#1Sb*%79aJurSBHjtmv*KVbH60dk-Y;LAK7rUMh@4jKXx`rLuT zLhLp$WD$0|Fa(R9X!SSn|7Gv}gR48L13|qf>H7rl%lNCpTjknv%}T{rl`k2xN!8Y5 zlHK{kcWSaEOKqyQHnm}PNs8U^OgV~^aVSEOgv7FuZ5hk9jD-yz}}z1^qJ?{oU}X(hki zN`8Bk{PxzBUmu5=W!Oh7`I201A}fUDSyOZ1ltHfbMot;yWmRV`!}$;jzzfXD%P9Q| zj{oZ#PE|%MxYK7TIOfvqo=X+ibE%5nrgl0jp!&79sh!Sli{H2!>QiJV! zKY1yscT`ER(v^1&YXt;qQfn9-6AMQ4L&|7T=SNtd{tS($?NISa%}MrR3Tzodq6c2= zieLaZfm9E}|cPZcx|Dx5*)sRI1Y5$4wQ4f1#cnLL`;G&QL`QE^2T@Qj`S zrwN?LhJY$=`Obj$(v=eqQB_}yHtnpOCiD^JFLR# zO)VPdtEV}tlt^nt5!I2a{@k8(RV+c-gDoUQA5buszoGYg!j8(PG?Htp72=(YN@6{r zrBQ@HBp0Pff+h1jhLG)#cH~=N#-zt!M3mq5C8I~%L(!da%_(=d0uZ0=4+#AL>`qM^ zZA6A-vw!;M%)<2Zh3FuY5Xmk+Qi$lld4l$QI4DFnu^pP6txJqtE7fH977o$Uui%u& ztio$a_31a2<`|yNU=^q#OTxN79a6<#z<&h zDzW1k3FS&BK8D0;U>|NLKpq{91{%9V+In509th?osZaLdv||ljD{xC&qbL79Tzm79 zTc{?wWXdaFUh;DxyTm+^J;_NYdC4xQduc&la>dX#-P;%K+JL58jILF3l=@dmB&h`PKIBRRW!Wb=~SQY154lCmu2pHmX{#|5wD90+j7kNK8>yXo6FJhs`{zv=Gz!){VG z&?hsl8N|(nU%CucSj0a@2fG4EEgKc!$=7{GW%A65fY`}>hAe>={&M3UM#>PLxLuG2l6md z0*?#{3WY6dkVm#};iybmNIf2z$cozFK!A~=zUA+x`Id{4UMwE*)MXGlCJK9n1}b5h zslMfyq-NvGTrM<_$KNGL{N&A?O|4a^FY$}w#T5RoXBGAe4O9Z*Q(dW@LLm?1?@_tT zoE!wpJUP*(ZFonY{=2PWs*hBaD7%Yye@1Wr*wQ3wxUW}aD@vb$KV#SHnM#^y#~Y&C zlm*BkJ|7yQR{MuASVQ+_0c$NZrmcJJ7WI2nT^4;ozmz!hXr`IJ*vQOZGBdx%Uo(8J zLhEW6;B`4y!m_^H*x+BuH27D|;7MF`kO^rUaxN_8A}(6=h6r=f*Fr7H$)h&Z-$1bL7@%BRp9)j2P^V`5oUfM z;kG|)FpF=)G(6*brL6ZR*%QG=8Bk1LUmS`A4K(J_Jxro+h45QX1ASY+l&FE$J<5h> z-fCp#C(X=B@-mlc>Zig}>(pN~?F|v;%kPASNS2qGOvKm@4NCGd=?xKv>${;LYPCPI z_VM&NRxb|OP;)NXq&*W##-G-sCfT}G53(@5zZZh69;fZ##EJTGJJZzP4^NHsp7(|b ztvyYk%CdKTUWbgJ z9aaB=8V|Fuh_8g|>>ugzE%ay`Yk8skF+!On-plVd>e2ui#_L`P6cVEik2GO&|0Fa- zttPRz=0U@c!-&dK9g(DB@2A1} z5Aut3wD*G}7dO}2;__~s)NRpZGuOq>h^!BDa}5$?@nT`|LCbd0ViLozejp3O|2%|r zV)!XRN~Q7P=^^I9cfArWcm73ah-7;<`@t-5JsTR7;M((+7KZB}G(<97E3;YPdM-35 z!8Mx+U%w0ukqp<2x7e`a`c-I9f@|GdS{Pr4p&^pt+VK_}hU?d%K?$w}Z-_8l&xeLc zhHJ=MY#6Q=LW2@q`48uEDT= z%C~N#-ck!#w`(LA#y2SFlU|EZ7aZj}93>%!n)YxIX2X%t@~kJ6fb{Ee;@lq6TkyT& z7IpY7+?M%fE1N}4GF!Wu@ODEOZ|Ep3dP9WO%4lc^pOX*#p`7C+4&Y{RoNf%x_d8wD z+8z|4McrA_21!U8&SWEQ3PC`+W!@VijI^6WLnQ0GIS+kdAs7n{N^os?LxkbFB{W2> z2H0KCj@^R#;H?^l#CUVkLvR=uw}uu%xES+>2;*WrG(;`8ws;#ZCvO;b8@?vvk0l@Q z#>MFE!PONc-2?)iBwjn2T-JAlAS2RkdP9Us_s-A|$>O!(4H{;t+e3pAT!%hof-e4K zXozIE#xucnM`%!jYdaHMcZP;2Be}YLO>qlX+|G`d5VXsqnfYEbb8#`9zP7lsh(!?)pQh}KzR#=} z9o`9#K4C$8e+Wy-f;i_58bW)yTptJxk>6kWpdLoKe5=iq-w)v=dBuJX zUmK}bdZ}?o&MF~FqB_S(Hd4VLOr28f#wKaAMByW6!r$%wtf!1*2+ObHgYRjvH7?MJ2xnI98nS1mox zd40t+){68do9q9odW9O8p;xHt1=#V|QaN$E3~}+CCKXC05xEzgMcciz zcEaFv;5-+D-`6mMk3Jtiz?Q<`!=F20aMWH6GWbckpY}^Sy42VSCnoEmtk`f+-o#*W0wKm$7U^~^?p z@PTXlduOBHgCD16qx10N^la1*Kl)~)i{QsgW}~z4~r#YTQC#Mwx7AW^kB z=qjEuY@WnUXZ%>`q(_&*nC%f?W=>!kC9Z)MPy6*Gj@@Sf@%6NnxR&Mw?k+BIE>R$_ zvw%Bepo=`TlJ8Zm4HNs~ZL zyZOT*XG~fyjhq)=fa5}auaDGEK$H6MI{okeQlS$BK_sy=<@#!;sxwAln*PQ8)oAi; zxl-vSGn2DrwQ&a$n+Nq9yn(iMDZ+$COgwMI7$c$SEVZbxO=pkCDw^Jztde$P!s>k( z7Z&ME_K0*vDe%MuBe)z(pBFi!Qah75QQ=2by)MkbqpEQ9(rYccWN<-(&x_7nBU)L7 ztmoG{hEw@Kt^`LBGd7T&!Qd7-I0It>N}D< zUkyu=gUy3k_!dI2BmdZ%V3gz8`KrD0K81|ZRYcxbLTpT#evtPyN&L={_v2wOJgv20 zC`wACbglJhh}^Z~fy**f$+%6El=I8 z19%?ttYqCQs)h`Ko2H6aL)5PwOVoz_+-bycBYy7V4eHwYG+jF@#Vw<*-H>k`PhFeO zw0cg>O0y;DiJ&As(QG9JCm`*$JT16Fuj#Qy>TQg>CD^;qhv>xY-Ov|A$XKeqJGqS! zP8E$SI|#SIhxPG6;CjwB;QOvss@+#s{>5w-l$>x!XY;qZyU#x1yx)IU&++Bkl*Jw2NkiSHIlf;E zk-m2P@S4wQ3hU%mBt|1X@|POa$;)XvdA}i@yd{PCceG@{49(x4vSNYmqc zQaCgE)}vn(0ow7@<4xDhsd4tQ5!@nsdS4C6CezH5l8mKl=94&^#o3-x-fXr~-Ut!? z*xfExy!+br2X5f?3(&uC@|nAUZmfn04X16!rgjnPmwhKBR(2X!{$FcQ`ER8u{|zbs z8I}K{e5-)+_rzlKqfPczz8(~d7kj|jbUT-tLs~aPFJkAu5uz)%b6*nfN~w14B!{GO z$#pWyi%8@~yxz?Q72jT(;#-v}EUV&^Y*aw;b+G07qOD@id8EizhHl4@OQ(&T6@^Mc zZAINDu$Mm+!>@VK$(YHuUZ$(1^|$7ee}GT=%uy_RXy=>AJGGBhRF7f=&?ail*j)pr zYWwB4D@J}5bS@owXbL#`>|g{Jl`Wn!gAOmqT(_+u!C?XX49q^}n6o(X z#v~0uGBOfxF<-K*Zk0&Y?eLjTFb0#wMSh}D=9rf+78m&^ zOJt72_Ap1B+-6Y^RVvk(XQ4fUBzMC44ch;~%Y)6Yr{O$`^(JO~8D$$BWLkBOjm+#h zJR^bw{No@V6M?7-un)c2^-~d@nTehz1$ zKm$EKH|t4&?D4tWMhQ3;JwA_0GpfnkZ{}ORN4gnRC-o8iZ&c^y8e_xcA{2m1Szj#!CLc*J$-!2D>N$ z4a7Oi^&~*XIpeE-0={*oqR}`fKXH8q=fpj^%b=?b4F1E08GJn-gAX4;2G4&JOA{Hq zc#d{6MuLnrL`JOYwj8Z#I% zYH+;bJTxy^Av+JP$rp?B&`(R`p_vyI4;kspXNwx-xVSnqbSut^Tau%)v*MwAu{bOK ztVC8^Y7Z;M>0}nw^z%fiy|2d~lFA)TYQJ`vwRKf>bah%f?`!JV>v>|muScH{)~(d@ zL~aj+75qgRdtWafix%+t)QoqCaL-6X(;6Q9Jj5Kwq;qb#MsNg0s*xJOU!b1LT_ZT3 zRwFngwK1r1n1yfZ25SUorO<*7KZZ4eo-oWBW!N-fc=i|zLq0XsUaPlLg4H_+(UP5_ zU6cZJV)blsf~r=i@TLLiZrDO&t)Aoo=Xl%UuIIdl%Dm@2+HmjJkJI zzI8lxZ$5qDY3k8WqTAXuP5sM|bRQG9rM9!M>kQTNVC);ZC=7u0eUr~Dd8c~5txkBac&(lTw^u?ReH((kNl z91xA(c*l^r+%VEd{NPeL7;Fgg3FR83tulq~E%Dv}Iuj1_ggeh@B2 zfFem($q)UD79Znp^>;ft`Io_R?)!`teDzm;r>kqANBvMYd%_QOvnTw3n?22P05Eya zVEQG4|2%l^8iglV-J1r_=`anHt1eUkKdXoCaWIz^N6#aLYPFwND=#4$ov%lu^O{C_ zP>14}{d#(!n|`gqn&FPpF1*dOg14Dg@ix=$fj+bJ*Z511UONca2ErAK zr_>dTr_~jUed3D6O9!J7LB;5@LEbn5N|s%c2rg_i6a57%j}2D5_`89Z|Rt$8luc?Xe1`p>H2(`e$}Dfl*~nNY7P5$&d5 zD+4|BYjwb=W5q&rpeHD<-AY`0l(_aPaXsaW>#W46FRqSYh>6T1>zDBY?X{)gh4F^O zyf{8Vd?S+A+AD~4#+ESZh>Uhc)rLpLqZd%EzP&;nYi#Qry^Mg_%iJHNY-|bP|bF_-xM{pGa`XNv;pqx7RJg*l4E*n~qc`5zM zx2rTpyj_iB*A%kpv0!S~)=fi1a91=_Bg^KC1+Na#iR4FV<4=97&5)!vLcwv_U^g-@XpC&}^9(;5BM@^M5sqdSWWZ6vEOjQIXpUQU~S zOFR%I(nmX=5L^LV=Q(b`aubWI(ZlHha{GXiBQZ+G zR1Oa!Bncyk3H9Tor%bDr$64>BjBO1xk3qCFezF3^&((~J|W*aw$h$Ys68it4%xw8 z4)1X=NtJLOb+Si)qu8`g>C$zYX{>}8Q9HQ;(W*B>F{n4IMR>-kzuI5<>nPR9UpGV~ zSEUgre1}tO#$+i@P}(|IB8e2=cF!ly&9hni(m9XW ztPQESVd*Yw*RajXxA+7L_vwZ$-1QAwxbZX#w=EGFv~b%WZ^XhK%D0ZKh4XCIG!mHU zOZ%(ZyCQ|!xXpS?NEeiP zC%wjE>e?t2ne>{Hk7ZAKjpbC@dUj(_gO>`7qR}cP>2>HyrS(!Vlm(BcDVGYw6BcGs z`G}wI>Ef(1B}ti-ADxqrWoMNY`C?uBUYAvFERj`KmXBS2G|q+wVZ~WxR;r66R#}vf zWoMOj`C@Taxv4}}*=`T3#K~zEm8;z9W<b0sXHs&-S>CZp)d;O zgnb{{AAfI8<)u_cbgo`K%eka_7BXY5j0noRWWCmF2cwnGa?qknd040Fepsc?{|EJ6 zc7MiHO>~=@E}hCKp>hJfd3VHIZw2s#YY$~jPD9yKuPUuLrG8YP>D(_#@I zk^VYB)6h*6mm2*?^;uYeRD!07NVOP170;Vrp~eymD|LOPswsssOI7R#KU}e2kkNaT zYUx#~<&;t_r+wA3AeSDjWXq^t(wLq44B}9OVfA9|O>ML43Mey@Tw5$zw;D`mlOCz5 zT4Aiyg&zv1p#sW=a60belw~Ged1_sC%`6=#kE&1}viWNQK8@|7-A0SvTtfKPhJ|o5 zpAhbS#xwjc9w8j|8OC3Fb{l^pgvxOR3%(`U34A8zL1o8h(}WO;HMMrmI=Q#{PS52ZI>I?#0o>M^xV6!8cZVXe7ocIJw{g>o<@>&+|rw%c4b zYDBGM|MV}0C&1}NQ;G2^brY>l4ZxWb(Ar$XK}kYPN1__17wDh|BK-e0`*6k^pHnwp zs3Q{kd`M*f#1j*vde2n5jnVWCDp{iEGO+Ye{n*>k|0$kyV8pc z?(-kYXMnpj(>o62C$4a0*mD^d=|YfGlW}^D%Q)FQoEu732_A*I)qDy&%oRJ0bHzl1 zT(KGmv@BPQNIy8p6$|p2j9jrM-#WHj!OM_`SGawGW6RuVkXzomGUS;U35-o~sa_uT zNQq1;LoP!KW)V+~=*D+6CCHdB|l>%^2tv?DBf?mAl zPay&>f_*2F@#FSrM#hTv#Y8ef9s80bW6)S_%4aM=SOL3l^rT!^OT`6$qoCkF%FZ8T z#DvDO+iG&>4*(H|a*=?DnBc4O(1`@*WVmRye#oayILgN!Ev9QrM)~rxP!CBc-;$4o z*e^fI!>-00BB&81dwYXQc0N%$!2z9@OAopld-9o#N_HfHk53#>lKVc0l`$yZXq+o1 z8{~@FG_II^SjbI~E9Rv-%g7bel9#Ng9XGCMUXA^#q)n{Genis6VmO=qpd1SEC}n(z zQz73o{8&fn_(dNd1iJI5m06uGgqDOvSUy8p@_EMnPYEFfLdX1x{8p>!S@zUJNqdI1 zie%aE&k_LO4d$+V%hKYw8O(e#7Uqh%#<}922DxH9jVneoaK)m0CL>p@ z%eRg#S8!driqs9~>oe%mk|WL87ztu#J%6N`PYO78_B#tZd$N@sFlY(b2}}Lh;|<$_ zcQq*WqiIsV^HBZZX-I1Ij8Z=#-#WHZAExtc<8+>Gkk0dI?I^Y+iwAA~lH`Sqbl#9} z9a}o*({>NBu4365*4jhYw8JYSWm^_B=Hr_ss)XJ$I;`)U-gGyi)<2pQitXku#*|sb!^CM3*tlQt+pv=#v$^4RR-V~Ji1*sP@ z%KVyq>)6VC^Y(yd9u#&rwg)uhW0Q7J_Z@eNpe?p9YNeXE@r&Wmmr>3{c0N)H~YP9a`^f?7Cx5 zeLN00U+v*q%JrHsz3Bff6_IRwUc0&`B#65IF6w$^&y~@=K}B^%rD_fv!T6vXG1551 zA&lyS?(*3Fgp}xM1DB14DxTi}XGHtVP~`4J3-B~VFBZ(bFqrQPg84@VvP4iqirk^d zpL=92h@$rg=YEQXix=11;k#Ju@L2@e_)KlAVz>w!dh?PKuMj74llD|bK6C33JGg88 zdu+&$Ar?EMD=T@ED%>qqroxz+4Pxfc7*#NkH48p1`9%~&C-U(J^c;>s7Q&!>FbGOH z4Dt@Um7DSYHh=|~n(AMm$ISMZg>nJv5NFzBKqy7_PuQ{*a-Fd2)jTfTkRW#g7w&{f z|Dho1!zyeahiIw_8~Q>}jm!nXEP2-;t_EU^#==rR2u)zJ;`~4Ql_v53Q9$2qpgyz) zR7SS~M%UQDUBM^kt5qZL_E~M9KOAD4UNgj;H-x#^&`qa@xGywBt(FAWiZ^H&uKPoS z5?qVk5Mj9HLqjCPwdD;OhU+7tK?$yPZ-_8l4}^xO)$&#td{hquy(w~bq=VO(^-#sX zHyDMY&A4wU;Lc0UF`j2d7RD44=LLQNf&ZPZXlc*fr&oU#rzmnJ(9!pSis88a(z9B# zNUL&1pBZ)7f3{A^Sv>VlBb_;?PrcKhlzS(&XlBx{PrxM^k)K>jtJ4&qj!~+td-EQ{k9rINa(tLKnqfSh z^fAp}URtnLy9$Iw1AV@F(K!te{du8jSZKa2kBZ>DBbq*rEFY%M>XD(&$h(SD=M$Yr zokgUMWe`=ckV01&L>X<3QM*$u4Q0H;+Cy_z^q6;;$QE^Cfy;9WX z#zeuxz*_oS!*W{J8&jdbjgX|8A)}vZ&%r5CAtR%|w)Q11BfEs|lGyLBy3oL!yIz4* zXt5~UxL8~RE_Mk~=}F`0c1#+*Ctj%g#PoOTjjt_GryEpbP+^Ahm^+GF9|9vS9wil_}N{>V|_p3fkV z1~)d z0&e1C8WkNCiheGQI^#!%I(sEhXSMUF^Egrm{K^jYo}Q=+vKlBTA zfqb_YceTOY`C?rl-_w2|zl1;*ba&>p{)3^w-C5MX3wI}M(l(Eb(j2+3xJg^ri0&wp z_T^G&zszWlB+Wqk!y`lc=@MxFmCmF6SCRH%$y`?5hecMlQ*)BjA1^MM8=Xg;uazR1 zC}c1cXk{d62Fct$GPGYRf%aeTJlcPw6xy$9G9vAfq=NPZ?fo{>`MY{1F?v|5j9-0J zw8~BioVD3`ob^rQEE`>jy@)ACo%mkFAsNAv_9DU{%%p*^cE8c|C4o@lb_l|avbHd6 z+wn(cJEX*!W;KRzrm6T$VYDu!p><-uT(pKkSV{w7t0f?;q=7L1k#ez6BFPbMBsroH zRc-mqwaS z;0t~Wu%iwi=(0WAqrI(rvESAp)e6P|=+YzYk)%j_Q}q(2{p^vU{rD%0?kTX9wbgmF zf3h6fYceA3k)#=Dzj|b7KUV_npXxl?e+OwFmdwo~L!H$UsI%R9)cGz_r=V6wA%meH z?}sE6l6j;GIi4;BBil?@?d#tKMhfD4o{fG``sjx&lQ+a-{?y7+Ob%#&Bc9FKB;hG3 zl@j*qr!}kzAndmUgqbuDrWacgSj?t@u+Vxj2n!!8mk=dN62guAjc6479VYo++G3|lUTi^EXnaKFb#Q^J z*QwvjbhP$0CUEpI{ks@F9MlY7qrlL%r^72}XCE<)TOi%=J-|+frJ8m$NJUdki@J&) zX^$k$K>P6{L;KYdX#f4rqx}y`q5Y^PBhns8Drlekq|bDxvxPnBv;5I(SP!90Cw-p9 zqSCfzm!Bzx>`P4Kkz|7G1x?i~W2%+-5uJjgPqNYH_3r}qltOhwKkEy$p>lb*6!L8` z@+}`V6#NiT(AjkQQ7Lpe*k+^el`dwhZ1mmIVP9mU@5e_^VU8aoW%72` zJWT7XIrXTp1uz3M4H2FCj5I60n^H!d%H9l$eP}xDnroM#Q(- z)A~I+NRHi-kz?`cnFHv=5LE_EX8Tzrzr{`)!u10LVXC5<9a0|#*NN?Joe=7^?QXCP z@$AD-1FsEq^>;;G|0^^=)jqAMO{CtO(9L1|SEh+Ij%zN8h%6EiC-aYkr*3g#VK80V zoE{Uw52(5#K>9S}s(K3kwE-6%NvBpZEJAIK6aqkeSS zPM-Z0A~?4nKd%?v!2y`{;}0JY;kssg)fOeCNmD0;?uVst{w(87B$?pNf}Fp|MxTyz ze!cGf77!2A*$Fp=@?K;jBWLI-2q43#BL& zlrI=m>6~Lle)5sxB0mH^TZa`ET%|!$&3}`cK6Sue z+SLeTK?Xf!3_4l5#T#Z-JIK|7{R_gr%U~bXGnF~|qV}s%F^tE3?9OJ6HwQ>MDp)u!@Ll3eyBb3{6LzC-)=c|s zro$UtX=eFV+`D>oT+^YRRjet@Dx=riGR-)*PJXImSp~NMaIv@svDgw>Wn5zjXTmaY zF;f_=(`jfu>|C_s=^=TjH^aL4k{ETb&0K`gdJ9$I8GP3qspOko~cO+)MM zr#lv{yR2Ls*N|bcn`w)kS}u37VSI0=fv{dO2qiKXq7G#i*C6m+;!L|5LpT#2@@v*i z>ujcd{d==!T4pmHHg%@qx462h;ik@n{+}^faZjK`j#y-C!oq;2(TUBp9$!;fq}TOJ z3BLH$qpi>?n`t1dlng?Nlts9ahY*d;qU<)KES}XAGleO;pN7_j$67(z!!!^^K36UX zB~ljQM#|zLH-YaGXBuV^2@+INFYW87Pzm%Zy z4my`95pHBkJiOm5w9YfM&SgdGavEBvR?C(3u*O?W17Ya#azQ9j2_W1^Swy3tYTHZ8p=Q{$0!zM(chWS`RuGtz+y=6Rsh{VlkVTpbGbw$`u%O zw=r$}#cIIpH_@zL*M$XOsz5~pdcJzbTtR34?8ACD`u40iQB60>(nWf;zb^?0Z`L#6 zSP$><@)~c;qY!O+`V3< z5CMnTDQ3G^HZBQZ0K6D@%8`Y?=lXt}^j znvD0L6N(KMyB$JL143~qsE^&afmiuOaM`xTwJr2Rslmtp(bNq0SCABR`FO2FJ{+4i z=ET6=Vm@5;rq9BMdG*R$!ZiLwrP58hkBc)A5+(79!Dv1mMuWJQ4pakT^Ln8ML5QkO zdO?VoNL>-WWc`LP@OLsBk_^03+$loj3%Ee6<4e+6LBlc{hOc=7G(B2^0APdk{PT~YTd1DxbneE`SwZ&j&m%{gFRQ7^sGx;dBh8Z&!Q@c!mY?17f(B6WW=JG2rD zZnPEd?>b-Y8>pxsXF$25O$N_w?@{BK;U{1rX0E$SA7`;v9O`ON@U7kVUV=-RV=tK* z{&vs}10H~uFOrfALPq|7avjI~<7X;>BAt$oqj!x~XI`NctOu-mLJ*0)*Xo3=!| z&-pKB00)(*>rdg(4~}?Q3$bk5{e!y9b~cD!#%yOBXEw0kvl0X3GZ_52Re){LxQuRj z3KVRZTONcbx-N)w%c^!JkW3l5MWe-as8`-Dz7IrOkRU@GB3)c19NI?W8{ibjg`)uB zp2l$`S-v{oZG zd0rmVaTxldstU=C_2-OlLt^CnHYHoDaS8H?wE|BzR~QJ?)WIX+q5C6*HVj7vfH#Rmy(SUM*?nBXT)8@x8$^B zZ+1&*lO-FvS%BPXOZH#m8JR0hJ|ZpEg6SL;$ZBW&x4QezyeK54JXV>7NS{6LV^r6Q!I)$5&!c~+KAt3^Py~+ zvW!7+FcX$B$YmQI@WzZG3Tbv9Wq zHs}yDV)_!$B8PZOg6!KQKbaF`gOl`)QehG45|b~9XWlv`eKS1fnT{4Z#3yMIsqPY) z<+vpEC)>zuonaMbBnIjy^_idCCaW+nL2k8kc@mwrAv#_2Y2HGsP_kpaDVLHhI%Of9 zb*xXU)r-tp9Z1gc-C>>=qXC~?n zVg#*|sAI%zlYEc7H8p9|>_lCY^Zjqv+*7M%RwEmws*#B>^Omee79|O@sgY-nkQzBC zu14MwrbK6|k*yd(>!=Y%%r>c!Jqfb!+cjH_>{P0iD=Ytun>?^ZN1inuUb9u*ef0`$ z`!W`6{Hv3Ib>9Y4(Ue4WL`2*OB#LcLG9y|xU2YLL7d#B*vufZJ-SYtbR&z1D$y; z+3_A57iJ-wE`2(nOW_hFdjKO`O~Wb)^^p==6J-|K=jxK+q?K_!f~n+sCrEUGko7vK z$wg-f;H-~urgVaZFbvsk62JusvadCp?HG3wXW=nDbF3_yG_uRYyC! zCHtWcQo%Z21Qncy$69B|&1?++by5`!_id7!MG11N<>rr=+~_-6o!n@;M{6WENdB#F z@mmg~J5X(wEJj-rC)rYnUkr%RLmebW8oMAyIndf6QZ;;=uhr^E6(dDfsd`4I%-&Q# zWfpcw8#v?qZ@OK|3|!MCkurnhV*Qmr?53>QKO|+%#!|CpccOH}S{bw{K$!RG=$RyD ztl&Jm(f3aV#Hy3rxK0ib)_jE53lJExvkFehM@Kg$$gMUqYsmIb6puP z9gH^RS}qq2YJ!R`g;!{MYXt|>nK0X&D zDb?q+%0Z#dD07*Ws*%JCtyTd^oRzrnC6Vh_zzoAvF3fmRh}yQ>)3z(jo`hSSCvS%g@PI&*zy+h>pL=dS8W=72{ECWTCk*p>^A?n86_?p==ddgYPg+_^INNx-gdQVHo=wpap6FZu~Oh?Pe}9tb1+t+zWi1= zT*TGi<8*n*$M#iMk`;QM1rz7$dFG3Gi$axOWT*8RR7? zsqtFr+J)>^CvAhEJa=X_%c>-y+FG*=$n}}sb9%zUhK&@=g*+jPrfps6)zRe1z8%NQUe-3FLwV`9&g-Eh<=^WBmtV zXTV;ub+_JxN=pUXoj$`B;H2-q7dAnZemB-Uu}2{oXZ;)=TmTPU|AMdC9))-7B$3_C z0vAZ-^;@$qwjbj;XSYgp#lxDSc~R8xq)@kwL{T3Mq`0O6nH$GU_Q+dl^*ekc&-lc_ z++DoFT!&D^bmATg15GnesrR-4zn&D<5a7C#d9qaZ&N3~bsbd8ghsQYh|mZelp~)ubYwU5SHi zMLH~$ux?_f?xw^w6|*;XHznt_NuAP;bLtIqtesslJ`N3Swb4j zj>|F@axacVUB|Y>g>RI(tCb-UndEqR1{oc%w$yd(%k@(HhHkR&UU@DFXA_%qzB>>` z{8A^CwVWfdn~NSdHInvz?}@*v z9do*pyCv+nA?cReC?v&Io*#My652Zw6Mn?SLM$GJ+tN42y;)5~^Ag$zaxK0`?M07j zw@tW|ZZ6 z^gy@zQL`m*aI|K3O4ur3BbJVesftFEQ<#FG27A%u4DN9E_jq^i1$GSSx-7A+eMvN( zxMPTV$ea%`g|W4=yp3>Kk0p|69Y}?|n}GvmfgRnZ)Z)hulx;~$mz;RCyTPMGTX{k! z&u;L$6KN}qXN$DKD68#Ay<2k8tele6iFF&a@ka6xtlM}`7zrhx+aJAKh(AH5lX7tr zVsdjo`Ywns7Czf8!J$C$g2R?oS{bvBig}^Ai28BH9*heHKJhI-R-6ED49yu;BiRwQ zoG9_ADs56IaY+Q_4G=rTDro%NV`s#_b1{NCv(Ht#Efr#wxr_;*Qy>>C}Q z4TEe@ApUKU8fnoqrB~f5tb^KXI%r>c!bqR8-)yPpTBcBTUOnDLqAIQepE%i7L zV%*>uxcC_e3S6T(!k#H?GQ6KhFMKc?_ByKH*vPcd_jxn=%t6hnESi_mpO9;5Z$`g! z-CRnpc7}agltimvZ?NH>tWH%;p;p=!7BNy=vI;Y}!O0Jjkgh({V^6AYw+shzBC%fwdDW#)x9Et6%!f_}G3`k7_(i9j zRX};VYQkVcJ?83XRh}(rsCOV2*-7V^j(CzI+zrDgJ~h{DN%8#bdxgmdr>7~(4?{t} z*;(_7I~L`#8Y%ABdn#T9cyxkOX0&W@n$T&R_|1>RTf%=^l2Eyw?u^D4`LCn95$#D# zIyo7i3;&%fC1aYu>vfh2FU{Kg{@G>_byYVA0y zgBUR0&XrEcB-))AG*3wM_{N?iq<+xMv_MujrzJu2j9lbN&|KP)#10IaHzl!~rTkhQ zH1En~H4-#`J7A%#IYbftF_a*3a{^|(0?f80TphBlm#ns!R?-xeFCn)2{ zLMfCZkRP3tn8=$SWu8e^*=$~ZbXKm#PX_sR(+`=BMSiqRR&-0EKARPN`oxN+UGkFZ z)*ku@XF4lrMH#ZQN@~e&?Z|AZ()Gpj#I5bZDCXsHyLUF}RzEC}hOlQ|B0HNvve3u6 zwN9agQwB}Cbz;qjpC!6|PO+ZieI2e)Fz-rDaA=3PGpZE#V+eO83qgg#kliMQGW>zI zDwH-!#*AFGNq-nsp*>D_GQvv6drl;yVN<&rLwFs@V90KhWNb>1{rJXLpvT12mUU__ zZ0LMalKO5*LC@F+eO2dpu*jLOU^mv*6_icMWi^r;e>jjEe^Dh&jxpD-OZEUY))cM} zyJgKQquiFuYJ}^bc(HSROSJCDhkUIoHUl^}22E(jGD_q>b2k^oQ?-ujm@y$SkvC1q z*wr_qtuLdTk!xvhny@8&yet)t?+%v5$44ODy((#+myemV(SAPOlxt}(AGfqS((Zk} zUM|xwpaZ(mR`KpgA3B2Fk%s03cJs=}ymL+3FC$}eE$x+&7B%y2Q~gF+aY(qqtItZ* z=%S^1XI*j=*ilw?3fqarD(|h{8T#<>kS=Lzy!$w4u29!x|1eVXVw^3BDnG{YGEm$D zu@|SzIz?i4BaUihkFJrVC*4sI5ik4HX(?|He^_Y!l4EVl+k3@rDo95b-tMUQX-r}_ zuT5p5;48w`$4^soE$y|bZQ6ucmN>|^2{U!F3DfW<%uWp9&gGX@*jzWlkeyXzO0IV} zkRba}w`T&wg=PiHcu%~|!D#kZw`xzyZ~#<6=o&$_K}yAf*iViAJR`1_idpEETI9u8 zl-m?<_On=EX7aeABoQx|Hab3n`? zD<7v&osxV|lKOqR;t zT3~9mTsVIUf{3mQnuzo1`$Y)QcASrYtQj~jktt?g1Wd8nVN9{~BEb2`d&tS*e78CJhRPI*P*NgZQn=CZlF#Q_zgz7d)W{zRYvdBanrsBD z2f|?8qXQFMvAa7tV8{+0k+|T74B`=;xAzU2&OG7R(+b~VhYrYTWHPJC99zZ_SfJ=?Y1u$>(|hv$0n-yEl$3~M=lf&hIv z#vNLA?O6!U8gMK^Y{=P!LHm)?SQf?8S~iO^`OJ+&tYi_il@qC#>#{?OpXeV3&1EQ5 z{;j=#VCA>ypa92g96Srtu1_dN86PHUvKc)Lz$&rg{L?rrhJQ}+gi|S~dUv^~8vCfw zkz{O8UOe&vsz8N9;toxg{x+I9m>lYgDu&&oXO9LJOJ=zFd{{)x9TA2r8C4r6r~-L8 zI~WCX)k@1+HFj78RV8`{i=R934j?mSRC>_c1n*#W!PBH(eu3E_I8K$|9lVk9_=O{| z=~SWt02ohPWAt@-6AynXjay<9m&m7MsWUgafzp15tz0j5zq9ys{nPDYm#x&98)cXB z1Zi%$U6@%+ow-rW95+E)`B(`Gzr^I$*26x(Xp5DebA#MyC@E7O7w^TO($RwlRYZ2^ zxG~A_$4g+6@~APAD%s66&f}>wpXd|_3c!h6EQ4LzBSR%Ra*Iu|%f+3g}m#N>pTlaIm~v+*Yyh@Tz`%SUEqIqjLJW+?Pe7KCxJ z1u!m!VQij4pOrczgF@em@oOUry+k*8#iPr~uD$kr&R4~*{pf?8rDoLD5iqTb-V2S_z9s^UUypuh5y@b*=-teyuRW z3o)$m$m1kghRL$gC0|7q;`PGGvYl9YSq5HzG|cPmao)LvmAf&wPzJ3^v?k**m+3^p zz$fwYL|bK0twcw6{W0l3W^#1loshFtB3O$tX38M=pe#aQHR6ABu`M?~o&1!iV%uyO zH)5DR5!<-fuJ}~*d>BT=EW1dBoxqhw3?ooFBp=P=_1%X(UQfYVE1bZI7}idBJaC~)^fyzWd?Vc&GS5wKtnAOu#6&hlo?*lc@VK{K*SpAVxV zGmNt>fN?DhV|zl0d)X28azly3d=jq@7DDz_E6-@>@jHh6leXp=%r zVQae32v}bXgVi4G)1FzIsPmRf(0PtS3N!9dBmUNx!W_~ff9trh#CjPlQKA`KjIjha zGbc%XOzIz&LAB=Tnb9)9E0L-8W0vTIsp3h3`A15y4&SU)x~c2(MfI8}T@>oN>;76PBJT~^YzVh3|7Oq@kSF&WdRO6q&08MM4F~wvB=)H` z3%{4}YUk1c`v%h-$u=S?x$(-Dgsfht9}S&_r9^LGKh|q3gPXe^_7*y817YGbp5(FI zvzK3O$uX3%6MflLzi-R3Pc@HJjEKn_2;2xawks7>DD_mHr$Q3@t6k5UF26Cc=`zf= z`G`ypD5&%#qRNhR2iBL;6&7A$%a_9<+u@k%aPTq{a!0&crem#-RX=+V>S==>z5*s8rxK!oUqzs23I2 z7il?<0O2DhYuqw*IRsA=KUvgAh6aKxJ_y=Ebt z(rO3U*WB1@O0myhgaajh6aA&oPIn*tWzK(5~B8 z;1J6gmqgyd2iGd=Em8E6t}v}Jy>MnTtl4?IQ0~t5nm}QcdR#7XXZz2L4|l$L=G--k zyU~1|uNtR}{_H`5(4SpcL11hhtP4@|Jg7}*k$ucnROZNG8yYL{y>u^x*DRjupl662 zz8Pk_V@`t1VeWo_1aZ8R1x7BW7{e3rZ-p_<1-t_@J0-g=YmXH$Rhg-_@}aokG)T2? zhpCnsl2CdtCI$?@?=3!Cg8f&l0bQ?ASm*e6-bV57X)Rk zJW#${5R}dGKzX_#C?n9it|YeoUO`Zn$^&JmASl!2f%5$@C?)Rk4?$-?PC}XQX|!-8 zbJLAQZ+hO#BGr|1S+dkz>kq;REbe4*K>3|BbE}>~cYx{yM88Hh<|1JGNasaj?Hfv@ z@0^F=a_CzkfIFVFlmlR91|0S9!|7TE13uGg2HYuw0W+g-y~*g?Z8iEv9`7vq-GGLm zpf69E@w}~0 zxAM*QZ4Z53%1pZ-zM0E=7wV70D9jAwY71c83&YqvKXCGi>~I_97Qpz^FpSM3^J*DnF3}n7TC4rE!)Ua2aAE5$DVJdDE3WS+gh`9|dz1z{X-0gTUv zVQd~NZncyZH(J1o2dzfo&{_%7T%y_A^N?JQRVfj`WlxaG0Whn(usFbre! z1ZC_CC0LZqC_MDItQlnfbr^-2VH|4#jL#Q@akvFAz7U47d91ir1}m1R5;r^~m!q>Y z^WnBPeKTZb2#Pt`*+%GP3U!&aTJvapSO$$Vqj2p3Y1Ep5!mGk4%nai~3t+rD3}f@i zJp08GtV)TZJn>P<2<3=!i2#m!T+ndp=#H8g zL^mG7=i{l*^@{>?6qq+Zi%2hssSbe8m;UJ6#uh1 zkc20-2dZ>1$-E%6N`IA)WEvJcr59PN-BhjgT#3;q@C))y#f;*xZuus>aK<-!;l2Hk zcJBtL;74ts+wdH$bZ?lilppekt`ze>3ofz0n=?8z8sx80FB4*PzE)~i5z$(K*EB`! zH4t+#R;pP;_!`D?8?onz6k&z10_3O}Gl@Lkwej@gaqV(RIl*9hFF%t&v4 z<$Sd|(B0py#_8$r!Et)@I7p)Y?%%IoWT*v70Wq|LMDOoDUp;kBBNd-GU%l|0#yb6Z z_M9dQ{Tc4SLgGqKNlQY2N8d+$7>QJH_23)INL>{Dz@Q7(6us&1V0FJ+dFeoJe{a;I zP}8edW}b)R6ynuqa5)Lz?wWaFj9wTj;i(^{j`1S{T&;Fh#mFrXusG@v7+{OE<~0_B zKSn5=aK4tQj^UfE9=N^=L1I_ z>qe4W3YzVonT21YyZe#m9O&xrQu

-74V1rUrrpG~dYEMEgqrc{F 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 q>h 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