This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new b09e60c1ec fix(deckgl-contour): prevent WebGL freeze by clamping and
auto-scaling cellSize (#37244)
b09e60c1ec is described below
commit b09e60c1ec261af5e59b5ad071ec7a4216c4675f
Author: Yousuf Ansari <[email protected]>
AuthorDate: Sun Jan 25 00:48:41 2026 +0530
fix(deckgl-contour): prevent WebGL freeze by clamping and auto-scaling
cellSize (#37244)
---
.../src/layers/Contour/Contour.tsx | 15 ++++-
.../src/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(-)
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 11a67569f6..bf5a1daf9c 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<ContourLayer> =
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 0000000000..cb29ae8162
--- /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 0000000000..0c4a8b7fc9
--- /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 223fa2fa52..c2759e0bc8 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';