FunctionNode: fix missing definitions in FunctionScope when emitting methods as JavaScript (references #249)

Uses the existing deferredBodyParsingLock that is already used by parseFunctionBody() and discardFunctionBody() to ensure thread safety when reconnecting the scope to the ScopedBlockNode, and also when removing stale definitions when the function body needs to be re-parsed and will create new definitions to replace them.

I ended up moving the changes from 35eed62f13519c659e6346d26cca3f44afe3170f from FunctionScope to FunctionNode. FunctionNode is the only place where the scope is reconnected, and it's the only place where definitions are already added to and removed from the FunctionScope. So it's better to remove stale definitions in the same place.

This issue is very difficult to reproduce (although building MXRoyaleBaseJS usually does it eventually... sometimes dozens or hundreds of compiles!). My best guess is that reconnecting the scope node while the body is currently being parsed, or while the definitions are currently being added to the scope, is where it leaves the scope without any definitions at all. I see that in analyze(), PostProcessStep.POPULATE_SCOPE creates a new FunctionScope, and PostProcessStep.RECONNECT_DEFINITIONS connects it to the ScopedBlockNode. Perhaps parseFunctionBody() was occasionally populating an old FunctionScope instead of the newly created one, and the lock is now forcing it to wait for the new scope to be connected before it starts populating.
3 files changed