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';

Reply via email to