Skip to content

Commit e7be41a

Browse files
committed
fix(frontend): stop duplicate tauri bootstrap and gpu link errors
1 parent 947f97b commit e7be41a

4 files changed

Lines changed: 41 additions & 12 deletions

File tree

src/frontend/index.html

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,9 +1625,6 @@ <h3>Select Target Node</h3>
16251625
<script src="path_app.js"></script>
16261626

16271627
<!-- ES Module Entry (Vite dev/build) - loads after legacy scripts for backward compat -->
1628-
<script>
1629-
window.__NC_DISABLE_MODULE_BOOT = true;
1630-
</script>
16311628
<script type="module" src="./main.mjs"></script>
16321629
</body>
16331630
</html>

src/frontend/layout_gpu.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,17 @@ class GPULinkForce {
232232
const nLinks = this._links.length;
233233
console.log(`[GPULink] Initializing for ${n} nodes, ${nLinks} links.`);
234234

235-
if (n === 0) return;
235+
if (this.kernel) {
236+
this.kernel.destroy();
237+
this.kernel = null;
238+
}
239+
240+
if (n === 0 || nLinks === 0) {
241+
this.adjHead = new Float32Array(n);
242+
this.adjCount = new Float32Array(n);
243+
this.flatIndices = new Float32Array(0);
244+
return;
245+
}
236246

237247
// Build Adjacency List (Source <-> Target)
238248
// D3 Link Force is symmetric: force acts on both ends.
@@ -295,8 +305,6 @@ class GPULinkForce {
295305
// Limit max neighbors width for texture if needed?
296306
// gpu.js handles 1D arrays well.
297307

298-
if (this.kernel) this.kernel.destroy();
299-
300308
// ---------------------------------------------------------
301309
// KERNEL
302310
// ---------------------------------------------------------
@@ -368,7 +376,7 @@ class GPULinkForce {
368376
}
369377

370378
force(alpha) {
371-
if (!this.available || this.nodes.length === 0) return;
379+
if (!this.available || this.nodes.length === 0 || this._links.length === 0 || this.flatIndices.length === 0) return;
372380

373381
const n = this.nodes.length;
374382
const posX = new Float32Array(n);

src/frontend/main.mjs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,27 @@
99
* the legacy payload scripts as side-effect imports.
1010
*/
1111

12+
function shouldSkipModuleBootstrap() {
13+
if (typeof window === 'undefined') {
14+
return false;
15+
}
16+
17+
// Legacy IIFE bootstrap is the active production path on index.html.
18+
// If it is already present, the module chain must stay dormant to avoid
19+
// duplicate i18n/runtime/app initialization and graph state races.
20+
if (window.i18n || window.NoteConnectionRuntime || window.settingsManager) {
21+
return true;
22+
}
23+
24+
const scriptTags = Array.from(document.querySelectorAll('script[src]'));
25+
return scriptTags.some((tag) => {
26+
const src = String(tag.getAttribute('src') || '').trim();
27+
return src.endsWith('i18n.js')
28+
|| src.endsWith('runtime_bridge.js')
29+
|| src.endsWith('source_manager.js');
30+
});
31+
}
32+
1233
async function bootModuleFrontend() {
1334
// 1. Foundation modules (ES module versions with window backward compat)
1435
await import('./i18n.mjs');
@@ -23,17 +44,17 @@ async function bootModuleFrontend() {
2344
// 3. Legacy IIFE modules (loaded as side-effect scripts; these register on window.*)
2445
await import('./workspace_panes.js');
2546
await import('./agent_workspace.js');
47+
await import('./storage_provider.js');
2648
await import('./settings.js');
2749
await import('./source_manager.js');
28-
await import('./storage_provider.js');
2950

3051
// 4. Large application payloads (loaded as side-effect modules)
3152
await import('./path_app.js');
3253
await import('./app.js');
3354
}
3455

35-
if (typeof window !== 'undefined' && window.__NC_DISABLE_MODULE_BOOT === true) {
36-
console.log('[main.mjs] Module frontend bootstrap disabled because legacy script bootstrap is active.');
56+
if (shouldSkipModuleBootstrap()) {
57+
console.log('[main.mjs] Module frontend bootstrap skipped because the legacy script bootstrap is active.');
3758
} else {
3859
void bootModuleFrontend();
3960
}

src/source_manager.loadflow.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,11 @@ describe('source manager load-flow guards', () => {
9797
const mainModulePath = path.join(repoRoot, 'src', 'frontend', 'main.mjs');
9898
const indexHtml = fs.readFileSync(indexPath, 'utf8');
9999
const mainModule = fs.readFileSync(mainModulePath, 'utf8');
100-
expect(indexHtml).toContain('window.__NC_DISABLE_MODULE_BOOT = true;');
101-
expect(mainModule).toContain("if (typeof window !== 'undefined' && window.__NC_DISABLE_MODULE_BOOT === true)");
100+
expect(indexHtml).toContain('<script type="module" src="./main.mjs"></script>');
101+
expect(indexHtml).not.toContain('window.__NC_DISABLE_MODULE_BOOT = true;');
102+
expect(mainModule).toContain('function shouldSkipModuleBootstrap()');
103+
expect(mainModule).toContain('window.i18n || window.NoteConnectionRuntime || window.settingsManager');
104+
expect(mainModule).toContain("src.endsWith('i18n.js')");
102105
expect(mainModule).toContain("await import('./i18n.mjs');");
103106
expect(mainModule).not.toContain("import './i18n.mjs';");
104107
});

0 commit comments

Comments
 (0)