Skip to content

Commit 3ad44fc

Browse files
author
mergetest
committed
Stop a dispel slot-style failure spamming errors and gutting FullFrameRefresh
ApplyOverlayLayout throws "calling 'ClearAllPoints' on bad self (forbidden object)" on the 12.1 slot path, because the overlay's border StatusBars are unbound descendants of Blizzard's secret aura button. The root cause needs a live probe to pin down; this change contains the damage it does meanwhile. Two things made one failure permanent and loud: * CacheLayoutState is the LAST statement of ApplyOverlayLayout, so a throw skips it, LayoutStateChanged keeps returning true, and the fast path never engages. The throw also unwinds past the version/generation latches in DriveDispelOverlayFactory, so every drive re-entered the same failing pass -- 68 identical errors from a single key. * UpdateDispelOverlay runs from FullFrameRefresh ahead of highlights, status icons, resource bar layout, absorbs and heal prediction. Throwing there abandoned all five on that frame, silently. Per-button styling is now pcall'd (split out as StyleOneSlot), `styled` means "we ran the pass" rather than "it worked" so the latch still lands, and the first failure logs one DebugWarn instead of a flood. FullFrameRefresh guards the dispel call so one broken element can't take the other five down. The overlay artwork itself is still broken -- unchanged by this.
1 parent ffaca1f commit 3ad44fc

3 files changed

Lines changed: 73 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ DandersFrames has been rebuilt for WoW 12.1 (Midnight), which fundamentally chan
199199
* (Click Casting) Fixed hover keybinds dying for the rest of the session on some frames after visiting player housing. (by Krathe)
200200
* (Click Casting) Fixed cast-on-down silently switching itself off on Blizzard's own raid and party frames after every roster change. (by Krathe)
201201
* (Pet Frames) Fixed pet frames never appearing in arena (2v2, 3v3 and Solo Shuffle). Arena counts as a raid to the game, so pet frames were being looked for on the raid frames — which arena does not use. They now build alongside the arena frames, and follow your Party pet settings. (by Krathe)
202+
* (Dispel) Fixed repeating error popups when a dispellable debuff appeared on a frame. The same error was also stopping highlights, status icons, the resource bar, absorbs and heal prediction from updating on that frame. The overlay's own artwork is still being worked on.
203+
* (Integrations) "Use DF Color Picker" and "Use DF Color Picker for All Addons" are now single settings shared by Party and Raid, applying to your whole account. Ticking them on the Raid tab previously did nothing at all. Your existing choice carries over. They no longer travel with profile imports and exports.
202204

203205
### Improvements
204206

DandersFrames/Features/Dispel.lua

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,7 @@ local GAME_ICON_ATLAS = {
11341134
Bleed = "RaidFrame-Icon-DebuffBleed",
11351135
}
11361136
local warnedTintBind = false
1137+
local warnedSlotStyle = false
11371138

11381139
-- Slot plan from settings. Returns nil when the native classification route is
11391140
-- required but missing (API drift) and no degrade applies.
@@ -1631,6 +1632,40 @@ local function StyleGameEdgeSlot(btn, frame, db, edge)
16311632
ApplySlotPulse(btn.dfDispelEdgeHolder and btn.dfDispelEdgeHolder[edge], db.dispelAnimate)
16321633
end
16331634

1635+
-- All the styling for ONE slot button. Split out of StyleDispelSlots so the whole
1636+
-- per-button pass can be pcall'd as a unit -- see the caller for why.
1637+
local function StyleOneSlot(btn, frame, db, info)
1638+
-- IN-PLACE PALETTE RE-BIND (68914): Blizzard securecopy's the colour map at
1639+
-- bind time, so a Colours-page edit needs the carrier RE-BOUND. That used to
1640+
-- force a full container rebuild (the palette generation rode the plan
1641+
-- signature) — a visible teardown/rebuild flicker on every colour tweak.
1642+
-- AddDispelTypeTexture accepts a re-bind from this tainted pass now (the
1643+
-- access-constrained rule is gone; /al accessbind + the 68914 validator,
1644+
-- which only rejects EXPLICITLY forbidden / protected / non-descendant
1645+
-- objects — our carrier is a descendant that merely INHERITS aspects), so
1646+
-- re-bind the carrier we already have and skip the rebuild entirely.
1647+
-- Icon slots bind nothing, so they never go stale. Re-binds the WHOLE
1648+
-- carrier list for this button in one clear-then-append pass.
1649+
if btn._dfDispelCarriers and btn._dfDispelCurveGen ~= DF.dispelCurveGen then
1650+
BindDispelCarriers(btn, btn._dfDispelCarriers, db, info.key)
1651+
end
1652+
if info.iconType then
1653+
StyleGameTypeIconSlot(btn, frame, db, info.iconType)
1654+
else
1655+
-- ONE button, every role it owns (see dispelSlotPlan's `roles`).
1656+
-- StyleGameMainSlot runs UNCONDITIONALLY: besides dressing the gradient
1657+
-- carrier it owns the shared geometry pass (ApplyOverlayLayout), hides
1658+
-- the legacy regions, and applies the darken/pulse — all of which the
1659+
-- pre-consolidation main slot did in every style, EDGE included.
1660+
StyleGameMainSlot(btn, frame, db)
1661+
local r = info.roles
1662+
if r and r.edges then
1663+
for _, edge in ipairs(r.edges) do StyleGameEdgeSlot(btn, frame, db, edge) end
1664+
end
1665+
if r and r.border then StyleGameBorderSlot(btn, frame, db) end
1666+
end
1667+
end
1668+
16341669
-- Style every live slot button per the plan. Returns false while no buttons exist
16351670
-- (combat-deferred build / fake backend) so the caller doesn't latch the version.
16361671
local function StyleDispelSlots(frame, db, h, slots)
@@ -1641,44 +1676,44 @@ local function StyleDispelSlots(frame, db, h, slots)
16411676
local info = slots[i]
16421677
local btn = buttons[info.key]
16431678
if btn then
1679+
-- `styled` means "a button existed and we ran the pass", NOT "the pass
1680+
-- succeeded". It has to stay true even when the pass throws, or the
1681+
-- caller never latches the version/generation and re-enters this same
1682+
-- failing pass on EVERY drive -- i.e. per UNIT_AURA, per frame, forever
1683+
-- (bug #1011: 68 identical errors from one key). A real change bumps
1684+
-- ver/gen and retries; a deterministic failure now costs one error, not
1685+
-- a permanent loop.
16441686
styled = true
1645-
-- IN-PLACE PALETTE RE-BIND (68914): Blizzard securecopy's the colour map at
1646-
-- bind time, so a Colours-page edit needs the carrier RE-BOUND. That used to
1647-
-- force a full container rebuild (the palette generation rode the plan
1648-
-- signature) — a visible teardown/rebuild flicker on every colour tweak.
1649-
-- AddDispelTypeTexture accepts a re-bind from this tainted pass now (the
1650-
-- access-constrained rule is gone; /al accessbind + the 68914 validator,
1651-
-- which only rejects EXPLICITLY forbidden / protected / non-descendant
1652-
-- objects — our carrier is a descendant that merely INHERITS aspects), so
1653-
-- re-bind the carrier we already have and skip the rebuild entirely.
1654-
-- Icon slots bind nothing, so they never go stale. Re-binds the WHOLE
1655-
-- carrier list for this button in one clear-then-append pass.
1656-
if btn._dfDispelCarriers and btn._dfDispelCurveGen ~= DF.dispelCurveGen then
1657-
BindDispelCarriers(btn, btn._dfDispelCarriers, db, info.key)
1658-
end
1659-
if info.iconType then
1660-
StyleGameTypeIconSlot(btn, frame, db, info.iconType)
1661-
else
1662-
-- ONE button, every role it owns (see dispelSlotPlan's `roles`).
1663-
-- StyleGameMainSlot runs UNCONDITIONALLY: besides dressing the gradient
1664-
-- carrier it owns the shared geometry pass (ApplyOverlayLayout), hides
1665-
-- the legacy regions, and applies the darken/pulse — all of which the
1666-
-- pre-consolidation main slot did in every style, EDGE included.
1667-
StyleGameMainSlot(btn, frame, db)
1668-
local r = info.roles
1669-
if r and r.edges then
1670-
for _, edge in ipairs(r.edges) do StyleGameEdgeSlot(btn, frame, db, edge) end
1687+
-- pcall'd per BUTTON so one bad slot can't skip the others, and -- more
1688+
-- importantly -- can't propagate out through DriveDispelOverlayFactory
1689+
-- into FullFrameRefresh, which would abandon every element that runs
1690+
-- after the dispel overlay (highlights, status icons, resource bar,
1691+
-- absorbs, heal prediction). Allocation is fine here: this path is gated
1692+
-- on a version/generation change, so it runs on rebuilds, not per aura.
1693+
local ok, err = pcall(StyleOneSlot, btn, frame, db, info)
1694+
if not ok then
1695+
btn._dfDispelStyleErr = tostring(err)
1696+
if not warnedSlotStyle then
1697+
warnedSlotStyle = true
1698+
if DF.DebugWarn then
1699+
DF:DebugWarn("DISPEL", "slot style %s failed: %s",
1700+
tostring(info.key), tostring(err))
1701+
end
16711702
end
1672-
if r and r.border then StyleGameBorderSlot(btn, frame, db) end
1703+
else
1704+
btn._dfDispelStyleErr = nil
16731705
end
16741706
end
16751707
end
16761708
-- Seed any health-tracking gradient bars now (both colour modes): the health
16771709
-- hook only fires on health CHANGES, and the layout pass just neutralized the
16781710
-- fill to full — without a seed a tracking bar renders full until the first
16791711
-- health tick. Early-outs when nothing tracks.
1712+
-- pcall'd for the same reason as the per-button pass: this reaches into the
1713+
-- slot widgets' StatusBars, so it shares their exposure and must not be able
1714+
-- to abort the caller.
16801715
if styled and DF.UpdateDispelGradientHealth then
1681-
DF:UpdateDispelGradientHealth(frame)
1716+
pcall(DF.UpdateDispelGradientHealth, DF, frame)
16821717
end
16831718
return styled
16841719
end

DandersFrames/Frames/Headers.lua

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3753,8 +3753,14 @@ function DF:FullFrameRefresh(frame)
37533753
if DF.UpdateMissingBuffIcon then DF:UpdateMissingBuffIcon(frame) end
37543754

37553755
-- Overlays
3756-
if DF.UpdateDispelOverlay then DF:UpdateDispelOverlay(frame) end
3757-
3756+
-- pcall'd: the dispel overlay is the only element here that reaches into the
3757+
-- native aura container's slot buttons, so it is the one most exposed to a
3758+
-- forbidden-object / taint throw. Unguarded, such a throw aborts the REST of
3759+
-- this function -- highlights, status icons, resource bar, absorbs and heal
3760+
-- prediction all silently stop updating on that frame (bug #1011). One broken
3761+
-- element must not take the other five down with it.
3762+
if DF.UpdateDispelOverlay then pcall(DF.UpdateDispelOverlay, DF, frame) end
3763+
37583764
-- Highlights (selection, aggro, etc.)
37593765
if DF.UpdateHighlights then DF:UpdateHighlights(frame) end
37603766

0 commit comments

Comments
 (0)