Stateful Counter that renders to HTML
Server with initial HTML + Client side rendering:
The below HTML is rendered by the server. (Check with View Source). And then the
same
.wasm module is loaded in the browser for interactivity.
<output class="flex p-4 bg-gray-800">0</output>
<button data-action="increment" class="mt-4 inline-block py-1 px-4 bg-white text-black rounded">Increment</button>
Client-only rendering:
The initial HTML from the server is just a loader, with only the browser loading the wasm file:
<div>Loading…</div>
View CounterHTML
WebAssembly wat source
(module $CounterHTML
(memory (export "memory") 3)
(global $bump_offset (mut i32) (i32.const 65536))
(global $bump_mark (mut i32) (i32.const 0))
(global $count (mut i32) (i32.const 0))
(global $body_chunk_index (mut i32) (i32.const 0))
(data (i32.const 293) "</output>")
(data (i32.const 303) "\n<button data-action=\"increment\" class=\"mt-4 inline-block py-1 px-4 bg-white text-black rounded\">Increment</button>")
(data (i32.const 255) "<output class=\"flex p-4 bg-gray-800\">")
(func $alloc (param $size i32) (result i32)
(global.get $bump_offset)
(i32.add (global.get $bump_offset) (local.get $size))
(global.set $bump_offset)
)
(func $free_all
(i32.const 65536)
(global.set $bump_offset)
)
(func $get_current (export "get_current") (result i32)
(global.get $count)
)
(func $increment (export "increment") (result i32)
(i32.add (global.get $count) (i32.const 1))
(global.set $count)
(global.get $count)
)
(func $rewind (export "rewind")
(local $ptr i32)
(i32.const 0)
(global.set $body_chunk_index)
(i32.const 65536)
(global.set $bump_offset)
(i32.add (i32.const 64) (global.get $bump_offset))
(local.set $ptr)
(loop $Clear
(i32.store (local.get $ptr) (i32.const 0))
(i32.gt_u (local.get $ptr) (global.get $bump_offset))
(if
(then
(i32.sub (local.get $ptr) (i32.const 1))
(local.set $ptr)
(br $Clear)
)
)
)
)
(func $i32toa (param $value i32) (result i32)
(local $working_ptr i32)
(local $digit i32)
(i32.add (global.get $bump_offset) (i32.const 11))
(global.set $bump_offset)
(global.get $bump_offset)
(local.set $working_ptr)
(loop $Digits
(i32.sub (local.get $working_ptr) (i32.const 1))
(local.set $working_ptr)
(i32.rem_u (local.get $value) (i32.const 10))
(local.set $digit)
(i32.div_s (local.get $value) (i32.const 10))
(local.set $value)
(i32.store8 (local.get $working_ptr) (i32.add (i32.const 48) (local.get $digit)))
(i32.gt_s (local.get $value) (i32.const 0))
(br_if $Digits)
)
(local.get $working_ptr)
)
(func $next_body_chunk (export "next_body_chunk") (result i32)
(block $i32_match (result i32)
(i32.eqz (global.get $body_chunk_index))
(if
(then
(i32.const 255)
(br $i32_match) )
)
(i32.eq (global.get $body_chunk_index) (i32.const 1))
(if
(then
(call $i32toa (global.get $count))
(br $i32_match) )
)
(i32.eq (global.get $body_chunk_index) (i32.const 2))
(if
(then
(i32.const 293)
(br $i32_match) )
)
(i32.eq (global.get $body_chunk_index) (i32.const 3))
(if
(then
(i32.const 303)
(br $i32_match) )
)
(i32.const 0)
)
(i32.add (global.get $body_chunk_index) (i32.const 1))
(global.set $body_chunk_index)
)
)
Cache-Control HTTP Header
View CacheControl
Wat source (953 B wasm)
(module $CacheControl
(memory (export "memory") 2)
(global $bump_offset (mut i32) (i32.const 65536))
(global $bump_mark (mut i32) (i32.const 0))
(global $bump_write_level (mut i32) (i32.const 0))
(global $private (mut i32) (i32.const 0))
(global $public (mut i32) (i32.const 0))
(global $no_store (mut i32) (i32.const 0))
(global $immutable (mut i32) (i32.const 0))
(global $max_age_seconds (mut i32) (i32.const -1))
(global $s_max_age_seconds (mut i32) (i32.const -1))
(data (i32.const 255) "public")
(data (i32.const 279) ", ")
(data (i32.const 311) "max-age=0")
(data (i32.const 282) "max-age=")
(data (i32.const 270) "no-store")
(data (i32.const 262) "private")
(data (i32.const 291) "s-maxage=")
(data (i32.const 301) "immutable")
(func $alloc (param $size i32) (result i32)
(global.get $bump_offset)
(i32.add (global.get $bump_offset) (local.get $size))
(global.set $bump_offset)
)
(func $free_all
(i32.const 65536)
(global.set $bump_offset)
)
(func $memcpy (param $dest i32) (param $src i32) (param $byte_count i32)
(local $i i32)
(loop $EachByte
(i32.eq (local.get $i) (local.get $byte_count))
(if
(then
return )
)
(i32.store8 (i32.add (local.get $dest) (local.get $i)) (i32.load8_u (i32.add (local.get $src) (local.get $i))))
(i32.add (local.get $i) (i32.const 1))
(local.set $i)
(br $EachByte)
)
)
(func $memset (param $dest i32) (param $u8 i32) (param $byte_count i32)
(local $i i32)
(loop $EachByte
(i32.eq (local.get $i) (local.get $byte_count))
(if
(then
return )
)
(i32.store8 (i32.add (local.get $dest) (local.get $i)) (local.get $u8))
(i32.add (local.get $i) (i32.const 1))
(local.set $i)
(br $EachByte)
)
)
(func $streq (param $address_a i32) (param $address_b i32) (result i32)
(local $i i32)
(local $byte_a i32)
(local $byte_b i32)
(loop $EachByte (result i32)
(i32.load8_u (i32.add (local.get $address_a) (local.get $i)))
(local.set $byte_a)
(i32.load8_u (i32.add (local.get $address_b) (local.get $i)))
(local.set $byte_b)
(i32.eqz (local.get $byte_a))
(if
(then
(return (i32.eqz (local.get $byte_b)))
)
)
(i32.eq (local.get $byte_a) (local.get $byte_b))
(if
(then
(i32.add (local.get $i) (i32.const 1))
(local.set $i)
(br $EachByte)
)
)
(return (i32.const 0))
)
)
(func $strlen (param $string_ptr i32) (result i32)
(local $count i32)
(loop $EachChar
(i32.load8_u (i32.add (local.get $string_ptr) (local.get $count)))
(if
(then
(i32.add (local.get $count) (i32.const 1))
(local.set $count)
(br $EachChar)
)
)
)
(local.get $count)
)
(func $format_u32_char_count (param $value i32) (result i32)
(local $digit_count i32)
(local $digit i32)
(loop $Digits
(i32.add (local.get $digit_count) (i32.const 1))
(local.set $digit_count)
(i32.rem_u (local.get $value) (i32.const 10))
(local.set $digit)
(i32.div_u (local.get $value) (i32.const 10))
(local.set $value)
(i32.gt_u (local.get $value) (i32.const 0))
(br_if $Digits)
)
(local.get $digit_count)
)
(func $format_u32 (param $value i32) (param $str_ptr i32) (result i32)
(local $working_offset i32)
(local $last_offset i32)
(local $digit i32)
(i32.add (local.get $str_ptr) (call $format_u32_char_count (local.get $value)))
(local.set $last_offset)
(local.get $last_offset)
(local.set $working_offset)
(loop $Digits
(i32.sub (local.get $working_offset) (i32.const 1))
(local.set $working_offset)
(i32.rem_u (local.get $value) (i32.const 10))
(local.set $digit)
(i32.div_u (local.get $value) (i32.const 10))
(local.set $value)
(i32.store8 (local.get $working_offset) (i32.add (i32.const 48) (local.get $digit)))
(i32.gt_u (local.get $value) (i32.const 0))
(br_if $Digits)
)
(local.get $last_offset)
)
(func $bump_write_start
(i32.eqz (global.get $bump_write_level))
(if
(then
(global.get $bump_offset)
(global.set $bump_mark)
)
)
(i32.add (global.get $bump_write_level) (i32.const 1))
(global.set $bump_write_level)
)
(func $bump_write_done (result i32)
(i32.gt_u (global.get $bump_write_level) (i32.const 0))
(if
(then
nop )
(else
unreachable )
)
(i32.sub (global.get $bump_write_level) (i32.const 1))
(global.set $bump_write_level)
(i32.eqz (global.get $bump_write_level))
(if
(then
(i32.store8 (global.get $bump_offset) (i32.const 0))
(i32.add (global.get $bump_offset) (i32.const 1))
(global.set $bump_offset)
)
)
(global.get $bump_mark)
)
(func $bump_write_str (param $str_ptr i32)
(local $len i32)
(i32.eq (local.get $str_ptr) (global.get $bump_mark))
(if
(then
return )
)
(call $strlen (local.get $str_ptr))
(local.set $len)
(call $memcpy (global.get $bump_offset) (local.get $str_ptr) (local.get $len))
(i32.add (global.get $bump_offset) (local.get $len))
(global.set $bump_offset)
)
(func $bump_written? (result i32)
(i32.gt_u (global.get $bump_offset) (global.get $bump_mark))
)
(func $set_private (export "set_private")
(i32.const 1)
(global.set $private)
)
(func $set_public (export "set_public")
(i32.const 1)
(global.set $public)
)
(func $set_no_store (export "set_no_store")
(i32.const 1)
(global.set $no_store)
)
(func $set_immutable (export "set_immutable")
(i32.const 1)
(global.set $immutable)
)
(func $set_max_age (export "set_max_age") (param $age_seconds i32)
(i32.and (i32.ge_s (local.get $age_seconds) (i32.const 0)) (i32.le_s (local.get $age_seconds) (i32.const 100000000)))
(if
(then
nop )
(else
unreachable )
)
(local.get $age_seconds)
(global.set $max_age_seconds)
)
(func $set_shared_max_age (export "set_shared_max_age") (param $age_seconds i32)
(i32.and (i32.ge_s (local.get $age_seconds) (i32.const 0)) (i32.le_s (local.get $age_seconds) (i32.const 100000000)))
(if
(then
nop )
(else
unreachable )
)
(local.get $age_seconds)
(global.set $s_max_age_seconds)
)
(func $to_string (export "to_string") (result i32)
(call $bump_write_start)
(global.get $public)
(if
(then
(call $bump_write_str (i32.const 255)) )
(else
(global.get $private)
(if
(then
(call $bump_write_str (i32.const 262)) )
(else
(global.get $no_store)
(if
(then
(call $bump_write_str (i32.const 270)) )
) )
) )
)
(i32.gt_s (global.get $max_age_seconds) (i32.const 0))
(if
(then
(call $bump_written?)
(if
(then
(call $bump_write_str (i32.const 279)) )
)
(call $bump_write_str (i32.const 282))
(call $format_u32 (global.get $max_age_seconds) (global.get $bump_offset))
(global.set $bump_offset) )
)
(i32.gt_s (global.get $s_max_age_seconds) (i32.const 0))
(if
(then
(call $bump_written?)
(if
(then
(call $bump_write_str (i32.const 279)) )
)
(call $bump_write_str (i32.const 291))
(call $format_u32 (global.get $s_max_age_seconds) (global.get $bump_offset))
(global.set $bump_offset) )
)
(global.get $immutable)
(if
(then
(call $bump_written?)
(if
(then
(call $bump_write_str (i32.const 279)) )
)
(call $bump_write_str (i32.const 301)) )
)
(i32.eqz (call $bump_written?))
(if
(then
(call $bump_write_str (i32.const 311)) )
)
(call $bump_write_done)
)
)
Set-Cookie HTTP Header
View CacheControl
Wat source (824 B wasm)
(module $SetCookie
(memory (export "memory") 2)
(global $bump_offset (mut i32) (i32.const 65536))
(global $bump_mark (mut i32) (i32.const 0))
(global $bump_write_level (mut i32) (i32.const 0))
(global $name (mut i32) (i32.const 0))
(global $value (mut i32) (i32.const 0))
(global $domain (mut i32) (i32.const 0))
(global $path (mut i32) (i32.const 0))
(global $secure (mut i32) (i32.const 0))
(global $http_only (mut i32) (i32.const 0))
(data (i32.const 265) "; Path=")
(data (i32.const 255) "; Domain=")
(data (i32.const 282) "; HttpOnly")
(data (i32.const 273) "; Secure")
(func $alloc (param $size i32) (result i32)
(global.get $bump_offset)
(i32.add (global.get $bump_offset) (local.get $size))
(global.set $bump_offset)
)
(func $free_all
(i32.const 65536)
(global.set $bump_offset)
)
(func $memcpy (param $dest i32) (param $src i32) (param $byte_count i32)
(local $i i32)
(loop $EachByte
(i32.eq (local.get $i) (local.get $byte_count))
(if
(then
return )
)
(i32.store8 (i32.add (local.get $dest) (local.get $i)) (i32.load8_u (i32.add (local.get $src) (local.get $i))))
(i32.add (local.get $i) (i32.const 1))
(local.set $i)
(br $EachByte)
)
)
(func $memset (param $dest i32) (param $u8 i32) (param $byte_count i32)
(local $i i32)
(loop $EachByte
(i32.eq (local.get $i) (local.get $byte_count))
(if
(then
return )
)
(i32.store8 (i32.add (local.get $dest) (local.get $i)) (local.get $u8))
(i32.add (local.get $i) (i32.const 1))
(local.set $i)
(br $EachByte)
)
)
(func $streq (param $address_a i32) (param $address_b i32) (result i32)
(local $i i32)
(local $byte_a i32)
(local $byte_b i32)
(loop $EachByte (result i32)
(i32.load8_u (i32.add (local.get $address_a) (local.get $i)))
(local.set $byte_a)
(i32.load8_u (i32.add (local.get $address_b) (local.get $i)))
(local.set $byte_b)
(i32.eqz (local.get $byte_a))
(if
(then
(return (i32.eqz (local.get $byte_b)))
)
)
(i32.eq (local.get $byte_a) (local.get $byte_b))
(if
(then
(i32.add (local.get $i) (i32.const 1))
(local.set $i)
(br $EachByte)
)
)
(return (i32.const 0))
)
)
(func $strlen (param $string_ptr i32) (result i32)
(local $count i32)
(loop $EachChar
(i32.load8_u (i32.add (local.get $string_ptr) (local.get $count)))
(if
(then
(i32.add (local.get $count) (i32.const 1))
(local.set $count)
(br $EachChar)
)
)
)
(local.get $count)
)
(func $format_u32_char_count (param $value i32) (result i32)
(local $digit_count i32)
(local $digit i32)
(loop $Digits
(i32.add (local.get $digit_count) (i32.const 1))
(local.set $digit_count)
(i32.rem_u (local.get $value) (i32.const 10))
(local.set $digit)
(i32.div_u (local.get $value) (i32.const 10))
(local.set $value)
(i32.gt_u (local.get $value) (i32.const 0))
(br_if $Digits)
)
(local.get $digit_count)
)
(func $format_u32 (param $value i32) (param $str_ptr i32) (result i32)
(local $working_offset i32)
(local $last_offset i32)
(local $digit i32)
(i32.add (local.get $str_ptr) (call $format_u32_char_count (local.get $value)))
(local.set $last_offset)
(local.get $last_offset)
(local.set $working_offset)
(loop $Digits
(i32.sub (local.get $working_offset) (i32.const 1))
(local.set $working_offset)
(i32.rem_u (local.get $value) (i32.const 10))
(local.set $digit)
(i32.div_u (local.get $value) (i32.const 10))
(local.set $value)
(i32.store8 (local.get $working_offset) (i32.add (i32.const 48) (local.get $digit)))
(i32.gt_u (local.get $value) (i32.const 0))
(br_if $Digits)
)
(local.get $last_offset)
)
(func $bump_write_start
(i32.eqz (global.get $bump_write_level))
(if
(then
(global.get $bump_offset)
(global.set $bump_mark)
)
)
(i32.add (global.get $bump_write_level) (i32.const 1))
(global.set $bump_write_level)
)
(func $bump_write_done (result i32)
(i32.gt_u (global.get $bump_write_level) (i32.const 0))
(if
(then
nop )
(else
unreachable )
)
(i32.sub (global.get $bump_write_level) (i32.const 1))
(global.set $bump_write_level)
(i32.eqz (global.get $bump_write_level))
(if
(then
(i32.store8 (global.get $bump_offset) (i32.const 0))
(i32.add (global.get $bump_offset) (i32.const 1))
(global.set $bump_offset)
)
)
(global.get $bump_mark)
)
(func $bump_write_str (param $str_ptr i32)
(local $len i32)
(i32.eq (local.get $str_ptr) (global.get $bump_mark))
(if
(then
return )
)
(call $strlen (local.get $str_ptr))
(local.set $len)
(call $memcpy (global.get $bump_offset) (local.get $str_ptr) (local.get $len))
(i32.add (global.get $bump_offset) (local.get $len))
(global.set $bump_offset)
)
(func $bump_written? (result i32)
(i32.gt_u (global.get $bump_offset) (global.get $bump_mark))
)
(export "alloc" (func $alloc)) (func $set_cookie_name (export "set_cookie_name") (param $new_value i32)
(local.get $new_value)
(global.set $name)
)
(func $set_cookie_value (export "set_cookie_value") (param $new_value i32)
(local.get $new_value)
(global.set $value)
)
(func $set_domain (export "set_domain") (param $new_value i32)
(local.get $new_value)
(global.set $domain)
)
(func $set_path (export "set_path") (param $new_path i32)
(local.get $new_path)
(global.set $path)
)
(func $set_secure (export "set_secure")
(i32.const 1)
(global.set $secure)
)
(func $set_http_only (export "set_http_only")
(i32.const 1)
(global.set $http_only)
)
(func $to_string (export "to_string") (result i32)
(call $bump_write_start)
(call $bump_write_str (global.get $name))
(i32.store8 (global.get $bump_offset) (i32.const 61))
(i32.add (global.get $bump_offset) (i32.const 1))
(global.set $bump_offset)
(call $bump_write_str (global.get $value))
(i32.gt_s (call $strlen (global.get $domain)) (i32.const 0))
(if
(then
(call $bump_write_str (i32.const 255))
(call $bump_write_str (global.get $domain)) )
)
(i32.gt_s (call $strlen (global.get $path)) (i32.const 0))
(if
(then
(call $bump_write_str (i32.const 265))
(call $bump_write_str (global.get $path)) )
)
(global.get $secure)
(if
(then
(call $bump_write_str (i32.const 273)) )
)
(global.get $http_only)
(if
(then
(call $bump_write_str (i32.const 282)) )
)
(call $bump_write_done)
)
)
View $Form
Wat source
(module $Form
(global $edited (export "edited") i32 (i32.const 1))
(global $submitting (export "submitting") i32 (i32.const 2))
(global $succeeded (export "succeeded") i32 (i32.const 3))
(global $failed (export "failed") i32 (i32.const 4))
(global $initial (export "initial") (mut i32) (i32.const 0))
(global $state (mut i32) (i32.const 0))
(global $edit_count (mut i32) (i32.const 0))
(global $submitted_edit_count (mut i32) (i32.const 0))
(func $get_current (export "get_current") (result i32)
(global.get $state)
)
(func $get_edit_count (export "get_edit_count") (result i32)
(global.get $edit_count)
)
(func $get_submitted_edit_count (export "get_submitted_edit_count") (result i32)
(global.get $submitted_edit_count)
)
(func $user_can_edit? (export "user_can_edit?") (result i32)
(i32.eqz (i32.eq (global.get $state) (global.get $submitting)))
)
(func $user_can_submit? (export "user_can_submit?") (result i32)
(i32.eqz (i32.eq (global.get $state) (global.get $submitting)))
)
(func $user_did_edit (export "user_did_edit")
(i32.eq (global.get $state) (global.get $initial))
(i32.eq (global.get $state) (global.get $edited))
(i32.or)
(i32.eq (global.get $state) (global.get $succeeded))
(i32.or)
(i32.eq (global.get $state) (global.get $failed))
(i32.or)
(if
(then
(global.get $edited)
(global.set $state)
(i32.add (global.get $edit_count) (i32.const 1))
(global.set $edit_count)
)
)
)
(func $user_did_submit (export "user_did_submit")
(i32.eqz (i32.eq (global.get $state) (global.get $submitting)))
(if
(then
(global.get $submitting)
(global.set $state)
(global.get $edit_count)
(global.set $submitted_edit_count)
)
)
)
(func $destination_did_succeed (export "destination_did_succeed")
(i32.eq (global.get $state) (global.get $submitting))
(if
(then
(global.get $succeeded)
(global.set $state)
)
)
)
(func $destination_did_fail (export "destination_did_fail")
(i32.eq (global.get $state) (global.get $submitting))
(if
(then
(global.get $failed)
(global.set $state)
)
)
)
)
Promise State Machine
View $Promise
Wat source
(module $Promise
(global $state (mut i32) (i32.const 0))
(global $change_count (mut i32) (i32.const 0))
(global $pending (export "pending") i32 (i32.const 0))
(global $resolved (export "resolved") i32 (i32.const 1))
(global $rejected (export "rejected") i32 (i32.const 2))
(func $transition_to (param $new_state i32)
(local.get $new_state)
(global.set $state)
(i32.add (global.get $change_count) (i32.const 1))
(global.set $change_count)
)
(func $get_change_count (export "get_change_count") (result i32)
(global.get $change_count)
)
(func $get_current (export "get_current") (result i32)
(global.get $state)
)
(func $resolve (export "resolve")
(i32.eq (global.get $state) (global.get $pending))
(if
(then
(call $transition_to (global.get $resolved))
)
)
)
(func $reject (export "reject")
(i32.eq (global.get $state) (global.get $pending))
(if
(then
(call $transition_to (global.get $rejected))
)
)
)
)
Dialog State Machine
View $Dialog
Wat source
(module $Dialog
(global $state (mut i32) (i32.const 0))
(global $change_count (mut i32) (i32.const 0))
(global $closed? (export "closed?") i32 (i32.const 0))
(global $open? (export "open?") i32 (i32.const 1))
(func $transition_to (param $new_state i32)
(local.get $new_state)
(global.set $state)
(i32.add (global.get $change_count) (i32.const 1))
(global.set $change_count)
)
(func $get_change_count (export "get_change_count") (result i32)
(global.get $change_count)
)
(func $get_current (export "get_current") (result i32)
(global.get $state)
)
(func $open (export "open")
(i32.eq (global.get $state) (global.get $closed?))
(if
(then
(call $transition_to (global.get $open?))
)
)
)
(func $close (export "close")
(i32.eq (global.get $state) (global.get $open?))
(if
(then
(call $transition_to (global.get $closed?))
)
)
)
(func $cancel (export "cancel")
(i32.eq (global.get $state) (global.get $open?))
(if
(then
(call $transition_to (global.get $closed?))
)
)
)
)
Offline Status State Machine
View $OfflineStatus
Wat source
(module $OfflineStatus
(global $state (mut i32) (i32.const 0))
(global $change_count (mut i32) (i32.const 0))
(global $offline? (export "offline?") i32 (i32.const 0))
(global $online? (export "online?") i32 (i32.const 1))
(global $listen_to_window (export "listen_to_window") i32 (i32.const 256))
(func $transition_to (param $new_state i32)
(local.get $new_state)
(global.set $state)
(i32.add (global.get $change_count) (i32.const 1))
(global.set $change_count)
)
(func $get_change_count (export "get_change_count") (result i32)
(global.get $change_count)
)
(func $get_current (export "get_current") (result i32)
(global.get $state)
)
(func $online (export "online")
(i32.eq (global.get $state) (global.get $offline?))
(if
(then
(call $transition_to (global.get $online?))
)
)
)
(func $offline (export "offline")
(i32.eq (global.get $state) (global.get $online?))
(if
(then
(call $transition_to (global.get $offline?))
)
)
)
)