codeant-ai-for-open-source[bot] commented on code in PR #39893:
URL: https://github.com/apache/superset/pull/39893#discussion_r3190165277


##########
superset-frontend/src/embedded/index.tsx:
##########
@@ -196,7 +196,11 @@ function start() {
       if (!root) {
         root = createRoot(appMountPoint);
       }
-      root.render(<EmbeddedApp />);
+      root.render(
+        <StrictMode>
+          <EmbeddedApp />
+        </StrictMode>,
+      );

Review Comment:
   **Suggestion:** Wrapping the embedded tree in `StrictMode` will trigger an 
extra mount/unmount cycle in development, and this code path includes a Redux 
`store.subscribe` side effect inside render (`EmbededLazyDashboardPage`) 
without cleanup. That causes duplicate active subscriptions and repeated 
`observeDataMask` emissions after startup. Move the subscription logic into an 
effect with cleanup (or gate StrictMode here until that cleanup is implemented) 
so StrictMode does not create leaked duplicate listeners. [memory leak]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Embedded dev dashboards emit duplicate observeDataMask events per change.
   - ⚠️ Host apps receive duplicated observeDataMask callbacks in development.
   - ⚠️ Redux store subscriptions accumulate without cleanup in embedded iframe.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. In a host app, call `embedDashboard` from 
`superset-embedded-sdk/src/index.ts` with
   `dashboardUiConfig.emitDataMasks: true` (see `UiConfigType.emitDataMasks` at 
lines 36-40
   and `calculateConfig()` adding `+16` for `emitDataMasks` at lines 143-156, 
then
   `dashboardConfigUrlParams` including `uiConfig` at lines 168-170). This 
generates an
   iframe src like `/embedded/<id>?uiConfig=<bitmask>`.
   
   2. The iframe loads the embedded frontend route defined in
   `superset-frontend/src/embedded/index.tsx` where `EmbeddedApp` (lines 
117-123) renders
   `<Route path="/embedded/:uuid/" component={EmbeddedRoute} />`. 
`EmbeddedRoute` (lines
   96-115) wraps children in `EmbeddedContextProviders`, which in turn wraps 
them in
   `EmbeddedUiConfigProvider` 
(`superset-frontend/src/components/UiConfigContext/index.tsx`
   lines 48-66).
   
   3. Inside `EmbeddedUiConfigProvider`, `getUrlParam(URL_PARAMS.uiConfig)` 
(lines 51-59 of
   `UiConfigContext/index.tsx`) decodes the `uiConfig` bitmask and sets 
`emitDataMasks:
   (config & 16) !== 0`. `EmbededLazyDashboardPage` in
   `superset-frontend/src/embedded/index.tsx` (lines 69-94) calls 
`useUiConfig()`, and when
   `uiConfig.emitDataMasks` is true, it executes the side-effect block at lines 
73-91 that
   declares `let previousDataMask = store.getState().dataMask;` and calls 
`store.subscribe(()
   => { ... Switchboard.emit('observeDataMask', ...) })` at lines 76-88, with 
no captured
   unsubscribe function or cleanup.
   
   4. The embedded app is started when the iframe's `MessageChannel` handshake 
triggers
   `Switchboard.defineMethod('guestToken', ...)` in
   `superset-frontend/src/embedded/index.tsx` (lines 259-264), which calls
   `setupGuestClient(guestToken)` and then `start()`. In `start()` (same file, 
lines
   179-217), after fetching `/api/v1/me/roles/`, the code creates the React 
root if needed
   and then calls `root.render(<StrictMode><EmbeddedApp /></StrictMode>);` at 
lines 197-203
   (the PR's new code).
   
   5. In development builds, React 18 `StrictMode` intentionally double-invokes 
function
   components on initial mount. As a result, `EmbededLazyDashboardPage`'s 
function body
   (including the `store.subscribe` call at line 78) runs twice, registering 
two Redux
   subscriptions without any corresponding unsubscribe on unmount. On each 
subsequent
   data-mask-related store update, both subscribers execute, each calling
   `Switchboard.emit('observeDataMask', ...)` (lines 84-87), so the host's 
`observeDataMask`
   callback registered via `ourPort.defineMethod('observeDataMask', 
callbackFn)` in
   `superset-embedded-sdk/src/index.ts` (lines 34-38 of the second chunk) is 
invoked multiple
   times per state change. Because no cleanup exists, these subscriptions 
persist for the
   lifetime of the page, creating leaked duplicate listeners specifically 
exposed by the new
   StrictMode wrapper.
   ```
   </details>
   
   [Fix in 
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt=This%20is%20a%20comment%20left%20during%20a%20code%20review.%0A%0A%2A%2APath%3A%2A%2A%20superset-frontend%2Fsrc%2Fembedded%2Findex.tsx%0A%2A%2ALine%3A%2A%2A%20199%3A203%0A%2A%2AComment%3A%2A%2A%0A%09%2AMemory%20Leak%3A%20Wrapping%20the%20embedded%20tree%20in%20%60StrictMode%60%20will%20trigger%20an%20extra%20mount%2Funmount%20cycle%20in%20development%2C%20and%20this%20code%20path%20includes%20a%20Redux%20%60store.subscribe%60%20side%20effect%20inside%20render%20%28%60EmbededLazyDashboardPage%60%29%20without%20cleanup.%20That%20causes%20duplicate%20active%20subscriptions%20and%20repeated%20%60observeDataMask%60%20emissions%20after%20startup.%20Move%20the%20subscription%20logic%20into%20an%20effect%20with%20cleanup%20%28or%20gate%20StrictMode%20here%20until%20that%20cleanup%20is%20implemented%29%20so%20StrictMode%20does%20not%20create%20leaked%20duplicate%20listeners.%0A%0AValidate%20the%20correctness%20of%20the%20
 
flagged%20issue.%20If%20correct%2C%20How%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20implement%20it%20and%20please%20make%20it%20concise.%0AOnce%20fix%20is%20implemented%2C%20also%20check%20other%20comments%20on%20the%20same%20PR%2C%20and%20ask%20user%20if%20the%20user%20wants%20to%20fix%20the%20rest%20of%20the%20comments%20as%20well.%20if%20said%20yes%2C%20then%20fetch%20all%20the%20comments%20validate%20the%20correctness%20and%20implement%20a%20minimal%20fix%0A)
 | [Fix in VSCode 
Claude](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt=This%20is%20a%20comment%20left%20during%20a%20code%20review.%0A%0A%2A%2APath%3A%2A%2A%20superset-frontend%2Fsrc%2Fembedded%2Findex.tsx%0A%2A%2ALine%3A%2A%2A%20199%3A203%0A%2A%2AComment%3A%2A%2A%0A%09%2AMemory%20Leak%3A%20Wrapping%20the%20embedded%20tree%20in%20%60StrictMode%60%20will%20trigger%20an%20extra%20mount%2Funmount%20cycle%20in%20development%2C%20and%20this%20code%20path%20includes%20a%20Redux%20%60store.subs
 
cribe%60%20side%20effect%20inside%20render%20%28%60EmbededLazyDashboardPage%60%29%20without%20cleanup.%20That%20causes%20duplicate%20active%20subscriptions%20and%20repeated%20%60observeDataMask%60%20emissions%20after%20startup.%20Move%20the%20subscription%20logic%20into%20an%20effect%20with%20cleanup%20%28or%20gate%20StrictMode%20here%20until%20that%20cleanup%20is%20implemented%29%20so%20StrictMode%20does%20not%20create%20leaked%20duplicate%20listeners.%0A%0AValidate%20the%20correctness%20of%20the%20flagged%20issue.%20If%20correct%2C%20How%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20implement%20it%20and%20please%20make%20it%20concise.%0AOnce%20fix%20is%20implemented%2C%20also%20check%20other%20comments%20on%20the%20same%20PR%2C%20and%20ask%20user%20if%20the%20user%20wants%20to%20fix%20the%20rest%20of%20the%20comments%20as%20well.%20if%20said%20yes%2C%20then%20fetch%20all%20the%20comments%20validate%20the%20correctness%20and%20implement%20a%20minimal%20fix%0A)
   
   *(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/embedded/index.tsx
   **Line:** 199:203
   **Comment:**
        *Memory Leak: Wrapping the embedded tree in `StrictMode` will trigger 
an extra mount/unmount cycle in development, and this code path includes a 
Redux `store.subscribe` side effect inside render (`EmbededLazyDashboardPage`) 
without cleanup. That causes duplicate active subscriptions and repeated 
`observeDataMask` emissions after startup. Move the subscription logic into an 
effect with cleanup (or gate StrictMode here until that cleanup is implemented) 
so StrictMode does not create leaked duplicate listeners.
   
   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%2F39893&comment_hash=de0dbfaa1511c4ef04ebdae480a2b1a20290243b80d9371f70f3cbc3e087a622&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F39893&comment_hash=de0dbfaa1511c4ef04ebdae480a2b1a20290243b80d9371f70f3cbc3e087a622&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]

Reply via email to