… no limit
The predicate guarded on the RESOLVED length where its three siblings guard on
the PREFERRED one:
isQualitySupported() preferredQuality == 0 || quality == preferredQuality
isMaxFileSizeSupported() preferredMaxFileSize == 0 || maxFileSize == preferredMaxFileSize
isSizeSupported() preferredWidth == 0 && preferredHeight == 0
isMaxLengthSupported() maxLength == 0 || maxLength == preferredMaxLength
The intent of that first clause is "the caller asked for no constraint, so any
resolved value satisfies it". Reading it off the resolved field makes it fire in
the opposite situation: a platform that expresses "no duration limit" by
resolving maxLength to 0 -- which is every platform with no compiler registered,
Java SE included, and any compiler that declines the request -- turned a
five-second preference into isMaxLengthSupported() == true, and isSupported()
with it. A caller asking whether its limit would be honored was told yes
precisely when the answer was no.
That also broke the invariant getMaxLength() documents: "This value will be
equal to getPreferredMaxLength() iff isMaxLengthSupported() is true."
When the caller asked for no limit, preferredMaxLength and maxLength are both 0,
so the new clause covers that case identically. The clause only ever changed the
answer in the broken case.
No framework caller reads the predicate, and no test asserted the old behaviour,
so nothing depended on it. The developer guide's Video-Capture-Constraints
example already describes the fixed semantics, and its support table already
lists Java SE as having no max-length support.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
VideoCaptureConstraints.isMaxLengthSupported()guarded on the resolved length where its three siblings guard on the preferred one:isQualitySupported()preferredQuality == 0isMaxFileSizeSupported()preferredMaxFileSize == 0isSizeSupported()preferredWidth == 0 && preferredHeight == 0isMaxLengthSupported()maxLength == 0That clause means "the caller asked for no constraint, so any resolved value satisfies it". Read off the resolved field it fires in the opposite situation instead: a platform that expresses no duration limit by resolving
maxLengthto 0 — every platform with no compiler registered, Java SE included, plus any compiler that declines the request — turned a five-second preference intoisMaxLengthSupported() == true, andisSupported()with it. A caller asking whether its limit would be honored was told yes precisely when the answer was no.It also broke the invariant
getMaxLength()documents: "This value will be equal togetPreferredMaxLength()iffisMaxLengthSupported()is true."When the caller genuinely asked for no limit,
preferredMaxLengthandmaxLengthare both 0, so the new clause covers that case identically. The clause only ever changed the answer in the broken case.Blast radius
No framework caller reads the predicate (the only references are the developer guide's snippet and a generated reflection shim), and no test asserted the old behaviour, so nothing depended on it.
Verification
testMaxLengthUnsupportedWhenResolvedToZerofails on the unfixed code (expected: <false> but was: <true>) and passes after — the other two new cases pass either way, which is what isolates the defect to this one clause.core-unittestssuite: 6077 tests, 0 failures.core-unittests: report regenerated, 0 findings.Found by Codex review on #5664, where the guide chapter documents this API.
🤖 Generated with Claude Code