I just had the weirdest problems when fixing Extension:Variables where one variables store should exist per Parser object.
I did this by using a new property from the outside (which is not bad practice for this kind of thing) $parser->mExtVariables = new ExtVariables()
Certain hooks will affect all instances of that store, for example ParserClearState will reset it entirely, practically something like $parser->mExtVariables->mVariables = array()
I just wasn't aware of the fact that there is a cloned Parser instance for the message cache which might call ParserClearState before the original Parser objecdt where the clone comes from.
This means all Changes I do in ParserClearState or any other hook for the cloned parser in $parser->mExtVariables->mVariables (where mExtVariables is an object as you can see) will affect the original Parser where the clone came from as well, since the clone is not a deep clone where all internal objects will be cloned as well.
So by resetting the variables store for the cloned object, I unwillingly do the same for the original.
Conclusion: The clone should be a new instance of the parser with same parser options or a deep clone perhaps?
Or does the clone actually rely on keeping track on object member variables changed in the original parser?
The cloning is done in MessageCache::getParser() since 1.18