Skip to content

fix(command_queue): deleteFile now cascade-deletes live artboards and their state machines#111

Open
mfazekas wants to merge 1 commit into
rive-app:mainfrom
mfazekas:fix/command-server-delete-file-cascade
Open

fix(command_queue): deleteFile now cascade-deletes live artboards and their state machines#111
mfazekas wants to merge 1 commit into
rive-app:mainfrom
mfazekas:fix/command-server-delete-file-cascade

Conversation

@mfazekas

@mfazekas mfazekas commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

CommandServer::m_fileDependencies[file] is created empty at loadFile and walked by deleteFile to cascade-delete dependents, but instantiateArtboard never appends to it — so the cascade is always a no-op. Deleting a file while artboards instantiated from it are still alive orphans them (and their state machines) server-side, with no remaining documented cleanup path. Existing tests mask this by always deleting artboards explicitly before the file.

This PR:

  1. Registers the artboard in m_fileDependencies at instantiateArtboard, mirroring how instantiateStateMachine registers in m_artboardDependencies.
  2. Un-registers it in cleanupArtboard, so explicit create/delete cycles on a long-lived file don't grow the dependency vector unboundedly.
  3. Makes deleteFile detach the dependency list before cascading (since cleanupArtboard now mutates it), and erases the file only after the cascade, since dependent artboards and state machines may reference file-owned data.

Tests added to command_queue_test.cpp (the first one fails without the fix):

  1. deleteFile with two live artboards + state machines cleans all of them up.
  2. Explicit deletes followed by deleteFile stay idempotent.
  3. Commands on cascade-deleted handles go through the normal unknown-handle error path.

Full unit test suite passes.

… their state machines

CommandServer::m_fileDependencies[file] was created empty at loadFile and
walked by deleteFile, but instantiateArtboard never appended to it - so the
cascade was always a no-op. Deleting a file while artboards instantiated
from it were still alive orphaned them (and their state machines)
server-side, unreachable through any cleanup path.

- instantiateArtboard now registers the artboard in m_fileDependencies,
  mirroring how instantiateStateMachine registers in m_artboardDependencies.
- cleanupArtboard un-registers the artboard from m_fileDependencies so
  explicit create/delete cycles on a long-lived file don't grow the
  dependency vector unboundedly.
- deleteFile detaches the dependency list before cascading (cleanupArtboard
  now mutates it) and erases the file only after the cascade, since
  dependent artboards and state machines may reference file-owned data.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes CommandServer::deleteFile dependency cascading so that deleting a file also deletes any live artboards instantiated from it (and their state machines), preventing server-side orphan instances and adding regression tests to cover the behavior.

Changes:

  • Register instantiated artboards into m_fileDependencies and cascade-delete them from deleteFile.
  • Unregister artboards from file dependency tracking during cleanupArtboard, and adjust deleteFile to detach the dependency list before iterating.
  • Add unit tests validating cascade deletion, idempotency with explicit deletes, and safe rejection of commands on cascade-deleted handles.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
tests/unit_tests/runtime/command_queue_test.cpp Adds regression tests for cascade deletion behavior and unknown-handle safety after deleteFile.
src/command_server.cpp Implements file→artboard dependency registration and safe cascade deletion ordering in deleteFile.
include/rive/command_server.hpp Updates cleanupArtboard to unregister artboards from m_fileDependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +177 to +181
for (auto& fileDependency : m_fileDependencies)
{
auto& artboardVector = fileDependency.second;
artboardVector.erase(std::remove(artboardVector.begin(),
artboardVector.end(),
Comment thread src/command_server.cpp
Comment on lines +1030 to +1032
assert(m_fileDependencies.find(fileHandle) !=
m_fileDependencies.end());
m_fileDependencies[fileHandle].push_back(handle);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants