Skip to content

JavaScript FFI

Simon Fowler edited this page Sep 19, 2017 · 1 revision

As of the Dalry release, Links supports a Javascript "foreign function interface", allowing JS functions to be called from Links web applications.

Example

As an example, consider the following JavaScript code.

function _setTitle(s) {
  document.title = s;
}

function _alertBox(s) {
  alert(s);
}

var setTitle = LINKS.kify(_setTitle);
var alertBox = LINKS.kify(_alertBox);

_setTitle(s) and _alertBox(s) are direct-style functions. To fit in with the Links CPS calling convention, setTitle and alertBox should wrap the underscored direct-style functions in a call to LINKS.kify.

Now, we can write some Links code!

module Test {
  alien javascript "/js/test.js" {
    setTitle : (String) ~%~> ();
    alertBox : (String) ~%~> ();
  }
}

fun mainPage(_) {
  var _ = spawnClient {
    Test.setTitle("Hello!");
    Test.alertBox("Hola!")
  };

  page
    <html><body><h1>Hi!</h1></body></html>
}

fun main() {
  addRoute("/", mainPage);
  addStaticRoute("/js", "js", [("js", "text/javascript")]);
  servePages()
}

main()

Here, we define a module Test containing the following alien block:

alien javascript "/js/test.js" {
  setTitle : (String) ~%~> ();
  alertBox : (String) ~%~> ();
}

The block begins with the language (currently only javascript is supported), and a URL to the JavaScript file. Next, the block contains two lines containing the names and types for the foreign functions. This will bring them into scope, allowing them to be used in the remainder of the application.

For example, when the mainPage is run:

fun mainPage(_) {
  var _ = spawnClient {
    Test.setTitle("Hello!");
    Test.alertBox("Hola!")
  };

  page
    <html><body><h1>Hi!</h1></body></html>
}

a process will be spawned on the client which calls setTitle and alertBox in the Javascript.

Finally, to ensure that the JS file is served by the server, it's important to call addStaticRoute to make the js directory available:

  addStaticRoute("/js", "js", [("js", "text/javascript")]);

Plain Alien Syntax

Alien blocks are actually syntactic sugar. Sometimes, it may be concise to just use the following form:

alien javascript "/js/test.js" setTitle : (String) ~> ()

Higher-order functions

...to be continued