[Patch] "tried to call the protected function#" taint error
brittyazel opened this issue ยท 8 comments
Hi Tuller,
My name is Soyier, and I'm the author of Neuron, an action bar addon very similar to your own. I noticed you were getting a lot of the same issue reports as I with regard to taint error "AddonX tried to call the protection function#:Hide()", or something in that vein. I think I have a decent fix for it, though I still need to test it thoroughly. I took your Blizzard Bar disabling code and modified it:
The code below is mostly yours, with a bit of modernization (I got rid of the _G calls), and most of the fix comes from these lines, which make use of Ace3-Hook:
Neuron:RawHook('ActionButton_Update', function() end, true)
Neuron:RawHook('MultiActionBar_Update', function() end, true)
Also, I had to explicitly disableFrame(MainMenuBar), or you get errors about :SetPoint or some such.
Hopefully this helps a bit, and maybe you can refine the code even further for both of our benefit :-)
Cheers buddy! Happy Holidays
function Neuron:HideBlizzard()
if (InCombatLockdown()) then
return
end
---the idea for this code is inspired from Dominos. Thanks Tuller!
local hiddenFrame = CreateFrame('Frame', nil, UIParent, 'SecureFrameTemplate');
hiddenFrame:Hide()
local function disableFrame(frame, unregisterEvents)
if not frame then
Neuron:Print('Unknown Frame', frame:GetName())
return
end
frame:SetParent(hiddenFrame)
frame.ignoreFramePositionManager = true
if unregisterEvents then
frame:UnregisterAllEvents()
end
end
local function disableFrameSlidingAnimation(frame)
local animation = (frame.slideOut:GetAnimations())
animation:SetOffset(0, 0)
end
disableFrame(MainMenuBar)
-- disable override bar transition animations
disableFrameSlidingAnimation(MainMenuBar)
disableFrameSlidingAnimation(OverrideActionBar)
disableFrame(MultiBarBottomLeft)
disableFrame(MultiBarBottomRight)
disableFrame(MultiBarLeft)
disableFrame(MultiBarRight)
disableFrame(MainMenuBarArtFrame)
disableFrame(StanceBarFrame)
disableFrame(PossessBarFrame)
disableFrame(PetActionBarFrame)
disableFrame(MultiCastActionBarFrame)
disableFrame(MicroButtonAndBagsBar)
disableFrame(MainMenuBarPerformanceBar)
StatusTrackingBarManager:UnregisterAllEvents()
StatusTrackingBarManager:Hide()
if (not Neuron:IsHooked('ActionButton_Update')) then
Neuron:RawHook('ActionButton_Update', function() end, true)
end
if (not Neuron:IsHooked('MultiActionBar_Update')) then
Neuron:RawHook('MultiActionBar_Update', function() end, true)
end
end
Minor edit, the Raw hook lines will throw an error that they're already hooked when taking a portal or entering an Arena:
if (not Neuron:IsHooked('ActionButton_Update')) then
Neuron:RawHook('ActionButton_Update', function() end, true)
end
if (not Neuron:IsHooked('MultiActionBar_Update')) then
Neuron:RawHook('MultiActionBar_Update', function() end, true)
end
Adding a check ahead of time solves this problem :-)
Hrm, well at the very least you know it's those two functions causing the issues. A messy, albeit guaranteed to work, method would be to overwrite those two functions with modified variants that just avoid the protected calls to :Hide and such. That way you can retain much of their functionality
RawHook, if I'm reading the API docs correctly, is roughly equivalent to just doing this:
ActionButton_Update = function(...) end
I don't exactly think that'll work in my case, as I actually need Blizzard to update the action buttons for me. I'll think more about this when I get home.
MultiActionBar_Update is relatively safe to override, so I've put that in place in the latest version. Dominos relies on ActionButton_Update, and I've yet to really see taint from that.
By the way, if you ever get bored, take a look at the code for Razer Gaming Keypad. I sort of rewrote the custom action button implementation used by Ion.
Haha nice, I'll take a look at it.
Yeah in my code ActionButton_Update was the main culprit, I've since refined the disablement a bit, easing up on the CPU load as well. I now have:
ActionBarController:UnregisterAllEvents()
StatusTrackingBarManager:UnregisterAllEvents()
if (not Neuron:IsHooked('ActionButton_OnEvent')) then
Neuron:RawHook('ActionButton_OnEvent', function(self) end, true)
end
I noticed almost all of the calls triggering the taint stemmed from the OnEvent function for ActionButton, and weirdly enough calling :UnregisterAllEvents() on each button individually didn't stop this function from being called. So I have just resorted to intercepting it and nullifying it. Somewhat messy still :-/
So, it looks like the real cause of the tainting issues I was having was me setting noGrid = 1
on the multi action buttons as a shortcut to hide empty ones. I've dropped that and implemented a new workaround for those. With it, I'm able to drop the MultiActionBar_Update
replacement and have things work in combat as expected.
Yesterday, I was getting "Action blocked" when I tried to bonus roll on world bosses, this is with 8.1.3, I don't remember what version I was on before, since I hadn't updated addons in a while.
I tried reloading UI / relogging, both didn't help. I had to disable Dominos Roll altogether to be able to bonus roll. So there might still be some taint somewhere there there.