“To guarantee verifiable memory safety and prevent malicious code exploits, WebAssembly strictly prohibits arbitrary goto jumps. Instead, it enforces Structured Control Flow using block, loop, if/else, and branch instructions (br, br_if, br_table).”
Why Wasm bans arbitrary goto jumps in favor of structured block, loop, and branch labels.
(module
(func $sumToN (param $n i32) (result i32)
(local $i i32)
(local $sum i32)
(block $exit
(loop $repeat
;; if ($i == $n) break
(br_if $exit (i32.eq (local.get $i) (local.get $n)))
;; $i = $i + 1
(local.set $i (i32.add (local.get $i) (i32.const 1)))
;; $sum = $sum + $i
(local.set $sum (i32.add (local.get $sum) (local.get $i)))
;; continue loop
(br $repeat)
)
)
(local.get $sum)
)
(export "sumToN" (func $sumToN))
)const { instance } = await WebAssembly.instantiate(wasmBytes);
console.log('Sum 1..100:', instance.exports.sumToN(100)); // 5050block $B: A forward-branching construct. A branch (br $B) jumps OUT of the block to the end
loop $L: A backward-branching construct. A branch (br $L) jumps back to the TOP of the loop
Condition is evaluated on the stack and popped by br_if
Nested control structures validate operand stack balance statically before execution
Guarantees all branches are provably well-formed at compile time
Structured control flow allows the JIT engine to validate and verify 100% of branch targets in a single sequential linear pass without expensive graph analysis.