Wren

Developers

Write a page

Two ways to write a page: JavaScript, as anywhere, or WebAssembly alone. Wren runs a page's scripts, classic or modules, and what it does not implement is simply absent. Or the page names a module that exports wb_main and calls the browser through the generated Odin SDK; the whole API, with its ABI, is in docs/api.

The same page, two ways

fetchpage/main.odin
package fetchpage

import "wren:core"
import "wren:dom"
import "wren:fetch"
import "wren:net"

out: dom.Element

// called once the document is parsed
@(export)
wb_main :: proc "contextless" () {
	out = dom.Document_getElementById("out")

	// fetch(url): a Promise of the Response
	p, err := fetch.promise("message.txt")
	if err != .None { dom.Node_setTextContent(out, "fetch refused"); return }
	core.Promise_then(p, on_response)
}

on_response :: proc "contextless" (user: i32, p: core.Promise, st: core.PromiseState) {
	if st == .Rejected { dom.Node_setTextContent(out, "network error"); return }
	resp := net.Response(core.Promise_value(p))
	core.Promise_then(fetch.Response_text(resp), on_text)   // response.text()
}

on_text :: proc "contextless" (user: i32, p: core.Promise, st: core.PromiseState) {
	buf: [4096]u8
	text, _ := core.Promise_text(p, buf[:])
	dom.Node_setTextContent(out, text)
}
the same page in JavaScript
<script>
fetch("message.txt")
  .then((r) => r.text())
  .then((text) => { document.getElementById("out").textContent = text; })
  .catch(() => { document.getElementById("out").textContent = "network error"; });
</script>
index.html
<!doctype html>
<meta charset="utf-8">
<title>Fetch, from Wasm</title>
<script type="application/wasm" src="fetchpage.wasm"></script>
<pre id="out">…</pre>
build (from a clone of the repository)
odin build fetchpage -target:freestanding_wasm32 -no-entry-point ^
  -default-to-nil-allocator -collection:wren=sdk/odin ^
  -out:fetchpage.wasm -o:size

The module above compiles to 1,135 bytes; it is examples/fetchpage, and the tests load it as written here. Put a message.txt beside index.html and open the page in Wren. For the JavaScript version, put the script at the end of the page instead of the module.

What a page can use

The web API

58 modules, 1,482 functions: DOM, events, timers, fetch, WebSocket, workers, storage, URL and encoding. Described once in api/*.widl, generated for Odin (a package per area: import "wren:dom", "wren:fetch"...), documented with its ABI for other languages.

JavaScript, if you want it

Classic scripts, ES modules and import maps, defer and async, document.write, inline handlers and javascript: URLs. A member Wren does not implement is absent, so feature detection tells the truth.

No build step for the page

Wren loads file:/// addresses and Windows paths as well as HTTPS. A page can be one .wasm module and one HTML file, opened from disk.