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

Declarative WebWorker? #4786

Open
fserb opened this issue Jul 18, 2019 · 11 comments
Open

Declarative WebWorker? #4786

fserb opened this issue Jul 18, 2019 · 11 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: workers

Comments

@fserb
Copy link
Contributor

fserb commented Jul 18, 2019

This is not a full proposal yet, but I'd like to float the idea.

How do people feel about having a declarative WebWorker API by providing a new attribute to the script tag that makes the script load on a separate WebWorker? For example:

<script id='myid' worker src='myscript.js'></script>
<script id='other' worker>
//...
</script>

document.getElementById('myid').targetWorker.postMessage(...);

or maybe using a different type:

<script id='myid' src='myscript.js' type='text/javascript-worker'></script>
<script id='other' type='text/javascript-worker'>
//...
</script>

document.getElementById('myid').worker.postMessage(...);

I think this is much nicer and more descriptive than the current createObjectURL(new Blob(textContent)) approach to inline workers. It could boost and simplify usage of WebWorkers.

@annevk
Copy link
Member

annevk commented Jul 18, 2019

So I'm sure this was discussed before as <script type=worker> (alongside type=module before that settled; potentially as <worker> and <module>) and there was general support because of the annoying pattern you mention, but unfortunately I cannot find that discussion. I think something like this makes sense.

@annevk annevk added topic: workers addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest labels Jul 18, 2019
@fserb
Copy link
Contributor Author

fserb commented Jul 18, 2019

with type=module, it means we would have to add type=worker and type=worker-module, I guess.
I tried to find the discussion but couldn't find it either.

@annevk
Copy link
Member

annevk commented Jul 18, 2019

Or maybe only allow module workers since non-modules are considered "classic".

@domenic
Copy link
Member

domenic commented Jul 18, 2019

My problem with this has always been that existing <script>s take place within the page's global scope. It's very strange to introduce something that looks so similar but behaves so drastically different. As such I've always preferred improving the story for creating workers from strings via new JS APIs, not new HTML.

@fserb
Copy link
Contributor Author

fserb commented Jul 18, 2019

Domenic, but that's the thing. People are already doing something that "looks so similar but behaves so drastically different". Except it's not explicit. Chrome has a bunch of code like this:

<!doctype html>
<html>
<body>
<canvas id='output' width='100' height='100'></canvas>
<script id='myWorker' type='text/worker'>
// wortker JS code
</script>
<script>
var blob = new Blob([document.getElementById('myWorker').textContent]);
var worker = new Worker(URL.createObjectURL(blob));
</script>
</body>
</html>

So we already have code that is on a <script> tag but that doesn't run on the page scope.

I don't think a better String to Worker API would solve this. People will keep doing things like the code above because you get the benefits of the <script> tag (syntax highlight, being on the same file, etc). Nobody wants to write code inside multi-line strings.

So my thinking is: we can make this less hacky, clearer and simpler for people to use.

@domenic
Copy link
Member

domenic commented Jul 18, 2019

I agree people can hack up something that is unintuitive and weird today. I don't think that's necessarily a great motivation for adding such semantics to the platform natively, especially if---as you explain---it's pretty easy to do without native support.

I think we could make it even easier, while maintaining the current invariant that in-page scripts run in the page's process, via a new string API. So that your example would become

<!doctype html>
<html>
<body>
<canvas id='output' width='100' height='100'></canvas>
<script id='myWorker' type='text/worker'>
// wortker JS code
</script>
<script>
var worker = Worker.fromString(document.getElementById('myWorker').textContent);
</script>
</body>
</html>

This seems to strike a better balance to me.

@fserb
Copy link
Contributor Author

fserb commented Aug 26, 2019

I'm not sold that your example is cleaner than what I suggested, but I agree that removing the Blob/createObjectURL would be a good thing, so I'm fine moving in this direction.

Do we know anyone on Firefox or Safari that deal with workers?

@asutherland
Copy link

Hi, I work on Firefox Workers. I would have the following concerns with the element based solution:

  • We're trending towards setting explicit headers for policy-related reasons on all Worker-variant globals. While Blob workers already have necessitated inheritance policies, creating an element-based affordance that might then give way to means of tunneling the headers or effects of those headers through would seem to complicate the spec a lot.
  • Lifecycle issues.
    • We can currently GC workers if the Worker binding gets GC'ed and there are no "message" listeners on it and/or the Worker cannot possibly generate a message given its state, but this declarative mechanism would bias towards creating a static root for the worker unless the page goes out of its way to remove the element.
    • When would the worker start? As soon as the </script> tag gets hit? Would we make the worker's creation obey "async" and "defer"?
    • An auto-starting worker potentially is going to race the page-load itself for resources.

I am agreed that anything we can do to reduce calls to createObjectURL and the potential leakage of the underlying blob by a failure to revoke the URL would be an improvement. So I like the idea of Worker.fromString. But Spec-wise, it seems like that potentially just amounts to syntactic sugar for createObjectURL/new Worker/revokeObjectURL? Unless we wait for a means of creating a Worker directly from a Response?

@domenic
Copy link
Member

domenic commented Aug 26, 2019

Unless we wait for a means of creating a Worker directly from a Response?

Interesting, that'd be basically as convenient, and would help with some of the header-based issues:

var worker = new Worker(new Response(document.getElementById('myWorker').textContent, headers));

However I guess such responses would have no URL, so we'd have to do a bit of legwork to figure out what that means... and it might amount to reinventing similar semantics to blob: URLs, hmm. But at least it's work that would pay off in other forms (i.e. for creating other resources from Response instances).

@asutherland
Copy link

Yeah, to be clear, I meant assume we've solved whatwg/fetch#49 first. (And maybe assume that we provide some means of stuffing a URL into the response on the basis that ServiceWorkers allow origins to lie to themselves about such things, and that w3c/ServiceWorker#1026 and the proposal at w3c/ServiceWorker#1195 (comment) ties into our desire for the above fetch issue to be resolved, in which case we wouldn't have to roundtrip through a ServiceWorker.)

@RReverser
Copy link
Member

I came across this issue while searching the tracker to see if someone proposed creating a Worker from Response before. @domenic's snippet looks pretty close to what I had in mind, but I was wondering if it would make more sense to add a Promise-based API similar to WebAssembly.instantiateStreaming:

Worker.instantiate('...').then(worker => ...);
Worker.instantiate(fetch('...')).then(worker => ...);
Worker.instantiate(new Response('...')).then(worker => ...);

With this, we could kill two birds with one stone and provide both a way to create workers from custom requests/responses, as well as a way to get load/error status in a unified way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: workers
Development

No branches or pull requests

5 participants