[svgwg] 16.3.2 fragment grammar vs. implemented handling of `svgView()` combined with `xywh=` (and other disallowed combinations) (#1112)

karlcow has just created a new issue for https://github.com/w3c/svgwg:

== 16.3.2 fragment grammar vs. implemented handling of `svgView()` combined with `xywh=` (and other disallowed combinations) ==
[SVG2 §16.3.2][grammar] defines the fragment grammar:

```
SVGFragmentIdentifier ::= BareName *( "&" timesegment ) |
                          SVGViewSpec *( "&" timesegment ) |
                          spacesegment *( "&" timesegment ) |
                          timesegment *( "&" spacesegment )

BareName     ::= XML_Name
SVGViewSpec  ::= 'svgView(' SVGViewAttributes ')'
spacesegment ::= [media-frags] xywh=...
timesegment  ::= [media-frags] t=...
```

Read strictly, this grammar admits exactly four shapes. In particular, `SVGViewSpec & spacesegment`, for example`#svgView(viewBox(0,0,100,100))&xywh=100,0,100,100`,  is **not** in any production. The same is true of `BareName & spacesegment`, `spacesegment & spacesegment`, and `spacesegment & SVGViewSpec`. A fragment outside the grammar is malformed and (by analogy with [media-frags §4.2][media-frags] error handling) should be ignored, with the document rendered as if no fragment were present.

### What implementations actually do

Tested 2026-05-20 with Firefox 153.0a1 (the engine that landed [Bug 1999989][bz1999989] in November 2025), Safari 26.5 TP, and Chrome (Blink) on the same machine. **No two engines agree.**

| fragment | spec (strict §16.3.2) | Safari / Chrome | Firefox |
|---|---|---|---|
| `#svgView(viewBox(0,0,100,100))&xywh=100,0,100,100` | ignore whole fragment, render full SVG | **terracotta TL** — applies `svgView()`, drops `&xywh=` | **teal TR** — applies `xywh=`, ignores `svgView()` |

Three distinct outcomes for one fragment:

1. **Spec-strict** = full SVG (4 quadrants).
2. **Safari / Chrome** = the `svgView()` crop wins. Implementations evidently parse `svgView(...)` permissively (not requiring whole-string consumption) and never reach the media-fragment branch.
3. **Firefox** = the `xywh` crop wins. Mozilla's `ProcessSVGViewSpec` requires the full string to match `svgView(...)`; the trailing `&xywh=...` makes that parse fail, and `ProcessFragmentIdentifier` falls through to `ProcessMediaFragment`. The fragment URI parser is `&`-token-based, so it skips the unknown `svgView(...)` token and matches the second `xywh=` token.

Reproducer (single reftest pair):
- Test: `tests/spec-issue-svgview-and-xywh.html` (this issue)
- Reference: `tests/spec-issue-svgview-and-xywh-ref.html` — full SVG, all 4 quadrants visible.
- Test FAILs in every engine tested. Safari/Chrome render solid terracotta; Firefox renders solid teal.

Neither engine implements the strict grammar.

### Three possible resolutions

**Option 1 — tighten the grammar (status quo of the spec).** Add explicit normative prose:

> If the fragment identifier is not a correctly formed SVG fragment identifier as defined by the grammar above, the user agent must ignore the fragment and render the document with its authored attributes.

Then Firefox, Chrome and Safari needs to fix `SVGFragmentIdentifier::ProcessFragmentIdentifier` (Firefox) to validate the entire fragment before applying any effect.


**Option 2 — relax the grammar.** Admit `SVGViewSpec & spacesegment` (and possibly other useful combos) and define semantics:

```
SVGFragmentIdentifier ::= ... |
                          SVGViewSpec *( "&" ( timesegment | spacesegment ) )
```

Composition rule: the `SVGViewSpec` provides the base view (viewBox / preserveAspectRatio / transform / zoomAndPan); a trailing `xywh=` further overrides the `viewBox` portion. Trailing `t=` is unchanged.

Implementations would needs to make `xywh` deliberately stack with `svgView()` rather than be silently dropped.

**Option 3 — codify one of the lenient parses.** Pick one of the two observed behaviors and add normative prose:

> *(Safari/Chrome variant)* When the fragment identifier matches the prefix of a production above, user agents must apply that production and ignore any remainder.

or

> *(Firefox variant)* User agents must validate the entire fragment against each production in turn; if the first production fails to consume the whole string, the next is tried. The media-fragment productions tokenize on `&` and silently skip unrecognized tokens.


[grammar]: https://svgwg.org/svg2-draft/linking.html#SVGFragmentIdentifiersDefinitions
[media-frags]: https://www.w3.org/TR/media-frags/#valid-uri
[bz1999989]: https://bugzilla.mozilla.org/show_bug.cgi?id=1999989
[wk290983]: https://bugs.webkit.org/show_bug.cgi?id=290983


## TEST case
From left to right: Safari, Firefox, Chrome.
<img width="3160" height="882" alt="Image" src="https://github.com/user-attachments/assets/5d2ed794-6dcc-4d82-8dfa-d9a410880846" />

Image for the reftest.
<img width="200" height="200" alt="Image" src="https://github.com/user-attachments/assets/8938a9f3-6146-4f0f-92b0-fd130b545ad3" />

[spec-issue-svgview-and-xywh-ref.html](https://github.com/user-attachments/files/28051699/spec-issue-svgview-and-xywh-ref.html)
[spec-issue-svgview-and-xywh.html](https://github.com/user-attachments/files/28051698/spec-issue-svgview-and-xywh.html)

Please view or discuss this issue at https://github.com/w3c/svgwg/issues/1112 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 20 May 2026 09:48:22 UTC