Je répète

If it was simple, it would be boring.
If it wasn't elegant, it would be wrong.
That said, we must adapt to the terrain, hence all this:

OK, so the solution to the below is 3 and 4. 3 for inter-document comms, 4 for doc->JID comms. This means modifying the client-side routing to allow multiple threads per JID. No problemo, we move the JID identity check for controller JIDs from right at the top to right at the bottom of the routing decision tree. Neither is happy, both are ugly, I will replace them if I find something better.

Issue number two is kind've a funny one. Before we used to do document loading via XMPP, which was a bad idea, to put it mildly. Now, we do it via HTTP, and a namespaced element in the document tells the canvas to send a message to a JID with the URL and the generated thread ID.

This means we don't have to do queuing packets for unloaded documents, which is a bit of a relief (although I only figured this out after I rewrote the routing code to allow multiple 'routing tables' to be used in the same router, which is nice logic separation but needn't have been done.)

However, now the SVG "onload" event is triggered before the UpdateManager is started, meaning that we could be sending stanzas before we've let the server know our thread ID, which is obviously not cool. The solution to this is to move the XMPP networking code into documentLoadingCompleted(), which is called after the document is loaded and blocks the thread that triggers the ECMAScript onload/script & interpreter initialization code, which is what we want.

This means that although we won't be sending stanzas with a thread ID we haven't declared, we can now receive directives and stanzas for the document before we have the thread we should be executing the events and running the directives in.

What this means is that we need to keep the packets for this canvas to one side while we add the packet router as an UpdateManagerListener to the canvas, wait for the event to fire, walk our way back the reference tree (or keep an internal Map) and then start processing packets.

Which is basically what I was doing back when I sent and received documents over XMPP, because it's semantically equivalent to queuing packets for unloaded documents. Funny how things work out.