Frontmatter
| id | 9586 |
| title | Analysis: Robust Multi-Window LivePreview Routing & Base Path Resolution |
| state | Closed |
| labels | enhancementaiarchitecture |
| assignees | tobiu |
| createdAt | Mar 27, 2026, 4:08 PM |
| updatedAt | Mar 27, 2026, 6:51 PM |
| githubUrl | https://github.com/neomjs/neo/issues/9586 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Mar 27, 2026, 6:51 PM |
Analysis: Robust Multi-Window LivePreview Routing & Base Path Resolution
tobiu cross-referenced by #9585 on Mar 27, 2026, 4:09 PM
tobiu assigned to @tobiu on Mar 27, 2026, 4:10 PM

tobiu
Mar 27, 2026, 6:50 PM
Input from Gemini 3.1 Pro (Antigravity):
✦ > Resolution Summary:
The
LivePreviewmulti-window regression has been successfully resolved.Root Cause: The issue stemmed from a timing race condition where
MainThreadAddons(likeResizeObserver) were not fully imported into the newly spawned popup window before theRemoteMethodAccess(RMA) mixin attempted to interface with them. This occurred because theAppworker was caching the addon requests at the application level, bypassing theimportAddonstep for additional windows once the addon was loaded in the initial window.Fixes Implemented:
src/worker/App.mjs: RefactoredgetAddon()to track addon loading on a per-window basis (${addonName}X${windowId}). This guarantees that when a component is moved to a new popout window (e.g., inLivePreview), the worker explicitly invokesNeo.Main.importAddonfor that specificwindowId.src/Main.mjs: Ensured theregisterAddon()method behaves idempotently. Dynamically importing an addon that is already registered no longer clobbers existing instances, avoiding unnecessary errors.- Validation: Implemented a new Playwright E2E test suite (
test/playwright/e2e/LivePreviewMultiWindow.spec.mjs) that structurally validates the popout functionality across all three environments (Dev,Dist Dev, andDist Prod) and both route contexts (HomeandLearn), specifically asserting against "Invalid remote namespace" errors.All matrix evaluations are currently passing!
tobiu closed this issue on Mar 27, 2026, 6:51 PM
Background
During v12.1.0 development, we deleted
src/code/LivePreview.mjs#beforeSetWindowUrl. This manual path calculation was originally added in #8074 to solve Windows OS path separator issues and nested "recursive" popouts. However, mapping the SharedWorker'sbasePathupward directly to the repo root fundamentally stripped out environment prefixes likedist/development/.Current State
The system now relies entirely on the Main thread's native browser relative URL resolution (e.g., evaluating
./childapps/preview/index.htmlstrictly againstlocation.href). Initial macOS testing confirms that this successfully resolves for popouts executed from both the Portal Home route and the Learn route, preventing environment-jumping bugs.Risk & Verification Plan
We must perform a matrix validation to ensure the native Main thread resolution handles all historical edge cases:
\) bug (#9365) does not regress without the manual split/join logic.LivePreviewcomponents located in apps with varying structural depths (e.g.,apps/portalvsexamples/component/button).development(raw),dist/development(bundled), anddist/production.childapps/preview/childapps/preview/).