Tcl distribution for Webassembly or Javascript
This is a Tcl distribution for WebAssembly
(webassembly.org). It enables Web
developers to embed a Tcl interpreter in the browser and integrate Tcl with
JavaScript. It enables Tcl developers to use their tools and language of choice
to create client side web applications. It enables all developers to reuse a
great and (over decades) grown code base of useful packages and scripts, such
as Tcllib,
to be used in web browsers.
It is an extension of the Emtcl project from Aidan Hobsen, which can be found here. But Wacl takes things a few steps further: it integrates a fully featured Tcl interpreter into the webpage and adds the following features:
- A main tclsh interpreter and capability to get it via JavaScript
- An event loop to process all Tcl events (timer events, fileevents, custom events)
- Client sockets. The socket -async ... command connects to
websocket servers with the binary protocol. Then the resulting handle
can be used to transmit binary data as with normal TCP sockets.
- The Tcl library: modules and packages in the Emscripten virtual filesystem. You can add your own packages!
- Proper initialization via Tcl_Init()
- An extension to call javascript functions from Tcl
- various useful extensions (see below for a list and comments)
The code compiles fine with Emscripten 1.37.9 to JavaScript and WebAssembly. The latter is the preferred format: WebAssembly is only half the size of the JavaScript "asm.js" output (~1.4MB vs. 2.9MB) and at least twice as fast! However, that could induce incompatibilities with older browsers, which don't (yet) support WebAssembly.
Extensions
The following extensions are included in Wacl
- wacl native extension with commands wacl::dom and wacl::jscall
- tDOM for parsing and creating
XML and HTML content
- json
and
json::write
from tcllib
- html from tcllib
- javascript from tcllib
- ncgi (as a dependency for html)
- rl_json 0.9.7
(Tcl_ObjType for efficiently parsing and creating JSON to/from Tcl dicts)
More extensions can easily be included and used. C extensions can be compiled with Emscripten (with USE_TCL_STUBS disabled and statically initialized via waclAppInit()) and Tcl extensions can be included in the library virtual filesystem.
But be aware that including extensions is a tradeoff: for the additional
functionality you pay with a larger download size. The really useful tDOM
extension for instance increases the Wacl distribution by not less than 400kB,
which must be downloaded to the users client when (s)he wants to run a
wacl based application, and this can be painful with lower bandwidth. Thus it
is better to limit the number of packages to what is necessary rather than to
build a batteries included distribution which contains everything.
Getting excited
You can try it out here. You can
download the precompiled version with the index page to play on your own
webpage here.
Both of these pages require a recent browser with webassembly support:
- Mozilla Firefox >= 52.0
- Google Chrome >= 57.0
- Microsoft Edge (Windows 10 "Creators" update)
- Opera
A websocket echo server demo is (tbd).
Getting started
wasmTcl will compile on a Unix/Linux environment with the following tools installed:
- the Emscripten SDK (installation is documented on the web page)
- make, autoconf
- diff, patch
- fossil (best grab a prebuilt binary, if it doesn't come with your distribution already)
fossil clone https://fossil.e-lehmann.de/wacl wacl.fossil
fossil open wacl.fossil
This will checkout the files in the current directory. There is a Makefile with the build steps and a README with instructione. The make procedure does merely download the tcl core sources, apply a small patch and configure & build the interpreter to a webassembly plus accompanying .data + .js files. These files can be deployed to the corresponding web source directories. The Emscripten SDK must be on the PATH (i.e. via source $EMSCRIPTEN/emsdk_set_env.sh). Once wasmTcl is built, it can be used in any browser which supports webassembly, also on Windows.
The build system can be changed to produce javascript instead of webassembly, by simply removing the -s WASM=1 flag from the BCFLAGS variable in the Makefile. This will generate a larger (~2.8MB), yet minified .js output, which is slower at runtime, but compatible with browsers that don't support webassembly.