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


##########
superset-frontend/src/preamble.ts:
##########
@@ -38,67 +39,102 @@ import 'dayjs/plugin/duration';
 import 'dayjs/plugin/updateLocale';
 import 'dayjs/plugin/localizedFormat';
 
-configure();
+let initPromise: Promise<void> | null = null;
 
-// Set hot reloader config
-if (process.env.WEBPACK_MODE === 'development') {
-  setHotLoaderConfig({ logLevel: 'debug', trackTailUpdates: false });
-}
+const LANGUAGE_PACK_REQUEST_TIMEOUT_MS = 5000;
 
-// Grab initial bootstrap data
-const bootstrapData = getBootstrapData();
-
-setupFormatters(
-  bootstrapData.common.d3_format,
-  bootstrapData.common.d3_time_format,
-);
-
-// Setup SupersetClient early so we can fetch language pack
-setupClient({ appRoot: applicationRoot() });
-
-// Load language pack before anything else
-(async () => {
-  const lang = bootstrapData.common.locale || 'en';
-  if (lang !== 'en') {
-    try {
-      // Second call to configure to set the language pack
-      const { json } = await SupersetClient.get({
-        endpoint: `/superset/language_pack/${lang}/`,
-      });
-      configure({ languagePack: json as LanguagePack });
-      dayjs.locale(lang);
-    } catch (err) {
-      console.warn(
-        'Failed to fetch language pack, falling back to default.',
-        err,
-      );
-      configure();
-      dayjs.locale('en');
-    }
+export default function initPreamble(): Promise<void> {
+  if (initPromise) {
+    return initPromise;
   }
 
-  // Continue with rest of setup
-  initFeatureFlags(bootstrapData.common.feature_flags);
+  initPromise = (async () => {
+    configure();
 
-  setupColors(
-    bootstrapData.common.extra_categorical_color_schemes,
-    bootstrapData.common.extra_sequential_color_schemes,
-  );
+    // Set hot reloader config
+    if (process.env.WEBPACK_MODE === 'development') {
+      setHotLoaderConfig({ logLevel: 'debug', trackTailUpdates: false });
+    }
 
-  setupDashboardComponents();
+    // Grab initial bootstrap data
+    const bootstrapData = getBootstrapData();
 
-  const getMe = makeApi<void, User>({
-    method: 'GET',
-    endpoint: '/api/v1/me/',
-  });
+    setupFormatters(
+      bootstrapData.common.d3_format,
+      bootstrapData.common.d3_time_format,
+    );
 
-  if (bootstrapData.user?.isActive) {
-    document.addEventListener('visibilitychange', () => {
-      if (document.visibilityState === 'visible') {
-        getMe().catch(() => {
-          // SupersetClient will redirect to login on 401
+    // Setup SupersetClient early so we can fetch language pack
+    setupClient({ appRoot: applicationRoot() });
+
+    // Load language pack before rendering
+    // Use native fetch to avoid race condition with SupersetClient 
initialization
+    const lang = bootstrapData.common.locale || 'en';
+    if (lang !== 'en') {
+      const abortController = new AbortController();
+      const timeoutId = window.setTimeout(() => {
+        abortController.abort();
+      }, LANGUAGE_PACK_REQUEST_TIMEOUT_MS);
+
+      try {
+        const languagePackUrl = makeUrl(`/superset/language_pack/${lang}/`);

Review Comment:
   **Suggestion:** The language pack URL is built with `makeUrl` and already 
includes the `/superset` prefix, which will cause a double-prefix (e.g. 
`/superset/superset/...`) in deployments where `makeUrl` prepends the 
application root or URL prefix, leading to 404s for the language pack and 
silent fallback to English translations. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Login page translations revert to English unexpectedly.
   - ❌ Any pre-render pages use fallback locale.
   - ⚠️ Console shows language pack fetch failure warnings.
   ```
   </details>
   
   ```suggestion
           const languagePackUrl = makeUrl(`/language_pack/${lang}/`);
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Ensure the frontend is served with a non-English default locale encoded 
in bootstrap
   data. The bootstrap consumer reads the data-bootstrap attribute in
   src/utils/getBootstrapData.ts (lines 24-34). Set that attribute (server-side 
or by
   starting the app with BABEL_DEFAULT_LOCALE) so bootstrapData.common.locale 
!== 'en'.
   
   2. Load a page that includes the preamble module (this module is prepended 
to multiple
   webpack entrypoints). The preamble's init function is defined at
   superset-frontend/src/preamble.ts:46 and is invoked eagerly at the bottom of 
the same file
   (see lines ~136-140 where initPreamble().catch(...) is called). This triggers
   initPreamble() during page load.
   
   3. Inside initPreamble(), the selected lang is computed at preamble.ts:72 
(const lang =
   bootstrapData.common.locale || 'en';). For a non-en locale the code enters 
the fetch
   branch and constructs the language pack URL at preamble.ts:80 (const 
languagePackUrl =
   makeUrl(`/superset/language_pack/${lang}/`);). The code then calls 
fetch(languagePackUrl)
   at preamble.ts:81-83.
   
   4. If makeUrl already prefixes the application root (for example, adding 
'/superset' or a
   URL prefix), passing a path that already contains '/superset' yields a 
doubled prefix
   (e.g. '/superset/superset/language_pack/…') so the network request performed 
at
   preamble.ts:81 results in a 404. The fetch's non-ok response (or network 
404) causes the
   code path at preamble.ts:84-89 to throw and the catch at preamble.ts:90-97 
to run, which
   calls configure() fallback and dayjs.locale('en'), producing English 
translations despite
   the configured non-English locale. Verify by observing the failed network 
request URL in
   browser DevTools Network tab and the console warning printed at 
preamble.ts:91-94 ("Failed
   to fetch language pack, falling back to default.").
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/preamble.ts
   **Line:** 80:80
   **Comment:**
        *Logic Error: The language pack URL is built with `makeUrl` and already 
includes the `/superset` prefix, which will cause a double-prefix (e.g. 
`/superset/superset/...`) in deployments where `makeUrl` prepends the 
application root or URL prefix, leading to 404s for the language pack and 
silent fallback to English translations.
   
   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.
   ```
   </details>



##########
superset-frontend/src/views/index.tsx:
##########
@@ -19,6 +19,20 @@
 import 'src/public-path';
 
 import ReactDOM from 'react-dom';
-import App from './App';
+import initPreamble from 'src/preamble';
 
-ReactDOM.render(<App />, document.getElementById('app'));
+const appMountPoint = document.getElementById('app');
+
+if (appMountPoint) {
+  (async () => {
+    try {
+      await initPreamble();
+    } finally {
+      const { default: App } = await import(/* webpackMode: "eager" */ 
'./App');
+      ReactDOM.render(<App />, appMountPoint);
+    }
+  })().catch(err => {
+    // eslint-disable-next-line no-console
+    console.error('Unhandled error during app initialization', err);
+  });
+}

Review Comment:
   **Suggestion:** If the `#app` mount element is missing from the DOM (for 
example due to an HTML/template regression), the current code does nothing and 
fails silently, leaving users with a blank page and no diagnostics; adding an 
explicit error log makes this failure mode visible and easier to debug. [logic 
error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Login and main UI render produce a blank page.
   - ⚠️ No diagnostic message appears in console.
   - ⚠️ Template regressions harder to debug without logs.
   ```
   </details>
   
   ```suggestion
   } else {
     // eslint-disable-next-line no-console
     console.error('Failed to initialize app: mount point element with id "app" 
was not found.');
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Inspect the mount logic in src/views/index.tsx and confirm the guard uses
   document.getElementById('app') at line 24 and conditional at 
src/views/index.tsx:26-38.
   
   2. Reproduce missing-mount by serving an HTML page without the <div 
id="app"> element (or
   by removing it in browser DevTools) so document.getElementById('app') 
returns null at page
   load.
   
   3. Reload the page; code at src/views/index.tsx:26 evaluates false and the 
if-block is
   skipped, causing no further logs or rendering to occur.
   
   4. Observe a blank page with no console diagnostic from this entrypoint; the 
suggested
   else branch would log an explicit error to aid debugging.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/views/index.tsx
   **Line:** 38:38
   **Comment:**
        *Logic Error: If the `#app` mount element is missing from the DOM (for 
example due to an HTML/template regression), the current code does nothing and 
fails silently, leaving users with a blank page and no diagnostics; adding an 
explicit error log makes this failure mode visible and easier to debug.
   
   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.
   ```
   </details>



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