UI code load order
From WoWWiki
Contents |
This document covers the order in which addons and files are loaded, in addition to the order in which loading activities occur when XML files are parsed:
Files within an AddOn
Within an AddOn (and within FrameXML), loading is performed linearly as defined by the .toc file for that AddOn. Thus the first file in the toc is parsed and executed, then the second, then the third, etc. If the file being processed is an XML file then any <Script file="X"/> elements it contains are executed as they are reached, parsing and executing the referenced file before continuing to the element after the script element. So, if we have this toc structure:
File1.lua File2.lua File3.xml File4.xml File5.lua
Also, File3.xml contains:
- <Script file="FileA.lua"/> and
- <Script file="FileB.lua"/>,
And File4.xml contains:
- <Script file="FileA.lua"/> and
- <Script file="FileC.lua"/>
Then, the load/execute order will be:
- File1.lua
- File2.lua
- File3.xml
- start
- FileA.lua
- FileB.lua
- rest of File3.xml
- File4.xml
- start
- FileA.lua
- FileC.lua
- rest of File4.xml
- File5.lua
As you can see the load order is entirely predictable, you can also see that in this scenario FileA.lua gets parsed and executed twice. Be aware of this if you include <Script> blocks in your XML.
Lua File Processing
A Lua file is simply parsed and then executed by the Lua engine. Any in-line code will be executed immediately (in fact this is how function definitions happen, they're simply being executed).
XML File Processing
XML Files are processed sequentially, element by element:
Script Elements
As described above, <Script.../> elements are processed immediately when they are encountered. These can only appear at the start of the file, and are traditionally used to run some setup code, or include a specific Lua file (Be cautious in this case because it can mean a lua file gets loaded multiple times).
Virtual Elements
Virtual frame elements are parsed and then stored for later use, they are not executed on their own, and do not create any Lua objects. They simply establish a template for later use. Virtual frame definitions are discarded at the end of an AddOn loading batch, this is explained in more detail below, but essentially game login is one batch, and each LoadOnDemand call (and any nested loads it performs) once the game is running is an indepdendent batch.
Normal and Inherited Elements
Each element is processed recursively using the following steps:
- Create the appropriate C++ object and its Lua reference (Bear in mind you cannot anchor to a frame which has not yet been created)
- If this frame inherits from a virtual template, then apply these rules to the template before continuing.
- If this frame has any children, apply these rules to each child in the order they appear in the XML file.
- Apply any script handlers to the frame
- Invoke the frame's OnLoad handler.
Consider the following structure:
<Frame name="V1" virtual="true">
<Frames>
<Frame name="$parent_V1_C1"/>
<Frame name="$parent_V1_C2"/>
</Frames>
</Frame>
<Frame name="V2" inherits="V1" virtual="true">
<Frames>
<Frame name="$parent_V2_C1"/>
<Frame name="$parent_V2_C2" inherits="V1"/>
</Frames>
</Frame>
<Frame name="F" inherits="V2">
<Frames>
<Frame name="$parent_C1" inherits="V1"/>
<Frame name="$parent_C2"/>
</Frames>
</Frame>
Then the order of create/load actions will be:
- Create F
- Create F_V1_C1
- OnLoad F_V1_C1
- Create F_V1_C2
- OnLoad F_V1_C2
- Create F_V2_C1
- OnLoad F_V2_C1
- Create F_V2_C2
- Create F_V2_C2_V1_C1
- OnLoad F_V2_C2_V1_C1
- Create F_V2_C2_V1_C2
- OnLoad F_V2_C2_V1_C2
- OnLoad F_V2_C2
- Create F_C1
- Create F_C1_V1_C1
- OnLoad F_C1_V1_C1
- Create F_C1_V1_C2
- OnLoad F_C1_V1_C2
- OnLoad F_C1
- Create F_C2
- OnLoad F_C2
- OnLoad F
AddOn Load Order
Putting aside Load-on-demand AddOns for a moment, FrameXML is loaded first (It's not an AddOn per se, but it's structured like one and loads in the same way), followed by the remaining AddOns, which are processed in the order they are returned from the operating system (For normal Windows installs this is order of directory entries, that is first addon to be placed in empty Addons derectory is loaded first, however when entries are removed from directory there will usually remain empty space that will be used by the next new directory entry. This order is known as unsorted order), with the following basic rules:
- If the AddOn is already loaded (or is in the process of being loaded), then don't load it again.
- If the AddOn has any un-loaded dependencies, process each of those in the order they appear in the .toc
- If the AddOn has any un-loaded, but enabled, optional dependencies, process each of those in the order they appear in the .toc.
- Load the files in the AddOn in accordance with the .toc as described earlier.
- If there are any other unloaded but enabled addons marked to LoadWith this AddOn, then process those (order unknown, I'd imagine it's in their natural filesystem order).
Following this loads all AddOns in a logical order, such that an AddOn's dependencies load before it.
Load-On-Demand AddOns
Load-On-Demand AddOns are a little more complicated since they're initiated on demand, and because the LoadAddOn function blocks until loading of the addon (and any of its children) is complete. When LoadAddOn is invoked for an addon, the steps for normal AddOn loading are followed as described above, but LoadAddOn doesn't return until the process is complete.
