fix: Deep-compare constraints instead of JSON.stringify-ing them - #4167
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
mrousavy
enabled auto-merge (squash)
August 21, 2026 13:23
`useCameraController` kept the user's `constraints` stable by putting
`JSON.stringify(constraints)` into the `useMemo` dependency array. That
works for plain constraints like `{ fps: 60 }`, but it silently breaks for
`{ resolutionBias: someOutput }`.
Nitro `HybridObject`s are created via `Object.create(prototype)` and hold
every property on their shared prototype, so the JS object itself has no own
keys. `JSON.stringify(...)` therefore serializes *every* `CameraOutput` to
`{}` (release) or `{"__type":"HybridObject<CameraPhotoOutput>"}` (debug) -
two different outputs of the same type produce the exact same string. Any
change that only re-points a `resolutionBias` at a different output is
invisible to the memo, and the session is never re-configured.
Replace the stringification with an explicit deep comparison that compares
object literals and arrays by value and everything else (i.e. `HybridObject`s)
by identity. That also drops a full JSON serialization from every render.
Also adds two Harness tests: one that re-renders with an inline `constraints`
array and asserts the session is configured exactly once (and re-configured
once more when the constraint values actually change), and one that asserts
re-pointing a `resolutionBias` constraint at a different output of the same
type does re-configure the session.
mrousavy
force-pushed
the
fix/memoize-constraints
branch
from
August 21, 2026 13:24
13d4770 to
82e22f0
Compare
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.
What
useCameraControllerkept the user'sconstraintsstable by puttingJSON.stringify(constraints)into theuseMemodependency array:That works for plain constraints like
{ fps: 60 }, but it silently breaks for{ resolutionBias: someOutput }.Nitro
HybridObjects are created viaObject.create(prototype)and hold every property on their shared prototype, so the JS object itself has no own keys.JSON.stringify(...)therefore serializes everyCameraOutputto the same string:JSON.stringify(photoOutput){}{"__type":"HybridObject<CameraPhotoOutput>"}Two different outputs of the same type are indistinguishable. So this, which is the documented way to express capture priority:
is invisible to the memo in release builds, and the session is never re-configured.
How
Replaces the stringification with an explicit deep comparison (
useMemoizedConstraints(...)) that compares object literals and arrays by value, and everything else (i.e.HybridObjects) by identity. It also drops a full JSON serialization from every render, and lets theuseMemodependency array be honest again (thebiome-ignoreis gone).Test
Adds two Harness tests in
visioncamera.hooks.harness.tsx:constraints={[{ fps }]}array and assertsonConfiguredfired exactly once, then asserts changing the actualfpsvalue re-configures exactly once more.resolutionBiasconstraint at a differentCameraPhotoOutputwhile the attachedoutputsstay identical, and asserts the session re-configures. Both bias outputs are deliberately the same HybridObject type, which is exactly whatJSON.stringify(...)could not tell apart - this test is red onmain.Note
Touches the same import block in
visioncamera.hooks.harness.tsxas #4166, so whichever lands second will need a trivial rebase.馃 Generated with Claude Code