codeant-ai-for-open-source[bot] commented on code in PR #41285:
URL: https://github.com/apache/superset/pull/41285#discussion_r3498038673
##########
superset-frontend/src/SqlLab/components/SqlEditor/index.tsx:
##########
@@ -271,6 +302,48 @@ const SqlEditor: FC<Props> = ({
const logAction = useLogAction({ queryEditorId: queryEditor.id });
const isActive = currentQueryEditorId === queryEditor.id;
+
+ // Re-renders when an extension registers a northPane view after async load.
+ const northPaneViews = useViews(ViewLocations.sqllab.northPane) || [];
+
+ // Resolve the per-tab localStorage key the same way every other SQL Lab
+ // consumer does (`tabViewId ?? id`), so the value written, read back, and
+ // observed via the `storage` event all agree once a tab is
backend-persisted.
+ const northPaneStorageId = queryEditor.tabViewId ?? queryEditor.id;
+
+ // ID of the northPane view active for this tab, or null for the default
+ // SQL editor layout. Set by an extension via PENDING_NORTH_PANE_VIEW_KEY
+ // before calling createTab(); persisted per-tab in localStorage.
+ const [northPaneViewId, setNorthPaneViewId] = useState<string | null>(() => {
+ const pendingViewId = readNorthPaneStorage(PENDING_NORTH_PANE_VIEW_KEY);
+ if (pendingViewId) {
+ writeNorthPaneStorage(PENDING_NORTH_PANE_VIEW_KEY, null);
+ writeNorthPaneStorage(
+ NORTH_PANE_VIEW_KEY(northPaneStorageId),
+ pendingViewId,
+ );
+ return pendingViewId;
Review Comment:
**Suggestion:** Using a single global localStorage key to pass the pending
north-pane mode creates a race when multiple tab-creation actions happen before
React mounts the new editor. The last writer wins, so one tab can consume
another tab’s mode. Store the desired mode in tab-scoped state tied to the
created tab id (or pass it through createTab options/redux) instead of a
process-wide shared key. [race condition]
<details>
<summary><b>Severity Level:</b> Major ⚠️</summary>
```mdx
- ❌ Extension-created SQL Lab tabs open wrong pane view.
- ⚠️ North-pane mode persistence unreliable for multi-tab workflows.
```
</details>
<details>
<summary><b>Steps of Reproduction ✅ </b></summary>
```mdx
1. Extension authors follow the documented pattern in
`superset-frontend/src/SqlLab/contributions.ts:61-72`, calling
`localStorage.setItem(PENDING_NORTH_PANE_VIEW_KEY, 'ext.view1')` then
`sqlLab.createTab({
title: 'Tab 1' })`, and immediately afterwards
`localStorage.setItem(PENDING_NORTH_PANE_VIEW_KEY, 'ext.view2')` then
`sqlLab.createTab({
title: 'Tab 2' })` before the first `SqlEditor` has mounted.
2. The `sqlLab.createTab()` implementation in
`superset-frontend/src/core/sqlLab/index.ts:12-74` dispatches
`addQueryEditor` and returns
Tab objects, but it does not read or clear `PENDING_NORTH_PANE_VIEW_KEY`, so
the global
key keeps the last written value (`'ext.view2'`) while both tabs are being
created.
3. When React mounts the `SqlEditor` component for Tab 1, the `useState`
initializer at
`superset-frontend/src/SqlLab/components/SqlEditor/index.tsx:68-79` executes
`const
pendingViewId = readNorthPaneStorage(PENDING_NORTH_PANE_VIEW_KEY);` (line
318), sees the
second tab's value (`'ext.view2'`), clears the global key, writes
`NORTH_PANE_VIEW_KEY(northPaneStorageId)` for Tab 1, and returns that value
as
`northPaneViewId`.
4. When `SqlEditor` for Tab 2 mounts, `pendingViewId` is now null because
Tab 1 cleared
the shared key; Tab 2 falls back to
`readNorthPaneStorage(NORTH_PANE_VIEW_KEY(northPaneStorageId))`, which is
empty, so Tab 1
incorrectly opens in mode `ext.view2` while Tab 2 opens the default SQL
editor layout,
demonstrating the cross-tab race caused by the global pending-mode key.
```
</details>
[](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=191549345e0747fc8eea81f3d05fa864&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
[](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=191549345e0747fc8eea81f3d05fa864&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:** superset-frontend/src/SqlLab/components/SqlEditor/index.tsx
**Line:** 318:325
**Comment:**
*Race Condition: Using a single global localStorage key to pass the
pending north-pane mode creates a race when multiple tab-creation actions
happen before React mounts the new editor. The last writer wins, so one tab can
consume another tab’s mode. Store the desired mode in tab-scoped state tied to
the created tab id (or pass it through createTab options/redux) instead of a
process-wide shared key.
Validate the correctness of the flagged issue. If correct, How can I resolve
this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41285&comment_hash=159c23cb979a8c30e3fbbcdc150ccc56ac07d36ce5187213065e3cedfda09821&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41285&comment_hash=159c23cb979a8c30e3fbbcdc150ccc56ac07d36ce5187213065e3cedfda09821&reaction=dislike'>👎</a>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]