API
Main API
compile
is the main method exported by WebAssemblyCompiler.
WebAssemblyCompiler.compile
— Functioncompile(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 definesjsexports
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 offuns
.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.@jscall
— Macro@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.Externref
— TypeExternref()
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.console_log
— MethodApplies JavaScript's console.log
to show x
in the browser log. Returns nothing.
WebAssemblyCompiler.JS.escape
— Methodescape(x)
Replaces HTML-specific characters in the string x
with encoded versions. It converts '&', '"', ''', '<', and '>'.
WebAssemblyCompiler.JS.eval
— MethodEvaluate the JavaScript string x
. Returns an Externref
.
WebAssemblyCompiler.JS.getelementbyid
— MethodReturns a DOM object based on document.getElementById(x)
.
WebAssemblyCompiler.JS.h
— Methodh(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.object
— Methodobject(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.
WebAssemblyCompiler.JS.sethtml
— MethodSets the innerHTML of the DOM object ref
to str
.
WebAssemblyCompiler.JS.@esc_str
— Macroesc"..."
Uses escape
to fix up an HTML string.
Example
esc"An HTML string with problematic characters, including ', >, and &"
WebAssemblyCompiler.JS.Node
— TypeNode(tag::String, attrs::NamedTuple, children::Tuple)
Should not often be used directly. See h
.
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.CompilationContext
— Typeabstract 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.allow
— Functionallow(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.transform
— Functiontransform(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.