Skip to content

[x-internals] Restore removed exports and pin internal dependencies - #23907

Merged
LukasTy merged 7 commits into
mui:masterfrom
LukasTy:claude/mui-x-issue-23905-0fe888
Oct 19, 2026
Merged

LukasTy merged 7 commits into
mui:masterfrom
LukasTy:claude/mui-x-issue-23905-0fe888

Conversation

@LukasTy

@LukasTy LukasTy commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Fixes #23905

@mui/x-internals 9.15.0 removed entry points and exports that published @mui/x-* 9.0.0 to 9.14.0 still import. Those packages declare @mui/x-internals with a ^9 range, so a fresh install picks 9.15.0 and fails with ERR_PACKAGE_PATH_NOT_EXPORTED. An upgrade of one package to 9.15.0 next to older ones has the same effect.

Changes

  • Bring back the removed entry points as re-exports from @base-ui/utils, where the code moved: store, fastObjectShallowCompare, useFirstRender (useOnFirstRender), platform (isFirefox, isJSDOM, iOSMediaQuery), and getTarget in domUtils.
  • The legacy createSelectorMemoized gives a combiner with fewer parameters than input selectors the full length before it calls Base UI. Base UI throws Unsupported number of arguments for such a combiner, and @mui/x-charts 9.4.0 has one: selectorChartSeriesFlatbushMap passes 7 input selectors to a combiner with 6 parameters.
  • fastArrayCompare wraps areArraysEqual to keep its old === comparison and its false result for non-array values. reactMajor stays a local one-liner, because Base UI has no equivalent.
  • loadStyleSheets accepts a nonce string as the third argument again. [charts-pro][data grid] Fix exports failing or hanging under a Content Security Policy #23521 changed it to an options object, so @mui/x-charts-pro 9.14.0 and earlier lost the CSP nonce in export and print.
  • Each legacy export has a TODO v10: remove note. legacyExports.test.ts fails when one of them goes away, and when the 9.4.0 selector pattern throws.
  • Pin @mui/x-internals, @mui/x-internal-gestures, @mui/x-charts-vendor, and @mui/x-virtualizer with workspace:*, so future releases depend on exact versions. @mui/x-license, @mui/x-telemetry, and the public packages keep ^.

Verification

  • I installed the packed @mui/x-internals under published packages:
    • Before: charts, data grid, and tree view 9.0.0 and 9.14.0 fail to import. @mui/x-date-pickers-pro 9.2.0 fails on getTarget.
    • After: every stable 9.x version from 9.0.0 to 9.15.0 (22 versions) works. All published charts, data grid, tree view, and pickers packages (community, pro, and premium where they exist) import in ESM and CommonJS, LineChart and RichTreeView render on the server, and DataGrid mounts in jsdom. Data grid 9.0.0 in Firefox gets its scroller tabIndex back.
  • A scan of all v9 tags finds no other missing runtime import.
  • pnpm pack of @mui/x-license gives "@mui/x-internals": "9.15.0" and "@mui/x-telemetry": "^9.15.0".

Notes

  • The re-exported utilities follow the @base-ui/utils range of the newest @mui/x-internals. A breaking change in a later Base UI 0.x minor reaches 9.0.0 to 9.14.0 through them.
  • If users mix versions, for example charts-pro 9.16 with charts 9.17, they get a second copy of each pinned package. For @mui/x-charts-vendor, that is a second copy of d3.
  • The only React context in @mui/x-internals is ToolbarContext, and only community x-charts and x-data-grid import it. However, charts-pro also imports and instantiates runtime classes from @mui/x-internal-gestures in useRegisterZoomGestures, then passes those instances to the community chart's gesture manager. Gesture instances therefore cross package boundaries, and mixed-version installations can involve different copies of the gestures package.
  • The pins protect only future releases. 9.0.0 to 9.14.0 keep ^9, so the legacy exports must stay until v10.

Generated with Claude Code

LukasTy and others added 3 commits October 16, 2026 16:00
`@mui/x-internals` 9.15.0 removed entry points and exports that published `@mui/x-*` 9.0.0 to 9.14.0 import through a `^9` range. A fresh install of those versions fails with `ERR_PACKAGE_PATH_NOT_EXPORTED`.

- Restore the `store`, `fastArrayCompare`, `fastObjectShallowCompare`, `platform`, `reactMajor`, and `useFirstRender` entry points from v9.14.0.
- Restore `getTarget` in `domUtils`, and `isFirefox` and `isJSDOM` in `platform`.
- Accept a `nonce` string as the third argument of `loadStyleSheets` again.
- Add a test that fails when one of these exports goes away.

Fixes mui#23905

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Published packages declared `@mui/x-internals` and the other internal packages with a `^` range, so a removal in an internal package broke older published versions.

- Use `workspace:*` instead of `workspace:^` for `@mui/x-internals`, `@mui/x-internal-gestures`, `@mui/x-charts-vendor`, and `@mui/x-virtualizer`.
- Keep `^` for `@mui/x-license`, `@mui/x-telemetry`, and the public packages, which must stay shared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-23905-0fe888

# Conflicts:
#	pnpm-lock.yaml
@LukasTy LukasTy added type: regression A bug, but worse, it used to behave as expected. internal Behind-the-scenes enhancement. Formerly called “core”. labels Oct 16, 2026
@LukasTy
LukasTy requested a balanced review from Copilot October 16, 2026 13:51
@code-infra-dashboard

code-infra-dashboard Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Deploy preview

https://deploy-preview-23907--material-ui-x.netlify.app/
QR code for https://deploy-preview-23907--material-ui-x.netlify.app/

Bundle size

Bundle Parsed size Gzip size
@mui/x-data-grid 🔺+29B(+0.01%) 🔺+8B(+0.01%)
@mui/x-data-grid-pro 🔺+29B(+0.01%) 🔺+5B(0.00%)
@mui/x-data-grid-premium 🔺+29B(0.00%) 🔺+4B(0.00%)
@mui/x-charts 0B(0.00%) 0B(0.00%)
@mui/x-charts-pro 🔺+29B(+0.01%) 🔺+13B(+0.01%)
@mui/x-charts-premium 🔺+29B(0.00%) 🔺+11B(+0.01%)
@mui/x-date-pickers 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers-pro 0B(0.00%) 0B(0.00%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)
@mui/x-scheduler 🔺+4B(0.00%) ▼-1B(0.00%)
@mui/x-scheduler-premium 0B(0.00%) 🔺+14B(+0.01%)
@mui/x-chat 0B(0.00%) 0B(0.00%)
@mui/x-license 0B(0.00%) 0B(0.00%)

Details of bundle changes

Performance

Total duration: 1,414.07 ms -159.67 ms(-10.1%) | Renders: 63 (+0) | Paint: 1,937.22 ms -284.55 ms(-12.8%)

Test Duration Renders
RadialLineChart with big data amount 69.72 ms 🔺+16.21 ms(+30.3%) 2 (+0)
PieChart with big data amount 9.99 ms 🔺+1.75 ms(+21.2%) 2 (+0)
FunnelChart with big data amount 5.24 ms 🔺+0.91 ms(+21.0%) 2 (+0)
SparkLineChart grid of 100 instances 119.98 ms ▼-100.20 ms(-45.5%) 1 (+0)
BarChart stacked with multiple series 64.76 ms ▼-37.59 ms(-36.7%) 2 (+0)

21 tests within noise — details

Metric alarms

Test Metric Change
PieChart with big data amount bench:paint 🔺 +3.13 ms
FunnelChart with big data amount bench:paint 🔺 +1.71 ms

Check out the code infra dashboard for more information about this PR.

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

Published-package resolution and mixed-version compatibility warrant human confirmation despite no identified blocking defects.

0 open findings

What changed in this PR

Restores compatibility for published MUI X 9.x packages affected by removed internal exports, addressing #23905.

Changes:

  • Restore legacy entry points and exports, with removal deferred until v10.
  • Restore string nonce support in loadStyleSheets and add regression tests.
  • Pin selected internal dependencies to exact versions for future releases.
File Description
pnpm-lock.yaml Synchronizes dependency pins and restored store dependencies.
packages/​x-virtualizer/​package.json Pins x-internals.
packages/​x-tree-view/​package.json Pins x-internals.
packages/​x-tree-view-pro/​package.json Pins x-internals.
packages/​x-scheduler/​package.json Pins x-internals.
packages/​x-scheduler-premium/​package.json Pins x-internals and x-virtualizer.
packages/​x-scheduler-internals/​package.json Pins x-internals.
packages/​x-scheduler-internals-premium/​package.json Pins x-internals.
packages/​x-license/​package.json Pins x-internals; preserves telemetry range.
packages/​x-internals/​src/​useFirstRender/​useFirstRender.ts Restores first-render hook.
packages/​x-internals/​src/​useFirstRender/​index.ts Restores deprecated hook entry point.
packages/​x-internals/​src/​tests/​legacyExports.test.ts Checks legacy exports and environment detection.
packages/​x-internals/​src/​store/​useStoreEffect.ts Restores store effect subscriptions.
packages/​x-internals/​src/​store/​useStore.ts Restores React store integration.
packages/​x-internals/​src/​store/​Store.ts Restores legacy store implementation.
packages/​x-internals/​src/​store/​index.ts Restores deprecated store entry point.
packages/​x-internals/​src/​store/​createSelectorType.ts Restores selector types.
packages/​x-internals/​src/​store/​createSelector.ts Restores selector utilities and memoization.
packages/​x-internals/​src/​reactMajor/​index.ts Restores React version export.
packages/​x-internals/​src/​platform/​index.ts Restores platform detection exports.
packages/​x-internals/​src/​fastObjectShallowCompare/​index.ts Restores object comparison entry point.
packages/​x-internals/​src/​fastObjectShallowCompare/​fastObjectShallowCompare.ts Restores shallow object comparison.
packages/​x-internals/​src/​fastArrayCompare/​index.ts Restores array comparison entry point.
packages/​x-internals/​src/​fastArrayCompare/​fastArrayCompare.ts Restores array comparison utility.
packages/​x-internals/​src/​fastArrayCompare/​fastArrayCompare.test.ts Restores array comparison tests.
packages/​x-internals/​src/​export/​loadStyleSheets.tsx Accepts legacy string nonce arguments.
packages/​x-internals/​src/​export/​loadStyleSheets.test.ts Tests legacy nonce propagation.
packages/​x-internals/​src/​domUtils/​index.ts Re-exports deprecated getTarget utility.
packages/​x-internals/​src/​domUtils/​getTarget.ts Restores shadow-DOM-aware event targeting.
packages/​x-internals/​package.json Adds external-store shim and types.
packages/​x-date-pickers/​package.json Pins x-internals.
packages/​x-date-pickers-pro/​package.json Pins x-internals.
packages/​x-data-grid/​package.json Pins x-internals.
packages/​x-data-grid-pro/​package.json Pins x-internals.
packages/​x-data-grid-premium/​package.json Pins x-internals.
packages/​x-data-grid-generator/​package.json Pins x-internals.
packages/​x-charts/​package.json Pins internals, gestures, and vendor dependencies.
packages/​x-charts-pro/​package.json Pins internals, gestures, and vendor dependencies.
packages/​x-charts-premium/​package.json Pins internals and vendor dependencies.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@LukasTy
LukasTy marked this pull request as ready for review October 16, 2026 14:11
@LukasTy

LukasTy commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

If you think that we shouldn't pin dependency in v9, I can drop this change and do it only on next major.

@michelengelen michelengelen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM ... Good to have the comments. The only suggestion would be to add the TODO v10: prefix on them so we can easily search for them.

Also shouldn't this target the v9 branch only?

@romgrk

romgrk commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

This one's on me, I assumed that x-internals was an internal- package and thus pinned.

But can we instead re-export those utils from @base-ui/utils? They have been moved there.

The removed code moved to `@base-ui/utils`, so the legacy entry points re-export it instead of a copy of the 9.14.0 code.

- Re-export `store`, `fastObjectShallowCompare`, `useFirstRender`, `platform`, and `getTarget` from `@base-ui/utils`.
- Keep `fastArrayCompare` as a wrapper of `areArraysEqual` with the old behavior, and keep `reactMajor` local.
- Remove the `use-sync-external-store` dependency again.
- Start each note with `TODO v10:`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LukasTy and others added 2 commits October 19, 2026 11:46
…oint

`@base-ui/utils` 0.5.0 rejects a memoized selector whose combiner has fewer parameters than input selectors. `@mui/x-charts` 9.4.0 uses this pattern, so the re-export broke that version.

- Restore the 9.14.0 store code and the `use-sync-external-store` dependency.
- Add a test for the 9.4.0 selector pattern.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This reverts commit 23b5bf9. Only `@mui/x-charts` 9.4.0 needs the store copy, and it can upgrade to 9.5.0 or later instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@LukasTy

LukasTy commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

@michelengelen Thanks. All notes now start with TODO v10: (d46959f).

About the v9 branch: v9.x split from master on 2026-09-23, so it has 9.14.0 but not 9.15.0. Its @mui/x-internals has no store and no errorOnce, and @mui/x-charts and @mui/x-charts-pro 9.15.0 import errorOnce. Our v9.x has been created slightly prematurely, and thus we have some inconsistencies with it.

@romgrk Done. The legacy entry points now re-export @base-ui/utils, with two exceptions: fastArrayCompare wraps areArraysEqual to keep === and the false result for non-arrays, and reactMajor stays local, because Base UI has only isReactVersionAtLeast.

One version still fails: @mui/x-charts 9.4.0. Its selectorChartSeriesFlatbushMap passes 7 input selectors to a combiner with 6 parameters. The old createSelectorMemoized accepted that, but the @base-ui/utils version throws "Unsupported number of arguments". A copy of the old store would fix only this version, but I don't feel like we should complicate code for everyone just to cover an edge case in one version. WDYT @JCQuintas?
The PR documents this possible combination issue.
If Base UI accepted this pattern again, 9.4.0 would work too.

@LukasTy
LukasTy requested review from michelengelen and a balanced review from Copilot October 19, 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

The documented charts 9.4.0 incompatibility and mixed-version gesture dependencies require final maintainer validation.

No open issues 🎉

1 file not reviewed
  • pnpm-lock.yaml: Generated file

Review effort: Balanced

@JCQuintas

Copy link
Copy Markdown
Member

One version still fails: @mui/x-charts 9.4.0. Its selectorChartSeriesFlatbushMap passes 7 input selectors to a combiner with 6 parameters. The old createSelectorMemoized accepted that

If we need to decrease the amount of selectors we could simply create a new memoized selector for both selectorChartDefaultXAxisId and ...YAxisId

const selectorDefaultXYAxisIds = createSelectorMemoized(
  selectorChartDefaultXAxisId,
  selectorChartDefaultYAxisId,
  (x, y) => { return {x,y} }
)
-  selectorChartDefaultXAxisId,
-  selectorChartDefaultYAxisId,
+  selectorDefaultXYAxisIds,

should have small impact

`@base-ui/utils` throws "Unsupported number of arguments" when a memoized combiner has fewer parameters than input selectors. The old version accepted this, and `@mui/x-charts` 9.4.0 uses it.

- Give such a combiner the full length in the legacy `createSelectorMemoized`.
- Add a test for the 9.4.0 selector pattern.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@LukasTy

LukasTy commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

Claude reply

@JCQuintas Thanks, but that change cannot reach the code that fails. The failing selector is in the published 9.4.0 package, and on master it already has 6 input selectors and 6 parameters (since 9.5.0). The count is also not the problem: Base UI throws when the combiner has fewer parameters than input selectors.

Instead, the legacy createSelectorMemoized now gives such a combiner the full length before it calls Base UI (fa86120). With this, all 22 stable 9.x versions import and render, 9.4.0 included.

@JCQuintas

Copy link
Copy Markdown
Member

Got it, we should probably merge this before release

@LukasTy
LukasTy merged commit 78fcfbd into mui:master Oct 19, 2026
23 checks passed
@LukasTy
LukasTy deleted the claude/mui-x-issue-23905-0fe888 branch October 19, 2026 13:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Behind-the-scenes enhancement. Formerly called “core”. type: regression A bug, but worse, it used to behave as expected.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pin @mui/x-internals dependency to compatible version

5 participants