From 2f81720603d77ef812ceb8df1f9f4c8ef4fcd9da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 24 Jan 2026 11:18:10 -0800 Subject: [PATCH 1/2] chore(deps-dev): bump @swc/plugin-transform-imports from 10.0.0 to 12.4.0 in /superset-frontend (#37384) Signed-off-by: dependabot[bot] Signed-off-by: hainenber Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: hainenber --- .github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 585917afda22..c01258ea8b98 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -19,6 +19,10 @@ updates: # Source: https://jestjs.io/blog#known-issues # GH thread: https://github.com/jsdom/jsdom/issues/3492 - dependency-name: "jest-environment-jsdom" + # `@swc/plugin-transform-imports` doesn't work with current Webpack-SWC hybrid setup + # See https://github.com/apache/superset/pull/37384#issuecomment-3793991389 + # TODO: remove the plugin once Lodash usage has been migrated to a more readily tree-shakeable alternative + - dependency-name: "@swc/plugin-transform-imports" directory: "/superset-frontend/" schedule: interval: "daily" From b09e60c1ec261af5e59b5ad071ec7a4216c4675f Mon Sep 17 00:00:00 2001 From: Yousuf Ansari <141269047+YousufFFFF@users.noreply.github.com> Date: Sun, 25 Jan 2026 00:48:41 +0530 Subject: [PATCH 2/2] fix(deckgl-contour): prevent WebGL freeze by clamping and auto-scaling cellSize (#37244) --- .../src/layers/Contour/Contour.tsx | 15 +++- .../layers/Contour/getSafeCellSize.test.ts | 67 +++++++++++++++++ .../src/layers/Contour/getSafeCellSize.ts | 73 +++++++++++++++++++ .../src/layers/Contour/index.ts | 2 + 4 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/getSafeCellSize.test.ts create mode 100644 superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/getSafeCellSize.ts diff --git a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/Contour.tsx b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/Contour.tsx index 11a67569f6c6..bf5a1daf9ca8 100644 --- a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/Contour.tsx +++ b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/Contour.tsx @@ -25,6 +25,7 @@ import sandboxedEval from '../../utils/sandbox'; import { GetLayerType, createDeckGLComponent } from '../../factory'; import { ColorType } from '../../types'; import TooltipRow from '../../TooltipRow'; +import { getSafeCellSize } from './getSafeCellSize'; import { createTooltipContent, CommonTooltipRows, @@ -159,11 +160,23 @@ export const getLayer: GetLayerType = function ({ return baseTooltipContent(o); }; + const safeCellSize = getSafeCellSize({ + cellSize, + viewport: fd.viewport, + onAutoAdjust: ({ original, adjusted, estimatedCells }) => { + console.warn( + `[DeckGL Contour] cellSize=${original} would create ~${Math.round( + estimatedCells, + )} cells. Auto-adjusted to ${adjusted} to prevent WebGL crash.`, + ); + }, + }); + return new ContourLayer({ id: `contourLayer-${fd.slice_id}`, data, contours, - cellSize: Number(cellSize || '200'), + cellSize: safeCellSize, aggregation: aggregation.toUpperCase(), getPosition: (d: { position: number[]; weight: number }) => d.position as Position, diff --git a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/getSafeCellSize.test.ts b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/getSafeCellSize.test.ts new file mode 100644 index 000000000000..cb29ae81621e --- /dev/null +++ b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/getSafeCellSize.test.ts @@ -0,0 +1,67 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { + getSafeCellSize, + MIN_CELL_SIZE, + MAX_CELL_SIZE, +} from './getSafeCellSize'; + +describe('getSafeCellSize', () => { + it('defaults to 200 when value is not finite', () => { + expect(getSafeCellSize({ cellSize: 'nope' })).toBe(200); + }); + + it('clamps below minimum', () => { + expect(getSafeCellSize({ cellSize: 1 })).toBe(MIN_CELL_SIZE); + }); + + it('clamps above maximum', () => { + expect(getSafeCellSize({ cellSize: 999999 })).toBe(MAX_CELL_SIZE); + }); + + it('auto-scales when estimated grid is too large', () => { + const size = getSafeCellSize({ + cellSize: 1, + viewport: { width: 11000, height: 11000 }, + }); + + expect(size).toBeGreaterThan(MIN_CELL_SIZE); + }); + + it('never exceeds MAX_CELL_SIZE', () => { + const size = getSafeCellSize({ + cellSize: 1, + viewport: { width: 100000, height: 100000 }, + }); + + expect(size).toBeLessThanOrEqual(MAX_CELL_SIZE); + }); + + it('calls onAutoAdjust when scaling happens', () => { + const spy = jest.fn(); + + getSafeCellSize({ + cellSize: 1, + viewport: { width: 11000, height: 11000 }, + onAutoAdjust: spy, + }); + + expect(spy).toHaveBeenCalled(); + }); +}); diff --git a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/getSafeCellSize.ts b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/getSafeCellSize.ts new file mode 100644 index 000000000000..0c4a8b7fc993 --- /dev/null +++ b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/getSafeCellSize.ts @@ -0,0 +1,73 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +export const MIN_CELL_SIZE = 10; +export const MAX_CELL_SIZE = 5000; +export const MAX_GRID_CELLS = 1_000_000; + +export function getSafeCellSize({ + cellSize, + viewport, + onAutoAdjust, +}: { + cellSize?: string | number; + viewport?: { width?: number; height?: number }; + onAutoAdjust?: (info: { + original: number; + adjusted: number; + estimatedCells: number; + }) => void; +}) { + let parsedCellSize = Number(cellSize ?? 200); + if (!Number.isFinite(parsedCellSize)) { + parsedCellSize = 200; + } + + let safeCellSize = Math.min( + MAX_CELL_SIZE, + Math.max(MIN_CELL_SIZE, parsedCellSize), + ); + + if ( + viewport && + typeof viewport.width === 'number' && + typeof viewport.height === 'number' && + viewport.width > 0 && + viewport.height > 0 + ) { + const estimatedCells = + (viewport.width / safeCellSize) * (viewport.height / safeCellSize); + + if (estimatedCells > MAX_GRID_CELLS) { + const scaleFactor = Math.sqrt(estimatedCells / MAX_GRID_CELLS); + const adjustedCellSize = Math.ceil(safeCellSize * scaleFactor); + + const finalSize = Math.min(MAX_CELL_SIZE, adjustedCellSize); + + onAutoAdjust?.({ + original: safeCellSize, + adjusted: finalSize, + estimatedCells, + }); + + safeCellSize = finalSize; + } + } + + return safeCellSize; +} diff --git a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/index.ts b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/index.ts index 223fa2fa5295..c2759e0bc838 100644 --- a/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/index.ts +++ b/superset-frontend/plugins/legacy-preset-chart-deckgl/src/layers/Contour/index.ts @@ -51,3 +51,5 @@ export default class ContourChartPlugin extends ChartPlugin { }); } } + +export { getSafeCellSize } from './getSafeCellSize';