Skip to content

Prevent unresolvable SVG attributes from dropping the entire generated asset#1320

Open
jonathanmos wants to merge 1 commit into
developfrom
jmoskovich/fix-unresolvable-svg
Open

Prevent unresolvable SVG attributes from dropping the entire generated asset#1320
jonathanmos wants to merge 1 commit into
developfrom
jmoskovich/fix-unresolvable-svg

Conversation

@jonathanmos

Copy link
Copy Markdown
Member

What does this PR do?

Fixes the Babel plugin's SVG asset generation so that an unresolvable attribute or unsupported wrapper element on one SVG child no longer causes the entire SVG to silently fail to generate.

RNSvgHandler.transformElement() now returns whether an element is supported; unsupported children (e.g. Animated.createAnimatedComponent(Path)) are spliced out of the cloned tree instead of being left in place with unsanitized attributes.
handleRegularAttributes() now signals when an attribute's value is a JSX expression that couldn't be statically resolved (e.g. fill={color}), so it gets removed from the element rather than surviving into the serialized output.
Fixes a related bug in the same function: resolvable-but-falsy values (0, '', false — e.g. opacity={0}) were being treated as unresolved due to a truthiness check, and silently dropped instead of correctly serialized. Now checks !== null explicitly.

Motivation

Previously, if any descendant of an had a dynamic attribute that couldn't be resolved at build time, or was a custom wrapper component not in the recognized SVG tag set, that raw JSX survived into the cloned AST. generate() would then serialize invalid SVG XML (e.g. fill={color}), svgo would throw on it, and the whole parent — not just the offending element — would silently fail to be captured for Session Replay. This reproduces a real customer pattern: an Animated.createAnimatedComponent-wrapped path with prop-driven fill/style.

The fix narrows the blast radius: only the specific unsupported element or unresolvable attribute is dropped, and the rest of the SVG generates normally.

Additional Notes
Added regression tests for: an unsupported element with a supported sibling, an unsupported element with dynamic/unresolvable attributes (the customer repro shape), and the falsy-zero (opacity={0}) case.
No behavior change for statically-resolvable attributes — those continue to be inlined as string literals as before.
Verified via tsc --noEmit, eslint, and the full react-native-babel-plugin test suite (190/190 passing).

Additional Notes

Anything else we should know when reviewing?

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests
  • Make sure you discussed the feature or bugfix with the maintaining team in an Issue
  • Make sure each commit and the PR mention the Issue number (cf the CONTRIBUTING doc)
  • If this PR is auto-generated, please make sure also to manually update the code related to the change

@jonathanmos jonathanmos marked this pull request as ready for review July 2, 2026 13:14
@jonathanmos jonathanmos requested a review from a team as a code owner July 2, 2026 13:14
Copilot AI review requested due to automatic review settings July 2, 2026 13:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the React Native SVG Babel plugin’s asset generation so that unsupported elements or non-statically-resolvable JSX attributes don’t cause the entire SVG to fail SVGO optimization (and therefore fail capture for Session Replay).

Changes:

  • Update RNSvgHandler to treat unsupported SVG children as removable (signal + splice) rather than leaving them in the cloned AST.
  • Update handleRegularAttributes() to (a) preserve statically-resolved falsy values like 0, and (b) signal removal for unresolved JSX expression container attributes (e.g. fill={color}).
  • Add regression tests covering unsupported elements, dynamic/unresolvable attributes, and the opacity={0} falsy-resolution case.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/react-native-babel-plugin/test/react-native-svg.test.ts Adds/updates tests validating unsupported-element removal and non-resolvable attribute dropping during SVG capture.
packages/react-native-babel-plugin/src/libraries/react-native-svg/processing/attributes.ts Makes regular attribute handling preserve falsy resolved values and remove unresolved JSX expression container attributes.
packages/react-native-babel-plugin/src/libraries/react-native-svg/handlers/RNSvgHandler.ts Splices unsupported child elements out of the cloned SVG tree and removes unresolved expression-container attributes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/react-native-babel-plugin/test/react-native-svg.test.ts Outdated
Comment thread packages/react-native-babel-plugin/test/react-native-svg.test.ts Outdated
@jonathanmos jonathanmos force-pushed the jmoskovich/fix-unresolvable-svg branch from 4f31770 to de6f7b8 Compare July 2, 2026 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants