Skip placeholder replies in Rapid Diffs discussions
Why
When a user replies to a diff discussion, the notes store (app/assets/javascripts/notes/store/legacy_notes, mutation SHOW_PLACEHOLDER_NOTE) inserts an optimistic placeholder note into the discussion: { id, isPlaceholderNote: true, placeholderType, notes: [{ body }] }. It has no author.
The Rapid Diffs discussion component, app/assets/javascripts/rapid_diffs/app/discussions/discussion_notes.vue, renders every non-system reply through noteable_note.vue, whose authorId computed reads this.author.id. For the placeholder this throws TypeError: Cannot read properties of undefined (reading 'id').
Under Vue 2 the error is caught, logged to the console, and the component renders blank. Users never saw a placeholder in Rapid Diffs. Under Vue 3 (@vue/compat) in the development build the error is rethrown and the whole discussion list breaks, so spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb and user_sees_avatar_on_diff_notes_spec.rb fail. That is why the Vue 3 migration of the merge request Rapid Diffs page (!252389 (merged)) was reverted (!255026 (merged)). Issue: #628791 (closed).
The legacy discussion component (app/assets/javascripts/notes/components/discussion_notes.vue) renders placeholders through dedicated PlaceholderNote and PlaceholderSystemNote components. Rapid Diffs never had that branch.
What
discussion_notes.vue: therepliescomputed also excludes notes withisPlaceholderNote, next to the existingisDraftexclusion. One line plus a comment.spec/frontend/rapid_diffs/app/discussions/discussion_notes_spec.js: two tests. Placeholder replies are not rendered throughNoteableNote, and they are excluded from theToggleRepliesWidgetreplies count.
How
This is the minimal fix for the crash. Rapid Diffs has never shown the optimistic placeholder, because Vue 2 rendered it blank. Skipping it keeps the visible behaviour unchanged. The saved reply appears when the store replaces the placeholder, as before. The replies toggle stops counting a phantom note.
Alternative: render the placeholder through placeholder components, as the legacy notes component does. !255075 (merged) does that with three helper methods, a dynamic <component :is> loop and two new components. That is optimistic-reply UI that Rapid Diffs never had, so it is split into a follow-up stacked on this MR: !255284 (closed). This MR unblocks the Vue 3 migration on its own.
The Vue 3 migration itself is re-applied in !255209 (closed), on top of !255205 (merged) (a non-production Vue 3 error handler). With this fix merged, the migration no longer depends on that handler.
How to verify
yarn jest spec/frontend/rapid_diffs/app/discussions/discussion_notes_spec.jsandVUE_VERSION=3 yarn jest spec/frontend/rapid_diffs/app/discussions/discussion_notes_spec.jspass, 32 examples each.- Feature specs: enable the Vue 3 migration of the Rapid Diffs page. Create
app/assets/javascripts/pages/projects/merge_requests/rapid_diffs/vue3_migration.ymlwithstatus: rolloutandfeature_flag: vue3_migrate_mr_rapid_diffs, plus the flag fileconfig/feature_flags/beta/vue3_migrate_mr_rapid_diffs.yml, as in !255209 (closed). Runbin/rspec spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb:49. It fails onmasterand passes with this MR. - Manually in GDK with the same flag: open a merge request's Changes tab, comment on a diff line, reply. Before: the reply never renders, and the console shows the
TypeErrorfollowed byCannot set properties of null (setting '__vnode'). After: the reply renders when saved, with no console error. Under Vue 2 (flag off) the behaviour is unchanged.
Screenshots or screen recordings
No visual change.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.
References
- Issue: #628791 (closed)
- Alternative fix that renders the placeholder; this MR is the minimal version of it: !255075 (merged)
- Follow-up stacked on this MR, optimistic reply UI: !255284 (closed)
- Original Vue 3 migration (merged, reverted): !252389 (merged), revert !255026 (merged)
- Migration re-applied: !255209 (closed), on top of the error handler !255205 (merged)
- Full-mount Jest spec for this bug class: !255198 (closed)
- Vue 3 migration (Code Review) epic: gitlab-org#23167