Skin runs a variety of hooks. These hooks are provided with an instance of Skin to make decisions about the rendering. However this also provides access to OutputPage and various methods that have side effects - for example OutputPage::addModules, OutputPage::addModuleStyles.
This led to the regressions T259858 and T259872.
Hooks should be used for their sole purpose - for example SiteNoticeBefore should only be used to modify the site notice. This makes the code easier to reason with.
I see two possible solutions here:
- OutputPage::freeze and OutputPage::unfreeze methods are executed before and after the skin rendering methods - the OutputPage will throw warnings in certain methods with side effects if they are invoked during this period
- Skin makes use of an OutputPageReadOnly class that creates a read only version of OutputPage by extending the class and disabling certain methods as NOOPs.
- Other idea (?)