make extension activation transactional (T-377)
Three lifecycle gaps, benign among curated builtins but hazardous the day Tier-6 Lua extensions land: a throw mid-contribution left earlier contributions mounted while the extension recorded as failed (a retry then double-applied them); deactivate ignored active dependents; and the panel/command registries silently clobbered on id collision. Activation now tracks what it mounted and unwinds it all on failure (including the extension's own deactivate when its activate had succeeded); deactivate refuses with a logged warning while active dependents exist — disable the dependents first; duplicate contribution/command ids throw, which the transactional path turns into a clean failed activation with first-wins semantics. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,11 @@ class PanelRegistry extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Whether any slot already mounts a contribution with [id]. Used by the
|
||||
/// extension manager to reject duplicate ids instead of silently mounting
|
||||
/// a second copy (T-377).
|
||||
bool hasContribution(String id) => _mounts.values.any((list) => list.any((c) => c.id == id));
|
||||
|
||||
void contribute(ContributionPoint point) {
|
||||
final slot = point.slot;
|
||||
if (slot == null) return;
|
||||
|
||||
Reference in New Issue
Block a user