Return None from value_source_location() for attributes written without a value - #334
Open
krickert wants to merge 1 commit into
Open
Return None from value_source_location() for attributes written without a value#334krickert wants to merge 1 commit into
krickert wants to merge 1 commit into
Conversation
…ut a value AttributeOutline::value defaulted to 0..0 for valueless attributes, and iter_attrs inferred "has a value" from `base + value.start` being nonzero. As a result Attribute::value_source_location() returned a zero-length span pointing at the start of the parser's current buffer -- or None, together with the name location, whenever the tag happened to sit at buffer offset 0 -- so the reported spans depended on where the tag fell relative to a write() boundary. Carry value presence explicitly as Option<Range> instead of deriving it from the offset. name_source_location() is now always present for parsed attributes, value_source_location() is None for valueless ones, and both are independent of how the input was chunked. Fixes cloudflare#333.
krickert
requested review from
a team,
Noah-Kennedy,
jasnell and
orium
as code owners
August 12, 2026 03:40
kornelski
approved these changes
Aug 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #333.
Problem
For an attribute written without a value (e.g.
<div hidden>),Attribute::value_source_location()either returnedNoneor returned azero-length span pointing at the start of the parser's current buffer, and
which of the two you got depended on where the tag fell relative to a
write()boundary. In theNonecasename_source_location()was absenttoo. Source locations describe the input, so they should not depend on how
the caller chunked it.
Cause
AttributeOutline::valuewas a plainRangedefaulting to0..0, anditer_attrsinferred value presence frombase + value.startbeing nonzero:With
value.start == 0that reduces toNonZero::new(base), which isNoneonly when the tag happens to sit at buffer offset 0.
Fix
Carry presence explicitly:
AttributeOutline::valueis nowOption<Range>,set only by
finish_attr_value.Attribute::name_value_startbecomesOption<(usize, Option<usize>)>, dropping theNonZeroworkaround. Behaviorafter the fix:
name_source_location()is always present for parsed attributes,including valueless ones (previously it could be
Nonefor them).value_source_location()isNonefor valueless attributes (doc commentupdated to say so).
write()calls.Downstream consumers of the outline keep their observable behavior:
Attribute::value()still returns""for valueless attributes, selectormatching still treats a missing value as empty, and the
<annotation-xml>integration-point
encodingcheck skips valueless attributes as before.Testing
attribute_source_locations_for_valueless_attributesandattribute_source_locations_do_not_depend_on_chunk_size(the reproductionfrom value_source_location() returns a bogus span for valueless attributes, and whether it does depends on chunk size #333); both fail on
mainand pass with this change../scripts/test.sh: library tests (all suites green) and C API tests pass.The
fuzz/test_casebindgen step could not run on my machine (no libclang),so that stage plus clippy/rustfmt were run individually as in CI:
cargo fmt -- --checkand all four CI clippy invocations are clean.