From f561ddbcef2c4febf4e70c6ae971c1d0045bcb73 Mon Sep 17 00:00:00 2001 From: Mihaela Mihaljevic Date: Thu, 25 Jun 2026 05:47:51 +0200 Subject: [PATCH] chore(release): stamp 0.4.0 (#284) Performance across all three benchmarked operations plus one XSD conformance fix, all backward compatible. Versus libxml2 on the 20k-item generated corpus: parse ~30x -> ~9x, serialize ~5.5x -> ~2.7x, xpath ~13x -> ~5.5x. The fix rejects an xsi:type that reaches a union declared type through a blocked member (XSTS invalid-instances-accepted 15 -> 14, valid-rejected held at 0). Verified against the full local suite (1695 tests), the Apache Xalan XSLT gold-output corpus, the W3C XML conformance corpora, the RELAX NG spec suite, the full W3C XSTS archive, and the WASM build. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9bd938..1cf1b56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.4.0] - 2026-06-25 + ### Fixed - An `xsi:type` substitution blocked by `block`/`blockDefault` is now rejected even when the substitute reaches the declared type through a union member rather than along its own base chain (cvc-elt.4.3 with cos-st-derived-OK clause 2.2.4: a type validly derived from a union member is validly derived from the union, and the `{disallowed substitutions}` apply to the derivation method used to reach that member). Previously the block check followed only the named base chain, found no path from the substitute to the declared union, and stayed silent, so a substitution reaching a union member by a blocked method was wrongly accepted (W3C XSTS `elemT074`: `block="restriction"` on the element, the `xsi:type` restricting a union member). A name-keyed union-member table is recorded during schema compilation and the block check now follows a derivation through a member; it adds a rejection only on a positively confirmed path, so an unresolved or inline-anonymous member leaves the check silent rather than risk a false positive. This drops XSTS `invalid-instances-accepted` 15 -> 14 while holding `valid-schemas-rejected` and `valid-instances-rejected` at 0 (full XSTS archive, the false-positive direction the production bar guards hardest). The member clause is existential (cos-st-derived-OK 2.2.4): the substitution is barred only when EVERY confirmed derivation path to a member is blocked, so a substitute that is itself a union member, or reaches one member by an unblocked method, is accepted whatever other members it also reaches by a blocked method. Disclosed under-rejection (bounded, not silent): only a union's DIRECT `memberTypes` are recorded, not flattened, so a substitution reaching the declared union through a member that is ITSELF a union (a nested-union member-of-a-member path) is not blocked; this can only under-reject (accept an invalid substitution), never over-reject, because an unmodeled path yields no confirmed derivation and the check stays silent rather than guess. Guarded by `SchemaXSITypeUnionMemberBlockTests`, which checks the rejection, that a non-blocked method (and no block) still accepts the valid substitution, and that a substitute which is itself a member is accepted even when listed after another member it derives from by a blocked method (the over-rejection an adversarial review caught and this design rules out).