Thread Tools Display Modes
Prev Previous Post   Next Post Next
08-13-17, 05:23 PM   #1
Thex
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Aug 2017
Posts: 5
Making proxy table for _G

Hi,

I'm currently trying to develop a small tool to help with addons creation. The point would be that said tool would "detect" all functions and variables declared in the global scope, and print a warning saying like "don't use global scope" or something, just to help catching mistakes.

So i set up a proxy table for the _G table. I created a copy of it, then _G = {}, and gave it __newindex and __index metamethods to redirect all transit. At the end of the addon loading, i'm resetting _G to its original form, to avoid other addons using this.
Issue i'm having is that apparently, changing the value of _G directly (either by doing "_G = {}" or even "_G = _G") is not allowed, and makes you, oddly enough, unable to use your spellbar hotkeys (prompting a popup "[Your addon] has been blocked from an action only available to the Blizzard UI".

So i'm kind of sad to see that; and i was wondering if you guys had any idea how to bypass that issue (or how to make it more "secure" i guess, in the eyes of the API), please?

Edit: One way i could think of would be to create a local _G = GetFakeG() at the beginning of all of my scripts, where GetFakeG() would just give me an empty table with the indirection metatable, created in my cerberus.lua file; but that would mean having to get that local _G in every script, and that's something i would like to avoid. I'd like this tool to be "install, initialize and forget about it".


(Here is my code, just in case you're wondering about anything: )
Lua Code:
  1. local cerberusTextColour = "ffc42727";
  2. local cerberusPrefix = "|c" .. cerberusTextColour .. "Cerberus: |r"
  3. function Cerberus_Print(message)
  4.     print(cerberusPrefix .. message);
  5. end
  6.  
  7.  
  8. g_cerberus = g_cerberus or {};
  9. local currentAddonName = nil;
  10. local function GetCurrentAddonName()
  11.     return currentAddonName;
  12. end
  13. g_cerberus._G = function()
  14.     return g_cerberus[GetCurrentAddonName()];   -- Using getter function to avoid conflicts between mods
  15. end
  16.  
  17.  
  18. g_cerberus.RegisterAddon = function(addonName)
  19.  
  20.     if g_cerberus._G() ~= nil then
  21.         Cerberus_Print("Attempting to register addon which has already been registered (" .. addonName .. "). Try with a different addon name, or a more specific one.");
  22.         return;
  23.     end
  24.  
  25.     currentAddonName = addonName;
  26.     g_cerberus[addonName] = {};
  27.     g_cerberus[addonName]._GCopy = _G;
  28.     _G = {};
  29.  
  30.     setmetatable(_G,
  31.     {
  32.         __newindex = function(_, key, value)
  33.             Cerberus_Print("Attempting to store " .. (key or "nil") .. " in the global scope with value \"" .. tostring(value) .. "\". Make sure that's what you actually want.");
  34.             g_cerberus._G()._GCopy[key] = value;
  35.         end,
  36.  
  37.         __index = function(_, key)
  38.             return g_cerberus._G()._GCopy[key];
  39.         end
  40.     });
  41. end
  42.  
  43. ----- In another file to put at the end of the toc list
  44. if g_cerberus ~= nil and g_cerberus._G() ~= nil and g_cerberus._G()._GCopy ~= nil then
  45.     _G = g_cerberus._G()._GCopy;
  46. end

Last edited by Thex : 08-13-17 at 07:17 PM.
  Reply With Quote
 

WoWInterface » Developer Discussions » Lua/XML Help » Making proxy table for _G


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off