Two more engines that check or derive data rather than query it:
JSON Schema draft-07 structural validation
(JSONSchema.Validate.fst)
and XForms bind recalculation
(XForms.Bind.fst),
the "spreadsheet half" of XForms — an instance document plus a bind sheet
of calculate/constraint/type expressions, recomputed in dependency
order. Both run live below.
One schema, required: ["name"]:
personSchema = JSON.stringify({
type: "object",
required: ["name"],
properties: { name: { type: "string" } },
})
schemaAccept = await fn.jsonSchemaValidate(personSchema, JSON.stringify({ name: "Alice" }))
{ valid: true, result: "pass", errors: [] } — {name: "Alice"} has the
one required property, of the right type. Drop it:
schemaReject = await fn.jsonSchemaValidate(personSchema, JSON.stringify({}))
{ valid: false, result: "fail", errors: [...] } — the empty object is
missing name, so JSONSchema_Validate.validate returns VFail rather
than VPass. A schema keyword this validator doesn't yet implement
returns a third, distinct outcome, "unsupported" — never silently
folded into pass.
An instance with two inputs and one derived leaf, and a single bind
naming sum's calculate expression:
xformsInstance = "<data><a>2</a><b>3</b><sum>0</sum></data>"
xformsResult = await fn.xformsRecalc(xformsInstance, [{ target: "sum", calculate: "../a + ../b" }])
The recalculated instance carries <sum>5</sum> — ../a + ../b
evaluated with the sum leaf itself as the XPath context node, so ../
steps back up to its siblings. XForms_Bind.recalculate topologically
sorts binds by which instance nodes their calculate expressions read
before running any of them, so a calculate graph with a cycle is
rejected as a document error rather than looped forever — there's no
bind here that depends on sum itself, but a binds list that did would
fail the same way jsonSchemaValidate fails an instance: cleanly, with
a reason, not a hang.
Every live cell above is pinned in
tests/hub/post29_test.mjs.