dglazkov / tubes

Web Platform Plumbing
Apache License 2.0
11 stars 0 forks source link

navigator.connect() should return MessagePort #8

Open omo opened 10 years ago

omo commented 10 years ago

Instead of passsing message port, why not return established connection?

partial interface Navigator { Promise connect(DOMString url, DOMString type); };

It guarantees if the connection is established (because there are no pre-connect channel!) And we can also hide how the channel is implemented. Exposing MessageChannel as underlying pipe is necessarily strong constraint.

rginda commented 10 years ago

We could consider changing navigator.connect to:

navigator.postMessage(DOMString url, any message, optional Array messagePorts)

That would allow for an initial message payload and zero or more outbound transferrables. If some alternate message channel became available in the future (like, say Mojo), then apps could upgrade at will. It also follows the precedent of window.postMessage and MessageChannel.postMessage.

omo commented 10 years ago

It could be explained as a shorthand of

Also, it's kind of sateful vs. stateless messaging choice. If we push stateless messaging, having only postMessage() makese sense. Otherwise, connect() would be preferable.

rginda commented 10 years ago

True, but then the user agent decides the messaging implementation rather than the endpoints. A nagivator.connect implementation that returns a MessagePort will always have to return a MessagePort or something very similar. If the endpoints are in control, they may be able to negotiate a different messaging primitive in the future.

By starting stateless, the two endpoints can decide for themselves an appropriate messaging implementation, stateful or not, MessagePort or not.

Starting a stateful connection is still easy:

var ch = new MessageChannel();
navigator.postMessage('http://url', {'magic': 'foobar/1.0'}, [ch.port2])

And the remote endpoint can tell by the 'magic' in the message payload that they have some understanding of the connection being attempted.

omo commented 10 years ago

I don't particularly support using MessagePort, as its stateful nature might complicate the design. For example, it is not clear what happens if a page attemps to connect() to same endpoint (URL) more than once. Stateless path doesn't have such a problem. So I agree that stateless could be better.

That being said, I think proposed navigator.postMessage() has an ergonomic problem: Its signature is different from any existing postMessage(), that is confusing. It'd better to model it after existing API if possible.

Considering this API as a cross-origin messaging between ServiceWorker, I think it makes more sense to follow the ServiceWorker API [1]. Its surface is similar to MessagePort but its semantics is (I believe) more flexible than that. It just represents an endpoint to the worker, which might be stateless or stateful. Actually, this is true for ServiceWorker. It can be killed at anytime thus cannot be stateful.

We could (and probably should) limit the API surface by, for example, defining something like WorkerProxy interface as if Web has WindowProxy for Window.

[1] http://www.w3.org/TR/2014/WD-service-workers-20140508/#service-worker-obj

rginda commented 10 years ago

I wonder if we could allow ServiceWorker to be constructable like a Worker or SharedWorker...

var ch = new MessageChannel();
var sw = new ServiceWorker('http://other.domain.com');
sw.postMessage({'magic': 'foobar/1.0'}, [ch.port2]);

It would be a little odd, since ServiceWorker already has properties that you wouldn't want to share, but maybe we could throw exceptions for attempts to read them or put placeholder values there.

The nice thing is it works exactly like the other workers and we don't introduce any new API surface.

omo commented 10 years ago

At the same time, it isn't clear sw.onmessage works in that case. Allowing the instantiation seems equivalent to making it stateful.

Anyway, I feel like we're stepping into details too much. It'd better wait @slightlyoff's first draft to be in the same page. Apparently API.md in this site is already outdated.