FYI: as of now, WebKit Workers 'close()' behavior is following the results of this thread and is compatible with FF (except we don't implement close event, as mentioned here).<br><br><div>Thanks for clarifications!</div>
<div><br></div><div>Dmitry</div><div><br><div class="gmail_quote">On Fri, Apr 16, 2010 at 6:06 PM, Ian Hickson <span dir="ltr"><<a href="mailto:ian@hixie.ch">ian@hixie.ch</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
On Tue, 30 Mar 2010, Jonas Sicking wrote:<br>
> ><br>
> > My understanding was that relying on exceptions for non-exceptional<br>
> > cases is bad API design. Why would it be ok here?<br>
><br>
> I think fallback is to be considered an exceptional case. Especially as<br>
> time goes on and more browsers implement support for the new type.<br>
><br>
> > The question is, what are the actual concrete cases where people will<br>
> > be sending DOM nodes? Without concrete cases, it's easy to construct<br>
> > artificial cases that prove this to be better one way or the other.<br>
><br>
> Say sending a DOM that the user has edited (using contentEditable) which<br>
> the worker will convert into a ODF document and send to the server.<br>
><br>
> >> Personally, I think throwing an exception fits in with the spec's use<br>
> >> of them elsewhere (i.e., cross-document and web workers.)<br>
> ><br>
> > Where do we use exceptions for extension points in a similar way?<br>
><br>
> For circular object graphs in the very same algorithms.<br>
<br>
On Thu, 1 Apr 2010, Simon Pieters wrote:<br>
><br>
> It does matter because if you send null, the worker has to respond that<br>
> it got null so the script can do what it wants on the main thread, which<br>
> makes the operation async and means the worker script needs logic for<br>
> the non-supported case. It's more convenient to catch an exception and<br>
> do what you want directly, and have the worker script only care about<br>
> the supported case.<br>
><br>
> This is actually the exact same problem as what we have now, moving from<br>
> string based to structured clone. In order to test structured clone<br>
> support, you have to send a message back and forth. I think it would<br>
> have been better if non-strings threw an exception from the start, but<br>
> it's too late to change it now.<br>
><br>
> A use case I had with structured clone is posting three ImageData<br>
> objects where the worker compares the pixels of two of them and puts the<br>
> difference on the third and posts that one back. I do it in a worker<br>
> because it's a heavy operation for big images and I needed to keep the<br>
> timing correct for events in the main thread. If workers isn't<br>
> supported, I did the operation later when the timing of events didn't<br>
> matter. I didn't make it detect support for workers but lack of<br>
> structured clone because it seemed too annoying to implement.<br>
<br>
Fair enough. I've changed the cloning mechanism to throw an exception<br>
instead of nulling host objects.<br>
<br>
<br>
On Tue, 30 Mar 2010, Dmitry Titov wrote:<br>
><br>
> [...] close() method on WorkerGlobalScope.<br>
><br>
> In particular, the spec seems to imply that after calling close() inside<br>
> the worker, the JS does not get terminated right away, but rather<br>
> continues to execute, while an internal 'closing' flag is set and a<br>
> message queue associated with the worker discards all the tasks,<br>
> existing and future. Also, all ports are immediately disentangled.<br>
<br>
I've changed the spec based no the feedback below so that the ports are no<br>
longer disentangled upon calling close().<br>
<br>
<br>
> This seems to leave some questions without explicit answer, with<br>
> differences in current implementations:<br>
><br>
> 1. Does this code in a worker continues looping until the parent page<br>
> unloads:<br>
>  ...<br>
>  close();<br>
>  while(true) {}<br>
><br>
> WebKit V8 terminates, WebKit JCS terminates after a timeout, FF does not<br>
> terminate.<br>
<br>
FF is correct. The WebKits are not non-conforming, though, since you're<br>
basically allowed to kill workers whenver.<br>
<br>
<br>
> 2. Do the errors propagate back to Worker object after close()?<br>
> ...<br>
> close();<br>
> nonExistingFunction();  <<-- throws, if not processed locally, posts error<br>
> info to the Worker object.<br>
><br>
> In WebKit and FF errors propagate, although it does not seem consistent<br>
> while worker closed all the ports and is in a dormant state.<br>
<br>
The spec seems clear that close() has no effect on error propagation.<br>
<br>
<br>
> 3. Should synchronous operations work after close()? Asynchronous ones<br>
> perhaps should not, because of the event loop queue which is stopped...<br>
> ...<br>
> close();<br>
> xhr.open("GET", "<a href="http://foo.com" target="_blank">foo.com</a>", *false*);<br>
> xhr.send();<br>
><br>
> WebKit: does not work (mostly), FF - does work.<br>
<br>
Anything depending on tasks doesn't work. Sync XHR doesn't seem to use the<br>
event loop mechanism, so it's ok.<br>
<br>
<br>
> Perhaps it would be simpler to either say nothing is executed/posted/fired<br>
> after close() (immediate termination), or to enable worker run unimpeded<br>
> (with ports open, etc) until it naturally yields from JS.<br>
<br>
I've gone with the latter.<br>
<br>
<br>
On Tue, 30 Mar 2010, Drew Wilson wrote:<br>
><br>
> I'll note that the spec gives the UA an significant amount of latitude<br>
> about its behavior after close() is called:<br>
><br>
> User agents may invoke the "kill a worker <#kill-a-worker>" processing<br>
> model on a worker at any time, e.g. in response to user requests, in<br>
> response to CPU quota management, or when a worker stops being an active<br>
> needed worker<#active-needed-worker> if the worker continues executing<br>
> even after its closing<#dom-workerglobalscope-closing> flag was set to<br>
> true.<br>
><br>
> Essentially, UAs can kill a worker at any time, and since the "kill a<br>
> worker" algorithm allows UAs to abort the script after a<br>
> user-agent-defined amount of time (including zero), it seems like almost<br>
> any behavior post-close is compliant. This seems like a guaranteed<br>
> source of cross-browser incompatibilities.<br>
<br>
It also allows killing scripts pre-close. We don't really have much choice<br>
here; browsers need to be able to terminate any malware or runaway<br>
process at their whim, basically.<br>
<br>
<br>
> I've always operated under the impression that the intent of the spec is<br>
> to allow pending worker operations to complete, but still give UAs the<br>
> ability to abort scripts that don't exit in a timely manner (so close()<br>
> should not immediately abort the script), but I don't see anything in<br>
> the spec regarding this.<br>
<br>
This is what the spec now requires, modulo UAs being allowed to bail on<br>
worker scripts at any time.<br>
<br>
<br>
> For #2 [above], I believe that exceptions in worker context should<br>
> *always* be reported, regardless of closing state. Section 4.6 (Runtime<br>
> script errors) makes no mention of tying this behavior to the closing<br>
> flag.<br>
<br>
Indeed.<br>
<br>
<br>
On Tue, 30 Mar 2010, Dmitry Titov wrote:<br>
><br>
> But if we say close() lets script run until completion (but prevents<br>
> further messages/events from dispatching), then perhaps we don't need it<br>
> at all - there is nothing then that script in the worker can not do to<br>
> the same effect (unregister onmessage, clear timers etc).<br>
<br>
It can be a lot harder to actually find all the various things that are<br>
keeping a worker alive than just to call close().<br>
<br>
<br>
> That means letting worker to call close() on itself only makes<br>
> additional sense if it is specified as immediate termination. It could<br>
> be useful and it can be specified in deterministic manner.<br>
<br>
I agree that immediate termination might also be useful, but if that's<br>
what you want, just don't do anything after calling close(). :-)<br>
<br>
<br>
On Thu, 1 Apr 2010, Jonas Sicking wrote:<br>
><br>
> The one thing that we do and that is somewhat iffy is the close event.<br>
<br>
The close event is no longer in the spec, so at this point it's a Firefox<br>
proprietary feature. :-) We removed it to prevent exposing GC behaviour,<br>
because otherwise if pages start depending on one particular behaviour,<br>
we'll have accidentally forced the GC rules into the platform, which<br>
seems like an incredibly bad idea.<br>
<br>
<br>
> [...] it exposes GC behavior. This is very unfortunate indeed and<br>
> because of it I feel that our implementation is somewhat experimental.<br>
<br>
I would recommend dropping the 'close' event for this reason.<br>
<font color="#888888"><br>
--<br>
Ian Hickson               U+1047E                )\._.,--....,'``.    fL<br>
<a href="http://ln.hixie.ch/" target="_blank">http://ln.hixie.ch/</a>       U+263A                /,   _.. \   _\  ;`._ ,.<br>
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'<br>
</font></blockquote></div><br></div>