fix: keep bypass/mute state on frontend 1.53+ node shell state (#1123)

ComfyUI frontend 1.53 turned LGraphNode.mode into a prototype accessor
backed by node._state, and serialize() now reads that state directly.
Redefining mode on the instance shadowed the setter, so bypass/mute
never reached the serialized workflow and silently reverted to Always
on save/reload or workflow tab switch.

Add interceptModeChange() in web/comfyui/utils.js: it delegates to the
prototype accessor when one exists (observing changes only), and falls
back to the legacy closure accessor on older frontends. Use it in
lora_loader.js and in the Vue widgets' setupModeChangeHandler, which
covers the LoRA provider/aggregator nodes with the same latent bug.
This commit is contained in:
Will Miao
2026-09-25 18:12:01 +08:00
parent dae18b3d1d
commit 067e605e75
8 changed files with 360 additions and 120 deletions
+10 -16
View File
@@ -10,6 +10,7 @@ import {
collectActiveLorasFromChain,
updateConnectedTriggerWords,
chainCallback,
interceptModeChange,
mergeLoras,
getAllGraphNodes,
getNodeFromGraph,
@@ -189,24 +190,17 @@ app.registerExtension({
let isUpdating = false;
let isSyncingInput = false;
// Mechanism: Property descriptor to listen for mode changes
// Mechanism: Observe mode changes without shadowing the frontend's
// own `mode` accessor (frontend >= 1.53 serializes from shell state,
// so redefining `mode` here would silently revert bypass/mute).
const self = this;
let _mode = this.mode;
Object.defineProperty(this, 'mode', {
get() {
return _mode;
},
set(value) {
const oldValue = _mode;
_mode = value;
// Trigger mode change handler
if (self.onModeChange) {
self.onModeChange(value, oldValue);
}
console.log(`[Lora Loader] Node mode changed from ${oldValue} to ${value}`);
interceptModeChange(this, (newMode, oldMode) => {
// Trigger mode change handler
if (self.onModeChange) {
self.onModeChange(newMode, oldMode);
}
console.log(`[Lora Loader] Node mode changed from ${oldMode} to ${newMode}`);
});
// Define the mode change handler