Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find a way for service workers to get their current state #1077

Closed
n8schloss opened this issue Feb 21, 2017 · 29 comments · Fixed by #1426
Closed

Find a way for service workers to get their current state #1077

n8schloss opened this issue Feb 21, 2017 · 29 comments · Fixed by #1426
Assignees
Milestone

Comments

@n8schloss
Copy link

A service worker instance currently has no way to get it's current lifecycle state. There's a bit of a hack one can do where you keep track of the current event as a global variable but that's error prone and doesn't capture the waiting periods correctly.

Imo, the best way to solve this would be to just allow a service worker to get it's ServiceWorker object somehow. Maybe via self.worker or self.self or something like that.

@publicocean0
Copy link

It is similar to my issue but I asked to use the same service worker as listener . I want notify my server when I can push a event and when a event can t be notified because no service worker is avaible to receive a notification

@jakearchibald jakearchibald added this to the Version 2 milestone Mar 30, 2017
@jakearchibald
Copy link
Contributor

self.<something> to reference the current worker sounds like a good idea to me. Throwing self.thisServiceWorker into the bikeshedding ring, although it's a bit long.

@jakearchibald
Copy link
Contributor

F2F: self.thisServiceWorker sounds good, unless anyone can come up with better

@slightlyoff
Copy link
Contributor

self.registration.self?

@publicocean0
Copy link

publicocean0 commented Apr 4, 2017

it is past a lot of time ago when i wrote about this problem .... if i remember correctly in my case i was searching a listener inside the service for all the states of service worker. My idea it was a bit advanced , a bit more for actual html5 :). Service worker is designed with many problems :

  • impossible to trace when browser starts up/is closing. Service worker life cicle might simulate to start when the browser is starting and closing as a real service (a kind of daemon in linux) even if it is running really just when a event is executed ;
  • impossible to wake up connections (web socket for example) or being triggered by on message event (the main scope of a service in computer science is to execute background code without user interation and to intercept async events from external universe. No ones of them is present in service worker)
  • service worker might simulate completely a service : a kind of process working independently by user interation ... instead it is pratically bind to the user interation.
    Service worker might be redesigned extending all the missing parts. Too much simple model when it might more complex and too much complex for solving simple things.

@wanderview
Copy link
Member

If we stick this on ServiceWorkerRegistration we then have an attribute that is always unpopulated in other contexts.

I would also note we have another issue somewhere about referencing the current global as a Client, which is similar to this. Might be nice to make the naming be similar for the two concepts.

Maybe something like self.asServiceWorker and self.asClient()?

interface WindowOrWorker
{
  // returns a new snapshot
  Client asClient();
};

interface ServiceWorkerGlobalScope
{
  [SameObject]
  readonly attribute ServiceWorker asServiceWorker;
};

@n8schloss
Copy link
Author

I totally agree that sticking this on the registration could get messy. self.asServiceWorker makes a lot of sense to me, so +1 for that :)

@delapuente
Copy link

Since this is a source of confusion, I would be extra explicit when naming this member. I like @wanderview solution but what about .runningServiceWorker and .runningClient. Using the asXXX formula seems to mean like a sort of casting on the ServiceWorkerGlobalScope.

@n8schloss
Copy link
Author

@delapuente you can have more than one SW instance running at a time, in this case we want the current context, not a currently running SW. @wanderview's suggestion makes more sense imo.

@delapuente
Copy link

Can you? I thought you could only have one executing service worker at a time. With executing I mean running JavaScript code. I thought you could have several service workers in different states at the same time (installing, activating, active...) but only one running at a time. I mean without real parallelism.

If this is not the case, and since I continue thinking asXXX evoke a casting action, I believe the metaphor is well enough.

@n8schloss
Copy link
Author

Alright, how about we just go with self.thisServiceWorker then as was suggested at the F2F? That seems to be the most clear.

@wanderview
Copy link
Member

With executing I mean running JavaScript code. I thought you could have several service workers in different states at the same time (installing, activating, active...) but only one running at a time. I mean without real parallelism.

This is not accurate. You can have multiple service workers in different states and executing in separate threads simultaneously. Consider an installing worker handling its install event in parallel with the active worker handling fetch events from current page.

@delapuente
Copy link

delapuente commented Apr 21, 2017

Thank you for the clarification, @wanderview

In that case, the spec says:

A ServiceWorkerGlobalScope object represents the global execution context of a service worker. A ServiceWorkerGlobalScope object has an associated service worker (a service worker).

So, I'm happy with self.serviceWorker and self.client or self.thisServiceWorker and self.thisClient (sounds weird) or, following spec terminology, self.associatedServiceWorker (sounds even weirder) and self.associatedClient.

@wanderview
Copy link
Member

Note, if we do this we will need to also fix #1162. Currently a script cannot access its state at script evaluation time, but with the changes discussed here it might be possible. In that case we will need to expose the initial parsed state that occurs before the worker enters the installing state.

@jungkees
Copy link
Collaborator

Note, if we do this we will need to also fix #1162.

Good catch. I think we can set the initial value of the state attribute to "parsed".

For the naming, I give my five cents to self.serviceWorker and self.client. this.serviceWorker sounds better than this.thisServiceWorker to me.

One more thing is what we'd expect postMessage() to self will do? Throwing an InvalidStateError? If the use case posed in the OP is about just exposing the state of itself, adding self.state (and probably self.onstatechange too) would be an option here?

@wanderview
Copy link
Member

For the naming, I give my five cents to self.serviceWorker and self.client. this.serviceWorker sounds better than this.thisServiceWorker to me.

I see your reasoning here, but do you think it would be confusing if both of these were true:

'ServiceWorker' in self
'serviceWorker' in self

One is the webidl interface and the other is an instance of that interface. Single character differences in global names seems a bit dangerous to me.

@jungkees
Copy link
Collaborator

I think we already have such a case in ServiceWorkerGlobalScope:

'Clients' in self
'clients' in self

But I understand your point, and it would prevent devs from using serviceWorker as a variable name on global scope.

@wanderview
Copy link
Member

Yea, we also already have self.Performance and self.performance. I guess there is plenty of precedent.

@NekR
Copy link

NekR commented Jun 15, 2017

@wanderview almost every single one which is exposed on global object: window/Window (not in worker ofc), indexedDB/IndexedDB, etc. Not really a concern, first thing JS devs are taught is variables naming :-)

@jakearchibald
Copy link
Contributor

I'm less bothered about self.ServiceWorker vs self.serviceWorker, but more bothered about serviceWorker vs navigator.serviceWorker.

@jakearchibald
Copy link
Contributor

We might want to think about this in relation to #1036 – what would be the difference between a ServiceWorker, and a client representing a service worker?

If this turn out to be the same thing (or are merged somehow), clients.self() could be the answer.

@jakearchibald
Copy link
Contributor

Or clients.selfId, which could be passed to clients.get().

@jakearchibald
Copy link
Contributor

Previous discussion of exposing client IDs to the client #643

@jakearchibald
Copy link
Contributor

Spec change #1426

Tests web-platform-tests/wpt#17285

I went with self.serviceWorker. If anyone wants to do some last-minute bikeshedding, now's the time 😀

@jakearchibald
Copy link
Contributor

jakearchibald commented Jun 12, 2019

@aliams @asutherland @youennf @cdumez I believe there was agreement for this feature at the F2F, but I'd like to be sure.

TL;DR: New feature: In a service worker, self.serviceWorker gives you a service worker instance for this service worker.

So, if you wanted to know what state this service worker was in, you'd read self.serviceWorker.state.

Are you happy for me to land this change?

@jakearchibald
Copy link
Contributor

@asutherland @youennf @cdumez nudge. Pretty sure we agreed on this at the f2f, but I don't want to land this without double checking.

@asutherland
Copy link

LGTM, thank you for doing this!

@youennf
Copy link

youennf commented Jun 21, 2019

LGTM too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants