@@ -102,15 +102,31 @@ When compiled with GHC this code will run a Warp web server you can connect to a
102102
103103## How does it work on GHC
104104
105−As of version 0.5 it runs a small warp server that provides [index.html](https://github.com/ghcjs/jsaddle/blob/master/data/index.html) and
106−[jsaddle.js](https://github.com/ghcjs/jsaddle/blob/master/data/jsaddle.js). The [jsaddle.js](https://github.com/ghcjs/jsaddle/blob/master/data/jsaddle.js) code connects to the server using WebSockets and processes JSON commands from the server and sends the result back over the same WebSocket.
105+There are a number of different JSaddle runners to choose from
107106
108−### Why use WebSockets?
107+* [jsaddle-warp](https://hackage.haskell.org/package/jsaddle-warp) - runs JSaddle in a warp server with a web browser connected to it.
108+* [jsaddle-webkit2gtk](https://hackage.haskell.org/package/jsaddle-webkit2gtk) - runs JSaddle in a WebKitGTK window.
109+* [jsaddle-wkwebview](https://hackage.haskell.org/package/jsaddle-wkwebview) - runs JSaddle in a WKWebView on iOS or macOS.
110+* [jsaddle-clib](https://hackage.haskell.org/package/jsaddle-clib) - C interface used to run JSaddle on Android using JNI.
109111
110−Older versions relied on WebKitGTK and JavaScriptCore, but in WekKit2 the interface JSaddle used is only available to WebKit Extensions
111−so most of the benefits of this interface are lost (extensions are not in the same process as Gtk and RPC would have been needed).
112−The general advice for people migrating from WebKit1 to WebKit2 seems to be to use JavaScript. There is an interface in WebKit2
113−to send JavaScript code from the host application, but it does not seem to provide any advantages over the WebSockets approach.
112+In all of these cases a web control or browser of some sort is used. An
113+[HTML file](https://github.com/ghcjs/jsaddle/blob/master/data/index.html)
114+and a [small JavaScript command interpreter](https://github.com/ghcjs/jsaddle/blob/master/data/jsaddle.js)
115+are loaded into it. Then the native GHC compiled JSaddle code runs. In order to interact with the browser
116+it sends commands to the JavaScript command interpreter. The mechanism for sending the commands differs
117+for the different runners, but they are always combined into batches and encoded in JSON.
118+
119+Haskell callbacks from JavaScript are supported by sending JSON back from the command interpreter. These can be synchronous (blocking the
120+JavaScript thread until the Haskell callback completes) or asynchronous.
121+
122+### Why use a JavaScript command interpreter?
123+
124+Older versions of JSaddle relied on the WebKit1 interface to WebKitGTK and JavaScriptCore that is only supported in older versions of
125+WebKitGTK. With the newer WekKit2 interface this level of access is only available to WebKit Extensions.
126+The general advice for people migrating from WebKit1 to WebKit2 seems to be to use JavaScript.
127+
128+As a bonus we have been able to support a number of different platforms with the JavaScript command interpreter and it should
129+be easy to support more in the future.
114130
115131### JSVal
116132
@@ -161,7 +177,7 @@ force all the pending asynchronous commands to be executed.
161177It uses a handful of JS FFI calls to execute JavaScript functions indirectly. This indirection will be small compared to the overhead of the WebSockets approach (used when JSaddle is compiled with GHC), but it will be significant compared to hand crafted JS FFI calls.
162178
163179For the best performance you may want to write both JS FFI and JSaddle wrappers
164−For your JavaScript code. This is the approach taken by recent versions of `ghcjs-dom`.
180+For your JavaScript code. This is the approach taken by `ghcjs-dom`.
165181
166182For instance here is `getElementById` from the `ghcjs-dom-jsffi` (used by `ghcjs-dom` when compiled with GHCJS)
167183
@@ -200,3 +216,6 @@ When using GHC the Haskell executions will probably continue for a while before
200216When it reaches the synchronous command a haskell type JSException will be thrown (this may not be the thread that initiated the
201217command that caused the exception). You can use `syncPoint` and `syncAfter` to force the exception to be thrown.
202218There are `JSM` versions of `catch` and `bracket` that also include a `syncPoint` call.
219+
220+## Building with Stack
221+The `jsaddle-webkit2gtk` runner can be difficult to build with stack. See [this issue](https://github.com/ghcjs/jsaddle/issues/38#issuecomment-331392995) if you get stuck.