13.4. SharedWorker

The SharedWorker faces towards the PDR. It comes into being when a client (let’s say a page) calls the 'new' constructor on 'SharedWorker'. The first page actually causes a new process, whereas the next page merely connects to the now existing SharedWorker. Hence 'shared'!

It is important to understand that when this new process is created, the PDR does not start running immediately. The client initiates the PDR by calling the runPDR function of the SharedWorkerChannel.

When a page actually creates a SharedWorker from its script, an event is raised at the SharedWorkerGlobalScope in the SharedWorker: the 'connect event'. The same happens when the next page connects to the now existing SharedWorker. The script 'perspectives-sharedworker.js' handles this event by creating a new ChannelID and sending it through the port that represents its end of the Channel between PDR and this client. The SharedWorkerChannel instance (facing towards the client) stores it internally.

The SharedWorker faces a problem similar to the SharedWorkerChannel: it communicates directly (through function calling) with an in-process program and at the same time communicates through the Channel Messaging API with an out-of-process program.

The PDR is itself a highly asynchronously operating program. The SharedWorker handles this asynchronous character by providing callback functions to the Perspectives.API. It constructs these functions itself and what they do is this:

  • it selects the right MessagePort to send a PDR reply to, based on the ChannelID;

  • it returns the PDR result through that port, identifiying it with its Correlation Identifier.

When received by the SharedWorker channel instance, the Correlation Identifier is used to retrieve the original callback function provided by the client. It finally is applied to the result created by the PDR.

13.4.1. Connection to the PDR: the InternalChannel

The PDR operates on a stream of requests that flow in from the various clients. All requests are coming in on the same stream. This stream is created when the PDR calls the function createRequestEmitterImpl, provided by the package perspectives-proxy.js. The PDR does this when starting up.

Now this function creates an instance of the class InternalChannel. It provides its constructor with three functions supplied by the PDR. The first two are stream data constructor functions. The third is an emit function that should be called with a stream data element. Whenever the InternalChannel calls emit, the stream in the PDR emits another element to be processed by the module Perspectives.API.

13.4.2. A dance in four steps

Summing up, this is how the entire process is booted on the SharedWorker/PDR side:

  • the client starts the SharedWorker. Through the SharedWorkers onConnect event, it establishes connection through the Messaging Channel API with the client. The SharedWorker, however has not yet started the PDR and thus cannot relay requests from clients yet;

  • the client then instructs the SharedWorker to start the PDR;

  • the PDR calls createRequestEmitterImpl as part of its startup routine, which constructs the InternalChannel instance and fulfills the InternalChannelPromise.

  • only then is the InternalChannel ready to relay requests from the clients to the PDR.