Fix dashboard grids not reacting to window resize (Babel arrow transform on gridstack)
What does this MR do and why?
This MR fixes a production bug. Analytics dashboards do not respond to window resizes after the initial page load. The feature-spec console error is only how we found it.
User-facing impact, on gitlab.com today:
- Every page that renders
GlDashboardfrom@gitlab/uiis affected: group and project analytics dashboards, the Value Streams Dashboard, explore analytics dashboards, compliance dashboards, contribution analytics, and Duo and SDLC trends. - gridstack calls
onResize()with no argument from its ResizeObserver. In production that call returns at once and does nothing. - So the responsive column breakpoint, which collapses panels to one column below the medium width, and cell height updates never apply after render.
- Nothing is logged and Sentry receives nothing. The defect is silent.
Root cause:
- gridstack 12.6.0, a dependency of
@gitlab/ui, hasonResize(clientWidth = this.el?.clientWidth). - webpack compiles gridstack with
babel-loader, because the webpack 4 parser cannot read?.. @babel/plugin-transform-optional-chainingrewrites the default parameter into an arrow IIFE that usesthis.@babel/plugin-transform-arrow-functionsconverts that arrow and hoistsvar _this12 = this;into the method body.- Default parameters run in their own scope. They cannot see the method body's
var. The parameter expression references an undeclared name. - This is a Babel bug. It reproduces with the repo's Babel (core 7.27.1) and with the latest Babel 7 (7.29.7).
Why tests crashed but production did not:
- In unminified builds (CI test assets, local development) the name is
_this12. It is unbound, so the call throwsUncaught ReferenceError: _this12 is not defined. The feature specs surfaced this in 70 examples across 9 analytics dashboard spec files. - In the production build Terser renames the alias to
g.gis also the webpack module wrapper'sexportsparameter. The expression readsexports.el, getsundefined, andonResizereturns early on its first line. I verified this by parsing the live gitlab.com chunk and resolving the binding.
Fix:
- Move
@babel/plugin-transform-arrow-functionsfrom the global plugin list into anoverridesentry withexclude: /node_modules/. - The plugin exists only because some of our own code calls
newon arrow functions. Our code is still transformed. - Third-party code keeps native arrow functions. Every target browser (browserslist
baseline widely available) supports them. - Side effect: every
node_modulesfile that goes throughbabel-loaderkeeps arrow functions. The output is slightly smaller. There is no behaviour change in supported browsers. - Only webpack sends
node_modulesthrough Babel. rspack uses SWC and does not compilenode_modules, so it never had this bug. A comment in the config notes that the override can move back intopluginsonce rspack replaces webpack.
Notes:
- A grep found no
this?.xdefault parameters inapp/oree/app/JavaScript, so our own code does not hit the same bug. - The
babel-loaderdisk cache key does not include the content ofbabel.config.js. Locally, cleartmp/cache/webpack/babel-loaderif the old output persists. - The console allowlist
spec/support/browser_console_allowlist.ymlcomes from the still-open MR linked below. Nothing to remove here. When it merges, the_this\d+ is not definedentry can be dropped.
How to verify
-
Open a group analytics dashboard in a production build. Narrow the window below the medium breakpoint (768px). Before this change the panels stay in several columns. After this change they collapse to one column.
-
Transform gridstack with the project Babel config and inspect
onResize:node -e ' const babel = require("@babel/core"); const code = babel.transformFileSync("node_modules/gridstack/dist/gridstack.js").code; const i = code.indexOf("onResize(clientWidth"); console.log(code.slice(i, i + 160)); 'Before:
onResize(clientWidth = function (_this12$el) {...}()) { var _this12 = this;After:
onResize(clientWidth = (_this$el => ...)()) {with no hoisted_this. -
Run two Jest specs that render
GlDashboard, which loads gridstack:yarn jest spec/frontend/explore/analytics_dashboards/pages/details_spec.js ee/spec/frontend/compliance_dashboard/components/dashboard/compliance_dashboard_spec.js -
Optional: run
ee/spec/features/groups/analytics/dashboards_spec.rbagainst a webpack build and confirm that the console shows no_thiserror.
Screenshots
Group analytics dashboard "GitLab Duo and SDLC trends", rendered by a feature spec against webpack test assets. The browser starts at 1400px wide and is then resized to 600px. Panels show "Something went wrong" because the test environment has no ClickHouse; only the layout matters here.
| Before (600px wide) | After (600px wide) |
|---|---|
![]() |
![]() |
- Before: the resize handler throws
ReferenceError: _this12 is not defined. The grid keeps its three-column layout (gs-xvalues0, 4, 8) in a 600px viewport. - After: no console error. gridstack collapses the grid to one column (every
gs-xis0).
Initial 1400px render, identical in both builds:
![]() |
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
- I have evaluated the MR acceptance checklist for this MR.
References
- Found via the first entry of section B in #628901
- Why the arrow-functions plugin exists: #229146
- Why
node_modulesgo through Babel at all (webpack 4 parser): #336216 - Allowlist that lists this error, not yet merged: !255207 (closed)
- Example CI job that showed the error: https://gitlab.com/gitlab-org/gitlab/-/jobs/16462296315


