You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Plugin namespace isolation — detect and warn on method collisions #1977
When two plugins provide the same method name for the same mixin target, the last-loaded plugin silently overwrites the first. There is no warning, no error, and no way for plugin authors or users to know this happened.
Current Behavior
In $processMixins(), methods are collected into a struct keyed by method name. StructAppend with overwrite=true means the last plugin wins silently.
Proposed Behavior
During $processMixins(), detect when a method name already exists in the mixin collection for the same target
In development mode: log a warning listing the collision (plugin A method X overwritten by plugin B method X)
In production mode: log at debug level only
Optionally (future): allow plugin.json to declare explicit overrides to suppress the warning
Detect and warn when two plugins provide the same method name for the same mixin target, instead of silently overwriting. Currently, $processMixins() uses StructAppend semantics where the last-loaded plugin wins with no diagnostic output.
Merit Assessment
Recommendation: Proceed
This is a real pain point for plugin users — silent overwrites cause hard-to-diagnose bugs where a plugin appears loaded but its methods are missing.
The fix is purely additive (logging/warning) with no change to runtime behavior — last-loaded still wins, but now you know it happened.
Aligns with the broader plugin system improvement goals by making the mixin system observable.
Implementation Plan
Modify $processMixins() in vendor/wheels/Plugins.cfc:219-274:
At line 265, before assigning the method into variables.$class.mixins[target][methodName], check if that key already exists.
If it does, record the collision in a new variables.$class.pluginCollisions array of structs: {method, target, overwrittenBy, previousPlugin}.
To track which plugin originally provided a method, maintain a parallel struct variables.$class.mixinSources[target][methodName] = pluginName alongside the mixin assignments.
Add collision reporting:
Add a getter: getPluginCollisions() returning the collision list.
In Global.cfc:$loadPlugins() (line 2767-2786), after plugin loading, check PluginObj.getPluginCollisions().
If in development mode and collisions exist, log via $log(type="warning", ...) or store in application.wheels.pluginCollisions for display in the debug panel.
Wire into the debug/info panel:
vendor/wheels/public/views/info.cfm already displays plugin settings — add a collision warning section if application.wheels.pluginCollisions is non-empty.
Add tests:
Create a test plugin asset directory (e.g., tests/_assets/plugins/collisions/) with two plugins providing the same method name.
Verify getPluginCollisions() returns the expected collision data.
Verify the method from the alphabetically-last plugin wins (since plugins are sorted by ListSort(StructKeyList(...), "textnocase")).
Estimated complexity: Low-medium — ~20 lines in $processMixins(), ~10 lines for the getter, ~15 lines for reporting.
Activity
bpamiri commentedon Mar 16, 2026
Analysis
Synopsis
Detect and warn when two plugins provide the same method name for the same mixin target, instead of silently overwriting. Currently,
$processMixins()usesStructAppendsemantics where the last-loaded plugin wins with no diagnostic output.Merit Assessment
Recommendation: Proceed
Implementation Plan
Modify
$processMixins()invendor/wheels/Plugins.cfc:219-274:variables.$class.mixins[target][methodName], check if that key already exists.variables.$class.pluginCollisionsarray of structs:{method, target, overwrittenBy, previousPlugin}.variables.$class.mixinSources[target][methodName] = pluginNamealongside the mixin assignments.Add collision reporting:
getPluginCollisions()returning the collision list.Global.cfc:$loadPlugins()(line 2767-2786), after plugin loading, checkPluginObj.getPluginCollisions().$log(type="warning", ...)or store inapplication.wheels.pluginCollisionsfor display in the debug panel.Wire into the debug/info panel:
vendor/wheels/public/views/info.cfmalready displays plugin settings — add a collision warning section ifapplication.wheels.pluginCollisionsis non-empty.Add tests:
tests/_assets/plugins/collisions/) with two plugins providing the same method name.getPluginCollisions()returns the expected collision data.ListSort(StructKeyList(...), "textnocase")).Estimated complexity: Low-medium — ~20 lines in
$processMixins(), ~10 lines for the getter, ~15 lines for reporting.Dependencies & Risks
plugin.jsonhas anoverrideskey, collision warnings could be suppressed for intentional overwrites.ListSortat line 227), so collision results are stable across platforms.Automated analysis by @claude — review and adjust as needed.
bpamiri commentedon Mar 26, 2026
Implemented:
$processMixins()tracks method providers per target and records collisions inmixinCollisionsarray. Warnings logged in development mode.