API

Main API

compile is the main method exported by WebAssemblyCompiler.

WebAssemblyCompiler.compileFunction
compile(funs::Tuple...; filepath = "foo.wasm", jspath = filepath * ".js", names = nothing, validate = true, optimize = false, experimental = true)

Compile the methods defined by funs. Each function definition to be compiled is a tuple with the first entry as the function followed by argument types. Keyword arguments include:

  • filepath–File path for the WebAssembly binary. The path will be created if it doesn't exist.
  • jspath–File path for the extra JavaScript file that defines jsexports which are the JS functions imported into WebAssembly (those normally defined by @jscall).
  • names–A vector or other indexable object with names of functions that are compiled. It's length must equal the length of funs.
  • validate–Apply Binaryen's validation tests.
  • optimize–Apply Binaryen's default optimization passes (still shaky).
  • experimental–Use experimental WebAssembly features.

compile also writes a WebAssembly text tile to the same path as filepath with an added ".wat" extension.

Examples:

compile((exp, Float64), filepath = "exp.wasm", optimize = true)   
compile((acos, Float64), (asin, Float64), filepath = "trigs.wasm", optimize = true)

Debugging is often needed when trying to fix code to make it compile.

You can enable debugging output using:

WebAssemblyCompiler.debug(x)

where x is :inline to display debugging information at the REPL or :offline do store information in WebAssemblyCompiler.DEBUG. Outputs from that are stored in WebAssemblyCompiler.DEBUG, include:

  • Julia IR for each method compiled
  • WebAssembly code generated for each statement

JavaScript interoperability

WebAssemblyCompiler provides several utilities to ease interoperability with the browser. The main way to call JavaScript methods is with @jscall (exported):

WebAssemblyCompiler.@jscallMacro
@jscall(fun, rettype, tt, args...)

Call a JavaScript function fun. fun is a string and normally includes the JavaScript function definition. Under the hood, these use Base.llvmcall. All @jscall definitions are imported from JavaScript.

rettype, tt, ang args... all follow the Base.llvmcall format. tt is a Tuple type (not a regular Tuple).

Arguments are converted to the types specified in tt. The following types can be included: String, Int64, Int32, UInt64, UInt32, Float64, Float32, Char, Bool, UInt8, and Int8. For all other types, specify Externref. Externref types are converted with JS.object.

Examples: @jscall("x => alert(x)", Nothing, Tuple{String}, x) d = @jscall("() => getElementById('someid')", Externref, Tuple{}) @jscall("d => d.innerHTML = 'hello world'", Nothing, Tuple{Externref}, d)

@jscall is used extensively in quirks.jl and javascript-interop.jl.

Objects on the JavaScript side are accessed using the Externref type (exported):

WebAssemblyCompiler.ExternrefType
Externref()

A type representing an external object in the host system (JavaScript). This object can be passed around, but no direct operations are supported. The object can be passed back to JavaScript methods. To convert a Julia object to an Externref, use JS.object.

The module JS provides several utility functions to help with browser interoperability. The JS module is exported, but its methods are not.

WebAssemblyCompiler.JS.escapeMethod
escape(x)

Replaces HTML-specific characters in the string x with encoded versions. It converts '&', '"', ''', '<', and '>'.

WebAssemblyCompiler.JS.hMethod
h(tag, children...; kw...)
h.tag(children...; kw...)
h.tag."classes"(children...; kw...)

Create an html node with the given tag, children, and kw attributes.

Examples

h.div("child", class="myclass", id="myid")
# <div class="myclass" id="myid">child</div>

h.div."myclass"("content")
# <div class="myclass">content</div>

Adapted from Cobweb. h uses the same API as Cobweb.h, except for getindex with symbols. For WebAssemblyCompiler.h, the following are equivalent:

h.div."myclass"("content")
h.div.myclass("content")

Note that strings are not encoded, so be sure not to include problematic HTML characters like <. Use escape or esc"..." to fix strings with problematic characters.

WebAssemblyCompiler.JS.objectMethod
object(x)

Return an Externref (JavaScript object) representing the Julia object x. This is useful for transfering arrays, named tuples, and other objects to JavaScript.

The types Int32, Float32, Float64, Bool, and Externref are passed straight through.

Overlays

It is common to need to swap out problematic parts of code when compiling to WebAssembly. The compilation pipeline uses Base.Experimental.@overlay to methods to be redefined. Here is an example of redefining Base.log10:

using Base.Experimental: @overlay
@overlay WebAssemblyCompiler.MT Base.log10(x::Float64) = @jscall("(x) => Math.log10(x)", Float64, Tuple{Float64}, x)

WebAssemblyCompiler.MT is the MethodTable that is used during compilation.

Redefinitions built into WebAssemblyCompiler are defined in quirks.jl. Many math functions are replaced by JavaScript versions. Many error functions are also replaced.

Mixtape support

Overlays are the most common way to manipulate code for compilation. More advanced manipulation is possible with Mixtape support built in.

Mixtape support is considered experimental and not part of the official API. This support has not been tested extensively.

Mixtape is enabled using the following methods and types (none are exported):

WebAssemblyCompiler.CompilationContextType
abstract type CompilationContext end

Parametrize the Mixtape pipeline by inheriting from CompilationContext. Similar to the context objects in Cassette.jl. By using the interface methods transform – the user can control different parts of the compilation pipeline.

WebAssemblyCompiler.allowFunction
allow(f::CompilationContext, args...)::Bool

Determines whether the user-defined transform is allowed to look at a lowered Core.CodeInfo or Core.Compiler.IRCode instance.

The user is allowed to greenlight modules:

allow(::MyCtx, m::Module) == m == SomeModule

or even specific signatures

allow(::MyCtx, fn::typeof(rand), args...) = true
WebAssemblyCompiler.transformFunction
transform(ctx::CompilationContext, b::Core.CodeInfo)::Core.CodeInfo
transform(ctx::CompilationContext, b::Core.CodeInfo, sig::Tuple)::Core.CodeInfo

User-defined transform which operates on lowered Core.CodeInfo. There's two versions: (1) ignores the signature of the current method body under consideration and (2) provides the signature as sig.

Transforms might typically follow a simple "swap" format using CodeInfoTools.Builder:

function transform(::MyCtx, src)
    b = CodeInfoTools.Builder(b)
    for (k, st) in b
        b[k] = swap(st))
    end
    return CodeInfoTools.finish(b)
end

but more advanced formats are possible. For further utilities, please see CodeInfoTools.jl.

Binaryen utilities

Binaryen binary utilities from Binaryen_jll such as wasm-dis are available in WebAssemblyCompiler.Bin.

This is not official API in terms of semver. Each release of WebAssemblyCompiler targets a specific version of Binaryen. There are no compatibility guarantees between versions of Binaryen. These are unlikely to change though.

LibBinaryen

The C interface to Binaryen is provided through WebAssemblyCompiler.LibBinaryen.

This is not official API in terms of semver. Each release of WebAssemblyCompiler targets a specific version of Binaryen. There are no compatibility guarantees between versions of Binaryen.