Skip to content

fix(invite): guard against JS double-mount - #1576

Merged
pringelmann merged 1 commit into
mainfrom
fix/invite-guest-modal-focus-race
May 22, 2026
Merged

pringelmann merged 1 commit into
mainfrom
fix/invite-guest-modal-focus-race

Conversation

@pringelmann

@pringelmann pringelmann commented May 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #1555. Modal not opening when clicking "Invite guest" in the share dialog on production NC 32.x.

Root cause

guests-init.mjs was evaluating twice in production. NC's Util::addScript appends a ?v=<hash> cache-buster to the script-tag URL, but the bundled import inside guests-main.mjs uses the bare relative path. Different URLs, the browser keys ES modules by URL, so the file runs twice and createApp(GuestForm).mount('#guest-root') happens twice.

The visible Vue instance is the last-evaluated one. OCA.Guests.openGuestDialog is reassigned during both evaluations and ends up bound to that visible instance, so Talk and contacts integrations work fine. But main.ts does import { guestForm } from './init.ts', which resolves to the bare-path module record, i.e. the orphaned first instance. The share-dialog handler then writes isOpened = true on a detached vnode and nothing visible happens.

Didn't reproduce on docker-dev because TemplateLayout::getVersionHashSuffix() returns an empty string when debug => true (which docker-dev sets by default), so both URLs match and the module loads once. Reproduces on the official nextcloud:32.0.9 Docker image and every real production install.

Fix

Make init.ts idempotent. The first evaluation creates the Vue app and stashes it on OCA.Guests._guestForm. The second evaluation reuses it instead of mounting a second app on #guest-root. openGuestDialog is assigned once after the if/else so its presence doesn't depend on which branch ran. No behavioral change for callers.

Related

The server-side fix for this exact bug already exists in NC33+: nextcloud/server#56941 added emit_import_map(), which emits an ES module importmap aliasing the bare path to the cache-busted URL. Single module record, double-mount becomes impossible. Backported to stable33 and stable34, not stable32. Asking for that backport separately. Other community apps with multi-entry bundles probably hit the same latent issue on NC32.

Test plan

Backport

stable-4.7

Signed-off-by: Peter Ringelmann <peter.ringelmann@nextcloud.com>
@pringelmann pringelmann self-assigned this May 22, 2026
@pringelmann pringelmann added bug Something isn't working 3. to review Waiting for reviews labels May 22, 2026
@pringelmann
pringelmann merged commit 33c1796 into main May 22, 2026
48 of 49 checks passed
@pringelmann
pringelmann deleted the fix/invite-guest-modal-focus-race branch May 22, 2026 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews bug Something isn't working

Projects

Development

Successfully merging this pull request may close these issues.

v4.7.1 no new guests can be added

2 participants