The ShEx WASI extension is a generic semantic-action
extension: the action's code is a program — the
WebAssembly Text (WAT)
source of a WASI command module — run
once per invocation with the evaluation context passed as WASI
argv. Whatever the module prints to WASI fd 1 is
collected as the extension's results; the module's exit status is the
verdict. Because the module imports only
wasi_snapshot_preview1, the same semantic actions run
under any conforming WASI host, in any ShEx implementation, in any
language.
A schema may carry Test and WASI actions
side by side (implementations fire the actions of extensions they
register and skip the rest), so the two suites can share test
schemas:
<http://a.example/S1> { <http://a.example/p1> . %<http://shex.io/extensions/Test/>{ print(s) %} %<http://shex.io/extensions/WASI/>{ (func $main (call $println_s)) %} %<http://shex.io/extensions/Test/>{ print(p) %} %<http://shex.io/extensions/WASI/>{ (func $main (call $println_p)) %} %<http://shex.io/extensions/Test/>{ print(o) %} %<http://shex.io/extensions/WASI/>{ (func $main (call $println_o)) %} }
<http://a.example/s1> <http://a.example/p1> <http://a.example/o1> .
Validating <http://a.example/s1> against
<http://a.example/S1> with the WASI
extension registered collects:
{
"prints": [
"http://a.example/s1",
"http://a.example/p1",
"http://a.example/o1"
]
}
The evaluation context arrives as command arguments:
argv[0] = "http://shex.io/extensions/WASI/"
argv[1…] = one "<letter>=<value>" per in-scope binding:
s=, p=, o= the matched triple's terms (TripleConstraint actions)
n= the focus node (Shape and NodeConstraint actions)
Start actions run with no bindings. Term values are serialized as
in the Test extension: the term's lexical
value, except literals with a non-xsd:string datatype,
which appear in Turtle form
("1"^^http://www.w3.org/2001/XMLSchema#integer).
Whatever the module writes to fd 1 is collected; each
newline-terminated line (plus any unterminated tail at exit) is
appended to the extension's results
(in shex.js,
validator.semActHandler.results["http://shex.io/extensions/WASI/"]).
0 | success |
1 | failure — validation treats the action as failed; lines printed before exiting are still recorded (like Test's fail()) |
2 and up | invocation error — the implementation throws (e.g. the library's binding accessors exit 2 when the binding is absent) |
A trap or a WAT compilation error is also an invocation error.
ShExC code blocks reserve % and \, so WAT
embedded in a schema writes them \% and
\\ (a WAT string's \0a newline escape
becomes \\0a). The parser unescapes before the
extension sees the text.
The code takes one of two forms:
(module is compiled as-is: a self-contained WASI
command importing only wasi_snapshot_preview1;
prelude.wat):
the prelude supplies the WASI imports, exported memory, argv
loading and print helpers, and an exported _start that
calls the author's (func $main …).
The prelude text is part of this extension's definition: any host performing the same composition runs the same actions. Its helpers:
$put (ptr len) | write bytes to fd 1 |
$nl () | write "\n" |
$println (ptr len) | $put then $nl |
$put_s $put_p $put_o $put_n | write a binding's value (exit 2 if absent) |
$println_s $println_p $println_o $println_n | ditto, newline-terminated |
$fail () | exit 1 — a failed action |
$strlen (ptr) → len | NUL-terminated string length |
Author data segments start at offset 8192; below that is
the prelude's argv and scratch space.
The prelude as defined makes WASI a competent
reporting extension — everything the
Test extension's print/fail
grammar expresses is a few library calls. To be useful as a
gating semantic action — one that passes or fails validation
based on the content of the bound terms — authors need more
than print helpers: comparing binding values against literals,
datatype-aware numeric comparison, substring/regex tests, perhaps
date arithmetic. Writing these from scratch in WAT for every action
is not realistic; the extension should adopt some standard set of
libraries (further prelude functions, or a convention for importing
shared modules) to make gating actions practical.
Community input on the shape and scope of that library set is
very much appreciated — as are opinions on accepting binary
(.wasm) actions alongside WAT, and on tracking WASI
preview 2 / the component model.
node:wasi). Its test suite re-codes every
shexTest
validation test bearing the SemanticAction trait with
parallel WASI actions and verifies both extensions
produce identical results.