| Copyright | (C) 2016-2026 David M. Johnson |
|---|---|
| License | BSD3-style (see the file LICENSE) |
| Maintainer | David M. Johnson <code@dmj.io> |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Miso.DSL
Description
Overview
Miso.DSL is the low-level JavaScript interop layer for miso. It provides the marshaling typeclasses, JS value types, and combinators needed to call browser APIs and exchange data with JavaScript from Haskell.
Most miso users never import this module directly — higher-level modules (Miso.FFI, Miso.Canvas, Miso.Fetch, etc.) build on top of it. Import it directly when writing custom FFI bindings or inline JS.
Marshaling
Two typeclasses handle the Haskell ↔ JavaScript boundary:
ToJSVal— converts a Haskell value into aJSVal. Instances exist for all primitive types, lists, tuples (up to 6),Maybe, andMapMisoString. Product record types can deriveToJSValviaGHC.Generics(sum types are not supported).FromJSVal— parses aJSValback into Haskell, returning(MaybeaNothingon type mismatch or missing field). UsefromJSValUncheckedwhen the shape is guaranteed by the caller. Product record types can deriveFromJSValviaGHC.Generics.
Two auxiliary classes support the calling convention:
ToArgs— marshals a Haskell value to a[argument list. Tuples up to arity 6 automatically produce the correct positional list.JSVal]ToObject— promotes a value to a JSObjectfor use as thethisreceiver in method calls.
Accessing the global scope
-- Read a global variable x <-jsg"innerWidth" -- globalThis.innerWidth -- Call a global functionjsg0"requestAnimationFrame" -- no argsjsg1"parseInt" ("42" ::MisoString) -- one argjsgf"encodeURIComponent" args -- arbitrary ToArgs
Property access and method calls
obj!"name" -- get obj.name :: IO JSVal obj!!3 -- get obj[3] :: IO JSVal obj#"push" [val] -- call obj.push(val) :: IO JSValsetFieldobj "x" 10 -- obj.x = 10getProp"x" obj -- obj.xsetProp"x" 10 obj -- obj.x = 10
Object creation
o <-create-- new empty object {} o <-createWith[("x", 1), ("y", 2)] -- { x: 1, y: 2 } v <-newconstructor args -- new Constructor(...args)
Callbacks
Wrap a Haskell IO action as a JS function. Variants ending in '
return the JSVal of the callback's return value.
cb 'syncCallback' action -- () - () cb1 'syncCallback1' (\x - …) -- (x) -> () cb2 'syncCallback2' (\x y - …) -- (x, y) -> ()
Always free callbacks when they are no longer needed to avoid leaks:
freeFunction cb
See also
- Miso.FFI — higher-level browser API wrappers built on this module
- Miso.FFI.QQ — the
[js| … |]quasi-quoter for inline JavaScript - Miso.Canvas — canvas 2D API using
ToArgsandToJSVal
Synopsis
- class ToJSVal a where
- class GToJSVal (f :: Type -> Type) where
- class FromJSVal a where
- class GFromJSVal (f :: Type -> Type) where
- gFromJSVal :: Object -> IO (Maybe (f a))
- class ToArgs args where
- class ToObject a where
- data JSVal
- newtype Object = Object {}
- newtype Function = Function {
- unFunction :: JSVal
- jsg :: MisoString -> IO JSVal
- jsg0 :: MisoString -> IO JSVal
- jsg1 :: ToJSVal arg => MisoString -> arg -> IO JSVal
- jsg2 :: (ToJSVal arg1, ToJSVal arg2) => MisoString -> arg1 -> arg2 -> IO JSVal
- jsg3 :: (ToJSVal arg1, ToJSVal arg2, ToJSVal arg3) => MisoString -> arg1 -> arg2 -> arg3 -> IO JSVal
- jsg4 :: (ToJSVal arg1, ToJSVal arg2, ToJSVal arg3, ToJSVal arg4) => MisoString -> arg1 -> arg2 -> arg3 -> arg4 -> IO JSVal
- jsg5 :: (ToJSVal arg1, ToJSVal arg2, ToJSVal arg3, ToJSVal arg4, ToJSVal arg5) => MisoString -> arg1 -> arg2 -> arg3 -> arg4 -> arg5 -> IO JSVal
- jsgf :: ToArgs args => MisoString -> args -> IO JSVal
- global :: JSVal
- (#) :: (ToObject object, ToArgs args) => object -> MisoString -> args -> IO JSVal
- setField :: (ToObject o, ToJSVal v) => o -> MisoString -> v -> IO ()
- (<##) :: (ToObject o, ToJSVal v) => o -> Int -> v -> IO ()
- (!) :: ToObject o => o -> MisoString -> IO JSVal
- listProps :: Object -> IO [MisoString]
- call :: (ToObject obj, ToObject this, ToArgs args) => obj -> this -> args -> IO JSVal
- new :: (ToObject constructor, ToArgs args) => constructor -> args -> IO JSVal
- create :: IO Object
- createWith :: ToJSVal val => [(MisoString, val)] -> IO Object
- setProp :: ToJSVal val => MisoString -> val -> Object -> IO ()
- getProp :: ToObject o => MisoString -> o -> IO JSVal
- eval :: MisoString -> IO JSVal
- requestAnimationFrame :: JSVal -> IO Int
- cancelAnimationFrame :: Int -> IO ()
- freeFunction :: Function -> IO ()
- (!!) :: ToObject object => object -> Int -> IO JSVal
- isUndefined :: ToJSVal val => val -> IO Bool
- isNull :: ToJSVal val => val -> IO Bool
- jsNull :: JSVal
- syncCallback :: IO () -> IO JSVal
- syncCallback1 :: (JSVal -> IO ()) -> IO JSVal
- syncCallback2 :: (JSVal -> JSVal -> IO ()) -> IO JSVal
- syncCallback3 :: (JSVal -> JSVal -> JSVal -> IO ()) -> IO JSVal
- syncCallback' :: IO JSVal -> IO JSVal
- syncCallback1' :: (JSVal -> IO JSVal) -> IO JSVal
- syncCallback2' :: (JSVal -> JSVal -> IO JSVal) -> IO JSVal
- syncCallback3' :: (JSVal -> JSVal -> JSVal -> IO JSVal) -> IO JSVal
- asyncCallback :: IO () -> IO JSVal
- asyncCallback1 :: (JSVal -> IO ()) -> IO JSVal
- asyncCallback2 :: (JSVal -> JSVal -> IO ()) -> IO JSVal
- asyncCallback3 :: (JSVal -> JSVal -> JSVal -> IO ()) -> IO JSVal
- apply :: (FromJSVal a, ToArgs args) => Function -> args -> IO a
Classes
class ToJSVal a where Source #
A class for marshaling Haskell values into JS
Minimal complete definition
Nothing
Methods
Instances
class GToJSVal (f :: Type -> Type) where Source #
Instances
| GToJSVal (U1 :: Type -> Type) Source # | |
| GToJSVal (V1 :: Type -> Type) Source # | |
| (GToJSVal a, GToJSVal b) => GToJSVal (a :*: b) Source # | |
| (TypeError ('Text "Sum types unsupported") :: Constraint, GToJSVal a, GToJSVal b) => GToJSVal (a :+: b) Source # | |
| GToJSVal a => GToJSVal (C1 i a) Source # | |
| GToJSVal a => GToJSVal (D1 i a) Source # | |
| (ToJSVal a, Selector s) => GToJSVal (S1 s (K1 i a :: Type -> Type)) Source # | |
class FromJSVal a where Source #
A class for marshaling JS values into Haskell
Minimal complete definition
Nothing
Instances
class GFromJSVal (f :: Type -> Type) where Source #
Instances
| GFromJSVal (U1 :: Type -> Type) Source # | |
| GFromJSVal (V1 :: Type -> Type) Source # | |
| (GFromJSVal a, GFromJSVal b) => GFromJSVal (a :*: b) Source # | |
| (TypeError ('Text "Sum types unsupported") :: Constraint, GFromJSVal a, GFromJSVal b) => GFromJSVal (a :+: b) Source # | |
| GFromJSVal a => GFromJSVal (C1 i a) Source # | |
| GFromJSVal a => GFromJSVal (D1 i a) Source # | |
| (FromJSVal a, Selector s) => GFromJSVal (S1 s (K1 i a :: Type -> Type)) Source # | |
class ToArgs args where Source #
A class for creating arguments to a JS function
Instances
class ToObject a where Source #
A class for creating JS objects.
Minimal complete definition
Nothing
Methods
Instances
| ToObject ImageData Source # | |
| ToObject Object Source # | |
| ToObject JSVal Source # | |
| ToObject Date Source # | |
| ToObject Date Source # | |
| ToObject File Source # | |
| ToObject FileReader Source # | |
Defined in Miso.FFI.Internal | |
| ToObject Image Source # | |
| ToObject URLSearchParams Source # | |
Defined in Miso.FFI.Internal | |
| ToObject URI Source # | |
| ToObject VTree Source # | |
| ToJSVal a => ToObject (IO a) Source # | |
| ToObject (Array value) Source # | |
| ToJSVal a => ToObject (Map MisoString a) Source # | |
Types
A type that represents any JS value
A JS Object
A JS Functionn
Constructors
| Function | |
Fields
| |
Utils
Arguments
| :: (ToJSVal arg1, ToJSVal arg2) | |
| => MisoString | Global function name on |
| -> arg1 | First argument |
| -> arg2 | Second argument |
| -> IO JSVal |
Invokes a function with 2 arguments
Arguments
| :: (ToJSVal arg1, ToJSVal arg2, ToJSVal arg3) | |
| => MisoString | Global function name on |
| -> arg1 | First argument |
| -> arg2 | Second argument |
| -> arg3 | Third argument |
| -> IO JSVal |
Invokes a function with 3 arguments
jsg4 :: (ToJSVal arg1, ToJSVal arg2, ToJSVal arg3, ToJSVal arg4) => MisoString -> arg1 -> arg2 -> arg3 -> arg4 -> IO JSVal Source #
Invokes a function with 4 arguments
jsg5 :: (ToJSVal arg1, ToJSVal arg2, ToJSVal arg3, ToJSVal arg4, ToJSVal arg5) => MisoString -> arg1 -> arg2 -> arg3 -> arg4 -> arg5 -> IO JSVal Source #
Invokes a function with 5 arguments
Arguments
| :: ToArgs args | |
| => MisoString | Global function name on |
| -> args | Arguments to pass to the function |
| -> IO JSVal |
Invokes a function with a specified argument list
(#) :: (ToObject object, ToArgs args) => object -> MisoString -> args -> IO JSVal infixr 2 Source #
Calls a JS function on an Object at a field with specified arguments.
Arguments
| :: (ToObject o, ToJSVal v) | |
| => o | JavaScript object to mutate |
| -> MisoString | Field name to set |
| -> v | Value to assign |
| -> IO () |
Sets a field on an Object at a specified field
(<##) :: (ToObject o, ToJSVal v) => o -> Int -> v -> IO () infixr 1 Source #
Sets a field on an Object at a specified index
Arguments
| :: (ToObject obj, ToObject this, ToArgs args) | |
| => obj | The function object to call |
| -> this | The |
| -> args | Arguments to pass to the function |
| -> IO JSVal |
Calls a JS function on an Object at a field with specified arguments.
Arguments
| :: (ToObject constructor, ToArgs args) | |
| => constructor | JavaScript constructor function (e.g. |
| -> args | Constructor arguments |
| -> IO JSVal |
Instantiates a new JS Object.
createWith :: ToJSVal val => [(MisoString, val)] -> IO Object Source #
Creates a new JS Object populated with key-value pairs specified
in the list. Meant for use with inline JS functionality.
update = case
Highlight domRef -> do
3 <- inline "hljs.highlight(domRef); return 3;" =<<
createWith [ "domRef" =: domRef ]
pure ()
Arguments
| :: ToJSVal val | |
| => MisoString | Property name to set |
| -> val | Value to assign |
| -> Object | Target JavaScript object |
| -> IO () |
Sets a property on a JS Object
Arguments
| :: ToObject o | |
| => MisoString | Property name to read |
| -> o | JavaScript object to read from |
| -> IO JSVal |
Retrieves a property from a JS Object
eval :: MisoString -> IO JSVal Source #
Dynamically evaluates a JS string. See eval
`eval()` is slower (not subject to JS engine optimizations) and also has security vulnerabilities (can alter other local variables).
Consider using the more performant and secure (isolated) inline function.
cancelAnimationFrame :: Int -> IO () Source #
freeFunction :: Function -> IO () Source #
Frees references to a callback
syncCallback2 :: (JSVal -> JSVal -> IO ()) -> IO JSVal Source #
A synchronous callback with two arguments
syncCallback3 :: (JSVal -> JSVal -> JSVal -> IO ()) -> IO JSVal Source #
A synchronous callback with three arguments
syncCallback1' :: (JSVal -> IO JSVal) -> IO JSVal Source #
A synchronous callback that takes a single argument and returns a value
syncCallback2' :: (JSVal -> JSVal -> IO JSVal) -> IO JSVal Source #
A synchronous callback that takes two arguments and returns a value
syncCallback3' :: (JSVal -> JSVal -> JSVal -> IO JSVal) -> IO JSVal Source #
A synchronous callback that takes three arguments and returns a value
asyncCallback2 :: (JSVal -> JSVal -> IO ()) -> IO JSVal Source #
A asynchronous callback with two arguments