v0.7.0
Minor Changes
-
Breaking: WASM plugins must return a packed
i64from all data-returning exports (filter,shortcode,hook,hooks,last_error). The return value packs a pointer and length into a single 64-bit integer:result = (ptr << 32) | len.Alloy rejects the previous multi-value
(result i32 i32)form at load time with an error naming the export and its actual signature. The sret form ((param i32 i32 i32) -> ()produced by Rust >= 1.82 and TinyGo tuple returns) is also rejected.The packed form works with current Rust, TinyGo, and AssemblyScript without unstable compiler flags:
#[no_mangle] pub extern "C" fn filter(ptr: i32, len: i32) -> u64 { // ... transform input ... ((result_ptr as u64) << 32) | (result_len as u64) }//export filter func filter(ptr, length int32) uint64 { // ... transform input ... return (uint64(resultPtr) << 32) | uint64(resultLen) }export function filter(ptr: i32, len: i32): u64 { // ... transform input ... return (u64(resultPtr) << 32) | u64(resultLen); }The previous multi-value ABI required hand-written WAT because no mainstream toolchain could produce two separate
i32return values through stable compiler flags. This change makes WASM plugins practical for Rust, TinyGo, and AssemblyScript. See WASM Plugins for complete examples.
Patch Changes
-
Fix WASM and Node hooks losing
url,path, andfrontMatterwhen chained with other hooks on the same event. A QuickJS hook chaining after a WASM or Node hook received only the mutable field (htmlorcontent) — context fields were dropped. All three runtimes now preserve context through the full hook chain. -
Fix plugin filter and shortcode errors being silently swallowed during template rendering. A filter that throws now fails the build with the filter name and source file path in the error message, instead of passing through the original input unchanged. Shortcode errors fail instead of producing empty output.
Previously,
{{ "hello" | myFilter }}wheremyFilterthrew an exception would silently outputhello.
Migration notes
WASM plugins — update all data-returning exports from (result i32 i32) to (result i64) with bit packing:
;; Before (v0.6.x)
(func $filter (export "filter") (param $ptr i32) (param $len i32) (result i32 i32)
local.get $ptr
local.get $len
)
;; After (v0.7.0)
(func $filter (export "filter") (param $ptr i32) (param $len i32) (result i64)
local.get $ptr
i64.extend_i32_u
i64.const 32
i64.shl
local.get $len
i64.extend_i32_u
i64.or
)
Modules using the old ABI fail at load time with a clear error. No silent fallback.