Skip to content
Divam edited this page Jul 24, 2018 · 4 revisions

Overview

JSaddle is an interface for JavaScript that works with GHCJS or GHC.

To make it work with WebGHC, an interface jsaddle-wasm backend is required.

Through this interface the JSON encoded messages (ByteString) will be transferred between the Haskell and JS side.

The JS side will have a decoder and interpreter to execute the JS code. Moreover the callbacks/events from browser should be transferred back to Haskell.

This interface will have following parts

  • Kernel / wasm.js support to facilitate HS/C/Wasm <-> JS communication, bi-directional

  • Haskell APIs to provide necessary interface to jsaddle, and the jsaddle.js part to actually execute the JS code

JS <-> HS communication

The communication can be done in following ways

  • Import API

    Wasm supports calling JS functions directly via C type FFI.

    This method is simple to use, but it requires specifying linker options, and special importObject.

  • Kernel level

    • Special Device like /dev/jsaddle_out, /dev/jsaddle_in

      The jsaddle-wasm can simply read/write to these special devices.

      and these kernel APIs will not use the usual browserfs, instead it will execute jsaddle.js

      • SYS_Open, SYS_Close
      • SYS_Write
      • SYS_Read
      • SYS_Poll / SYS_Select

      If the device-type is set as 'character device', then Haskell treats is as Stream

      Stream :: IODeviceType

      From Haddocks -> A duplex communications channel (results in creation of a duplex Handle). The standard libraries use this device type when creating Handles for open sockets.

      So a single FD can be used for both read and write.

      What about multi-process support with single kernel?

      • Perhaps use /dev/jsaddle_pid_out, /dev/jsaddle_pid_in
      • or just keep stuff isolated in kernel
    • Call special "driver" APIs

      Kernel level "driver" APIs can be implemented to do read/write in special ways.

      This approach might not be necessary, as we can implement the same functionality by simple SYS_Read/SYS_Write

API Design

  • JS side APIs

    This is mostly same as the existing code in other backends like jsaddle-warp.

  • Haskell APIs

    The jsaddle-wasm backend will implement the functionality to runJavaScript

runJavaScript :: (Batch -> IO ()) -> JSM () -> IO (Results -> IO (), Results -> IO Batch, IO ())

This internally does the implementation of JSContextRef.

data JSContextRef = JSContextRef {
    contextId              :: Int64
  , startTime              :: UTCTime
  , doSendCommand          :: Command -> IO Result
  , doSendAsyncCommand     :: AsyncCommand -> IO ()
  , addCallback            :: Object -> JSCallAsFunction -> IO ()
  , nextRef                :: TVar JSValueRef
  , doEnableLogging        :: Bool -> IO ()
  , finalizerThreads       :: MVar (Set Text)
  , animationFrameHandlers :: MVar [Double -> JSM ()]
  , liveRefs               :: MVar (Set Int64)
}

Clone this wiki locally