Skip to content

RUM-12185: Support aliased import paths for local SVG discovery - #1352

Open
jonathanmos wants to merge 6 commits into
developfrom
jmoskovich/rum-12185/support-alias-paths
Open

jonathanmos wants to merge 6 commits into
developfrom
jmoskovich/rum-12185/support-alias-paths

Conversation

@jonathanmos

@jonathanmos jonathanmos commented Jul 28, 2026 •

Copy link
Copy Markdown
Member

What does this PR do?

Adds support for resolving aliased local SVG imports during Session Replay asset discovery.

Supports TypeScript/JavaScript path mappings and babel-plugin-module-resolver, including .babelrc, function-form plugin configurations, and Windows paths. Includes regression coverage for the supported configurations.

Handle alias entries in babel-plugin-module-resolver that resolve to absolute paths, not just relative ones
Detect aliased SVG imports whose specifier has no .svg extension (alias points directly at the file)
Add support for metro.config.js's resolver.extraNodeModules, matching Metro's own scoped-specifier parsing

Before
Screenshot 2026-08-31 at 17 29 11

After
Screenshot 2026-09-03 at 14 52 30

Motivation

What inspired you to submit this pull request?

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

@datadog-prod-us1-5

datadog-prod-us1-5 Bot commented Jul 28, 2026 •

Copy link
Copy Markdown

Tests

✅ All CI checks and tests passed.

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 1bfcddc | Docs | View more details | Give us feedback!

@jonathanmos
jonathanmos force-pushed the jmoskovich/rum-12185/support-alias-paths branch from 1a97eab to ffa6d6f Compare July 28, 2026 12:21
@jonathanmos
jonathanmos requested a lite review from Copilot July 28, 2026 12:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds support for resolving aliased local .svg imports during Session Replay asset discovery, so ReactNativeSVG.buildSvgMap() can map SVG components even when imports use TS/JS path mappings or babel-plugin-module-resolver.

Changes:

  • Introduces PathAliasResolver to resolve non-relative SVG import specifiers via babel-plugin-module-resolver and tsconfig.json/jsconfig.json paths.
  • Updates ReactNativeSVG.buildSvgMap() to use the resolver (and reset cached alias config between runs).
  • Adds regression tests and a benchmark scenario exercising aliased SVG imports.

Reviewed changes

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

Show a summary per file
File Description
yarn.lock Adds lock entries for tsconfig-paths and babel-plugin-module-resolver (and transitive deps).
packages/react-native-babel-plugin/test/react-native-svg.test.ts Adds coverage for alias resolution via tsconfig/jsconfig + babel-module-resolver, and precedence/fallback behavior.
packages/react-native-babel-plugin/src/libraries/react-native-svg/pathAliasResolver.ts New resolver implementing alias lookup via Babel partial config + tsconfig-paths.
packages/react-native-babel-plugin/src/libraries/react-native-svg/index.ts Wires alias resolution into buildSvgMap() via resolveImportSource().
packages/react-native-babel-plugin/package.json Adds tsconfig-paths dependency and babel-plugin-module-resolver devDependency.
benchmarks/src/scenario/SessionReplay/component/Svg.tsx Adds an aliased SVG import case (Group H) to the benchmark test screen.
benchmarks/package.json Adds babel-plugin-module-resolver for the benchmark app.
benchmarks/babel.config.js Configures module-resolver alias used by the benchmark aliased SVG case.

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

@jonathanmos
jonathanmos marked this pull request as ready for review July 28, 2026 14:37
@jonathanmos
jonathanmos requested a review from a team as a code owner July 28, 2026 14:37
@jonathanmos
jonathanmos requested a review from cdn34dd July 28, 2026 14:38
Comment thread packages/react-native-babel-plugin/package.json
Comment thread packages/react-native-babel-plugin/package.json Outdated
Comment thread packages/react-native-babel-plugin/src/libraries/react-native-svg/index.ts Outdated
Copilot AI review requested due to automatic review settings August 31, 2026 09:02
@jonathanmos
jonathanmos force-pushed the jmoskovich/rum-12185/support-alias-paths branch from ffa6d6f to b95312d Compare August 31, 2026 09:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Suppressed comments (1)

packages/react-native-babel-plugin/src/libraries/react-native-svg/pathAliasResolver.ts:39

  • isRelativePath() only matches ./ and ../ with forward slashes, so module-resolver results like src/components/icon.svg or Windows-style ..\\src\\icon.svg will be treated as non-relative and discarded, preventing alias resolution.
function isRelativePath(value: string): boolean {
    return /^\.?\.\//.test(value);
}

Copilot AI review requested due to automatic review settings August 31, 2026 15:04
@jonathanmos
jonathanmos force-pushed the jmoskovich/rum-12185/support-alias-paths branch from b95312d to d8bb805 Compare August 31, 2026 15:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 11 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

packages/react-native-babel-plugin/src/libraries/react-native-svg/pathAliasResolver.ts:39

  • isRelativePath() only matches ./... paths; it does not match ../... (or deeper) relative paths. babel-plugin-module-resolver can legally return ../... when an alias resolves outside the importing file’s directory, and the current check would incorrectly treat that as non-relative and return null (falling back to unresolved resolution).
function isRelativePath(value: string): boolean {
    return /^\.?\.\//.test(value);
}

packages/react-native-babel-plugin/src/libraries/react-native-svg/pathAliasResolver.ts:200

  • parseExtraNodeModulesSpecifier() returns subpath including a leading "/". Passing that into path.join(target, subpath) causes Node to discard target (because an absolute segment resets the join), so extraNodeModules aliases like assets/icon.svg will resolve to /icon.svg instead of ${target}/icon.svg.
        const { packageName, subpath } = parseExtraNodeModulesSpecifier(
            importSource
        );
        const target = extraNodeModules[packageName];
        if (!target) {
            return null;
        }

        return subpath ? pathN.join(target, subpath) : target;

Comment thread packages/react-native-babel-plugin/src/libraries/react-native-svg/index.ts Outdated
Copilot AI review requested due to automatic review settings August 31, 2026 15:17
@jonathanmos
jonathanmos force-pushed the jmoskovich/rum-12185/support-alias-paths branch from d8bb805 to d890b12 Compare August 31, 2026 15:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 11 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

packages/react-native-babel-plugin/src/libraries/react-native-svg/pathAliasResolver.ts:39

  • isRelativePath() only matches sources starting with ./ (due to ^\.?\.\/), so it will incorrectly treat ../... (and Windows .\\/..\\) paths returned by babel-plugin-module-resolver as non-relative and skip resolution. That can break aliases whose replacement uses parent-directory segments.
function isRelativePath(value: string): boolean {
    return /^\.?\.\//.test(value);
}

packages/react-native-babel-plugin/src/libraries/react-native-svg/index.ts:265

  • Same issue as the ImportDeclaration handler: relative/absolute re-export sources that don't end in .svg can never be resolved by PathAliasResolver, so collecting them for the second pass is unnecessary overhead.
                        const source = path.node.source?.value;
                        if (!source) {
                            return;
                        }

                        if (source.endsWith('.svg')) {
                            const resolved = this.resolveImportSource(
                                file,
                                source
                            );
                            this.populateExportedSvgNames(path, resolved);
                            return;
                        }

                        const candidateNames: string[] = [];
                        for (const spec of path.node.specifiers) {
                            if (spec.type !== 'ExportSpecifier') {
                                continue;
                            }
                            // spec.exported is the name consumers import under
                            // ('default' would be wrong for `export { default as Logo }`)
                            const exported = spec.exported;
                            const name = getNodeName(
                                this.t,
                                this.t.isStringLiteral(exported)
                                    ? exported.value
                                    : exported.name
                            );
                            if (name) {
                                candidateNames.push(name);
                            }
                        }
                        if (!candidateNames.length) {
                            return;
                        }

                        pendingBareSources.push({
                            file,
                            source,
                            candidateNames,
                            populate: resolved =>
                                this.populateExportedSvgNames(path, resolved)
                        });
                    }

Comment thread packages/react-native-babel-plugin/src/libraries/react-native-svg/index.ts Outdated
Copilot AI review requested due to automatic review settings August 31, 2026 16:49
@jonathanmos
jonathanmos force-pushed the jmoskovich/rum-12185/support-alias-paths branch from d890b12 to a1af24b Compare August 31, 2026 16:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 11 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/react-native-babel-plugin/src/libraries/react-native-svg/pathAliasResolver.ts:39

  • isRelativePath() only recognizes ./ and ../ with forward slashes. On Windows, babel-plugin-module-resolver commonly returns relative paths using backslashes (e.g. .\\src\\... / ..\\...), which will be treated as non-relative here and make aliased imports fail to resolve on Windows.
function isRelativePath(value: string): boolean {
    return /^\.?\.\//.test(value);
}

Copilot AI review requested due to automatic review settings September 3, 2026 11:15
@jonathanmos
jonathanmos force-pushed the jmoskovich/rum-12185/support-alias-paths branch from a1af24b to 87c92cb Compare September 3, 2026 11:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

A Windows-path handling bug in PathAliasResolver can prevent module-resolver relative outputs using backslashes from being recognized and resolved correctly.

Review details

Suppressed comments (1)

packages/react-native-babel-plugin/src/libraries/react-native-svg/pathAliasResolver.ts:39

  • isRelativePath() only detects POSIX-style ./ and ../ prefixes. On Windows, babel-plugin-module-resolver (or user config) can yield relative paths using backslashes (e.g. .\\src\\components\\icon.svg), which would be treated as non-relative and make alias resolution incorrectly fall back to null.
function isRelativePath(value: string): boolean {
    return /^\.?\.\//.test(value);
}
  • Files reviewed: 9/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 3, 2026 11:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved alias resolution, binding propagation, cache, platform selection, shadowing, and performance issues remain.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
Resolved since last review (3)

Comment thread packages/react-native-babel-plugin/src/libraries/react-native-svg/index.ts Outdated
Copilot AI lite review requested due to automatic review settings September 30, 2026 09:03
@jonathanmos
jonathanmos force-pushed the jmoskovich/rum-12185/support-alias-paths branch from 477e241 to 608037e Compare September 30, 2026 09:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved critical and moderate correctness issues remain in binding fallback, platform selection, stale map state, and alias validation.

Review effort: Lite
Findings: 4 High severity · 1 Medium severity

Open (5)

Comment thread packages/react-native-babel-plugin/src/libraries/react-native-svg/index.ts Outdated
@marco-saia-datadog marco-saia-datadog added the Do not merge This PR is not ready to be merged yet label Oct 9, 2026
Copilot AI lite review requested due to automatic review settings October 15, 2026 07:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Unresolved alias validation, export precedence, cache, and scan-performance issues can affect SVG discovery.

0 open findings

5 resolved since last review
Previously missed (5)

In code that hasn't changed since last review

Medium severity Declare benchmark debugger frontend dependency explicitly

benchmarks/​package.json:55

The new benchmark aliases hardcode files under benchmarks/node_modules/@react-native/debugger-frontend, but this package is not a direct benchmark dependency. The lockfile has both 0.76.9 and 0.78.2 transitively; node-modules hoisting does not guarantee the expected 0.78.2 files at that path, so the benchmark may fail to bundle or exercise these cases. Declare @react-native/debugger-frontend at the benchmark's React Native version (0.78.2) and update the lockfile, or use an explicitly owned fixture.

Medium severity Validate alias-resolved SVG targets before caching

packages/​react-native-babel-plugin/​src/​libraries/​react-native-svg/​buildSvgMap.ts:38

If an alias maps to a missing .svg file, the nonempty resolver result is stored as a valid entry here without checking the target. A module-resolver or Metro alias can yield a path even when no file exists; a later JSX transform then fails to read it and skips the SVG. Check that alias-resolved .svg targets are real files before populating the map, both for sources ending in .svg and for extensionless aliases at lines 61–62. The existing missing-path test only exercises tsconfig-paths.

Medium severity Prevent wildcard exports from overriding explicit names

packages/​react-native-babel-plugin/​src/​libraries/​react-native-svg/​buildSvgMap.ts:619

Wildcard traversal also runs when this barrel has an explicit export of the same name. For export { Logo } from './nonSvg'; export * from './svgBarrel';, JavaScript selects the explicit Logo, but following the wildcard can assign the SVG to the consuming JSX binding and wrap the wrong component. Record explicit exported names (including direct SVG and deferred bare exports), and only follow a wildcard for names not explicitly exported by that barrel.

Medium severity Reuse Babel bindings across equivalent configurations

packages/​react-native-babel-plugin/​src/​libraries/​react-native-svg/​pathAliasResolver.ts:540

moduleResolverBindings is keyed by filename, so loadPartialConfig() runs again for each distinct source file with a reachable bare import, even when they share the same Babel configuration. On a large React Native project this can repeatedly load the full config and plugins during one SVG scan, including for ordinary JSX component imports. Reuse the resolved binding across files whose Babel configuration is equivalent, while preserving file-specific Babel overrides and separate monorepo configs.

Medium severity Invalidate legacy SVG caches before discovery

packages/​react-native-babel-plugin/​src/​libraries/​react-native-svg/​svgBindingMap.ts:82

An existing unversioned svg-map.json is accepted here and buildSvgMap() returns before rescanning. That cache was generated before aliased imports were discovered, so a build without a platform can keep missing aliased SVGs after upgrading until the asset generator rewrites the cache. Invalidate or regenerate legacy caches for discovery (and update the legacy-cache test), rather than treating them as a complete map.

🧠 Review effort: Lite

Copilot AI lite review requested due to automatic review settings October 15, 2026 09:31
@jonathanmos
jonathanmos force-pushed the jmoskovich/rum-12185/support-alias-paths branch from 949971f to a57d63c Compare October 15, 2026 09:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The new binding graph and cache affect runtime SVG handling, and unresolved alias-resolution defects need correction and human validation.

4 open findings

🧠 Review effort: Lite

Comment thread benchmarks/babel.config.js Outdated
Comment thread packages/react-native-babel-plugin/src/libraries/react-native-svg/buildSvgMap.ts Outdated
Comment thread packages/react-native-babel-plugin/src/libraries/react-native-svg/buildSvgMap.ts Outdated
Copilot AI lite review requested due to automatic review settings October 15, 2026 14:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Cache failures remain unresolved, and the platform-sensitive discovery changes need final human validation.

3 open findings
3 resolved since last review

🧠 Review effort: Lite

Copilot AI lite review requested due to automatic review settings October 18, 2026 08:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved moderate and critical findings affect binding reachability, path resolution, cache handling, and benchmark isolation.

3 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Override does not disable Datadog instrumentation for fixtures

benchmarks/​babel.config.js:33

Babel merges plugins from overrides with the top-level plugins array; it does not replace the top-level Datadog plugin for these files. As a result, the fixture files still run the svgTracking: true instance (or Babel reports a duplicate-plugin error), so this override cannot disable direct fixture instrumentation and the benchmark cases do not isolate alias discovery as intended. Move the enabled Datadog plugin into an override that excludes the fixture directory, rather than adding a second disabled instance.

1 resolved since last review

Review effort: Lite

Copilot AI lite review requested due to automatic review settings October 18, 2026 09:27
@jonathanmos
jonathanmos force-pushed the jmoskovich/rum-12185/support-alias-paths branch from 43827c0 to 1bfcddc Compare October 18, 2026 09:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Unresolved SVG resolution and cache compatibility issues remain, along with unrelated Podfile.lock changes.

1 open issue
2 resolved since last review

Review effort: Lite

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Do not merge This PR is not ready to be merged yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants