W3C home > Mailing lists > Public > whatwg@whatwg.org > August 2008

[whatwg] Workers feedback

From: Jonas Sicking <jonas@sicking.cc>
Date: Fri, 08 Aug 2008 00:15:33 -0700
Message-ID: <489BF295.2000206@sicking.cc>
>> One solution I thought about is to have a base interface such as:
>>
>> interface MessagePort {
>>   void postMessage(...);
>>   attribute EventListener onmessage;
>>   ...
>> }
>>
>> Then have
>>
>> interface Worker : MessagePort {
>>    bool isShared();
>>    <worker specific stuff>
>> }
>>
>> interface PipePort : MessagePort {
>>    attribute Window ownerWindow;
>>    <Pipe specific stuff>
>> }
>>
>>
>> And then make the APIs that we want to allow passing around pipe-ends take a
>> PipePort object.
>>
>> The result is basically that workers are separate objects from what's 
>> returned for (new MessagePipe()).port1, but they share some API.
> 
> The problem there though is that when you receive a port, you have no idea 
> if it's a port into another frame, or a port into a worker that happened 
> to be created as a pipe, or a port into a worker that happened to be 
> created when the worker was created. I don't see why you would ever need 
> to have that distinction, either.

Sorry, I might have been unclear. My suggested inheritance might be 
better explained as

interface CommunicationPort {
   void postMessage(...)
   attribute EventListener onmessage;
   ...
}

interface Worker : CommuncationPort {
   attribute EventListener onload;
   attribute EventListener onerror;
}

interface MessagePort : CommunicationPort {
}

I.e. we wouldn't allow a Worker to be passed to postMessage, but the 
object returned from myPipe.port1 would be allowed.

> The whole point of ports as an 
> architectural concept is that they provide an opaque interface, and who 
> exactly is on the other side is not something that you should need to have 
> any information about.

Why do we need this feature? I.e. why is it useful to have an abstracted 
MessagePort where you don't know who you are communicating with?

The one useful thing that I see that MessagePorts do is that they allow 
objects that usually can't directly reach each other send messages to 
each other. I.e. two iframes that live next to each other can't usually 
get a reference to each other, but using MessagePorts a communcation 
channel can be negotiated between them.

Similarly, two sibling workers can't in the current proposal reach each 
other, but using MessagePorts they can communicate with each other anyway.

>> I in general am not a big fan of the MessagePort API, the whole cloning 
>> and dying thing is really ugly. I don't think there is much we can do 
>> about that, but because of it I think we should only use the API when 
>> it's strictly needed, which seems to be only in fairly complex usecases. 
> 
> I don't really understand this concern. Why is it complex? Then again, I 
> have the same reaction to your proposal for a Worker object. :-)

My proposal makes Workers behave the same way as Windows when it comes 
to sending messages. I think postMessage on Windows can generally be 
considered a success, I haven't heard a lot of people complaining about 
it being complex.

>> Exposing a MessagePort as a permanent property, like the global 'port' 
>> property, has the downside that that object can potentially die if the 
>> MessagePort is ever passed through postMessage somewhere.
> 
> Do you mean that:
> 
>    var w = createWorker('worker.js');
>    otherWindow.postMessage('here is the worker you asked for', w.port);
>    w.port.postMessage('oh i wanted to talk to you after all');
> 
> ...would fail? (It would return false from the last call.)

Yes.

Further, the fact that a clone is created on the other end rather than 
the same object I think can be confusing. I.e. if I set an expando on a 
port the receiver of the port won't see the expando. This is required 
since otherwise we'd have synchronous communication between threads, but 
I think it's confusing to authors. This is why I generally don't like 
MessagePorts and think that they should be used as little as possible.

Also, I would have expected the above to throw an exception. Having it 
silently fail (which is what'll happen if you don't check the return 
value) seems likely to cause hidden bugs.

> I don't think this is a big problem. I mean, it's like being worried that 
> references into a window fail to have the right effect after the window is 
> closed or navigated.

I think for windows we are usually saved by the fact that generally when 
a window is navigated, all the code that uses that window is killed.

>> This leaves the user with a permanent property containing a dead useless 
>> object. Not exposing it as a permanent property forces things like the 
>> onconnect event and returning a MessagePort from createWorker.
> 
> Do you mean on the Worker (outside) or the WorkerGlobalScope (inside)?

Yes

> The current spec doesn't expose 'port' as a permanent attribute on the 
> WorkerGlobalScope (inside), it's just a property added to the global 
> object, it's not NoDelete or anything.

Hmm.. pretty much all other properties that are created by a browser is 
permanent. So I don't expect that this will change as far as user 
expected behavior goes.

I have yet to actually see any advantages to demanding the use of 
MessagePorts. Other than potentially somewhat nicer interface for shared 
workers, but I don't think that's common enough to optimize for, nor do 
I think the win there is particularly big.

/ Jonas
Received on Friday, 8 August 2008 00:15:33 UTC

This archive was generated by hypermail 2.4.0 : Wednesday, 22 January 2020 16:59:04 UTC