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

worker: align MessagePort message handling more with Web #26487

Closed
wants to merge 2 commits into from

Conversation

addaleax
Copy link
Member

@addaleax addaleax commented Mar 7, 2019

This aligns MessagePorts more with the web API and resolved #26463.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. worker Issues and PRs related to Worker support. labels Mar 7, 2019
@addaleax addaleax force-pushed the worker-messageport-noerror branch from 365a595 to 8354833 Compare March 7, 2019 09:34
@addaleax
Copy link
Member Author

addaleax commented Mar 7, 2019

/cc @nodejs/workers

CI: https://ci.nodejs.org/job/node-test-pull-request/21299/

@@ -203,6 +203,11 @@ input of [`port.postMessage()`][].
Listeners on this event will receive a clone of the `value` parameter as passed
to `postMessage()` and no further arguments.

When there are `'message'` event listeners and `.start()` is not called
explicitly, and the Web-based `.onmessage` property is not used, no messages
Copy link
Member

@Trott Trott Mar 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we capitalize web generally so maybe web-based?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Maybe web-baed should be removed? It seems likely to be misunderstood. I think we just mean "modeled on the analogous web-based API" but people are likely to interpret as more like...something to do with the web directly? That's what I did when I read this for a few seconds.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Both comments above are non-blocking.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think removing web-based would be a bit confusing, given that we don’t currently document onmessage ourselves.

@chjj
Copy link
Contributor

chjj commented Mar 7, 2019

I'd like to look at this more closely.

To keep things clear, the current behavior on master is:

  • .on('message', fn) with no listeners -> reference and start
  • .off('message', fn) with one listener -> dereference and stop
  • .onmessage = fn -> reference and start
  • .onmessage = null -> dereference and stop

This PR changes the behavior to:

  • .on('message', fn) with no listeners -> reference and start (unchanged)
  • .off('message', fn) with one listener -> dereference and stop (unchanged)
  • .onmessage = fn -> reference and start (unchanged)
  • .onmessage = null -> dereference, do not stop (changed)

I believe the browser behavior should be:

  • .on('message', fn) with no listeners -> reference, do not start
  • .off('message', fn) with one listener -> dereference, do not stop
  • .onmessage = fn -> reference and start
  • .onmessage = null -> dereference, do not stop

I'll have to write up some code to confirm that the latter is actually the browser behavior (I haven't actually confirmed that .addEventListener('message') does not start the port, at this point I'm just taking MDN's word for it). It might take me a second.

If that is the behavior, I think there's one more thing to consider: the browser doesn't have references since it's an ever-living event loop (I'm pretty sure workers can't exit gracefully in-browser). That said, we could maybe consider removing the magical referencing behavior of .on('message') and .off('message') altogether since it doesn't actually have anything to do with starting or stopping the port anymore. This would mean that the parentPort would have to be started by default (I believe it is in the browser, since self.start() does not exist, but I'll have to test this as well.

It's probably worth discussing a bit more before anything is merged.

@addaleax
Copy link
Member Author

addaleax commented Mar 7, 2019

@chjj I think you’re correct about the behaviour everywhere here.

The behaviour for the Node.js-style APIs was picked because it made the most sense to me, and since the browser has neither .on nor .off methods (and the browser lacks EventEmitter as an API and Node.js lacks EventTarget as an API in general), it didn’t seem like a full match was feasible or desirable.

For example, the “event” that the onmessage function receives in Node.js is not really close to being a full MessageEvent.

@chjj
Copy link
Contributor

chjj commented Mar 7, 2019

@addaleax, yeah, the more I think about it, the way node does it makes more sense than the browser. In my own worker compatibility module, I actually hack the browser into behaving like node since it seemed to make more sense in the end.

Personally, I'd be fine with having things stay the way they are and simply document the difference (i.e. node.js will automatically start and stop the buffering of the port).

Anyway, I'm going to tinker with the browser more to confirm the exact behavior. Right now, I suspect that addEventListener('message') has no magic behavior and that DedicatedWorkerGlobalScope is akin to a MessagePort started by default.

@chjj
Copy link
Contributor

chjj commented Mar 7, 2019

I've confirmed that MDN was correct about port.addEventListener('message'): it does not start the port in the browser.

I've also confirmed that DedicatedWorkerGlobalScope behaves like a MessagePort which is started by default (i.e. you will miss self.onmessage events if you don't bind the listener right away). I don't think it's worth starting the parentPort by default just for browser compat, since there's probably some legitimate use cases for not doing that in node.js.

I think the third behavior I described in my first post is probably the way to go if we want browser compat. That said, it might be worth just keeping things the way they are. I do think the current node.js behavior is much saner than the browser. I think my original issue may have been bikeshedding a bit. Would love to hear your thoughts, @addaleax.

edit: I take it all back. I've spent the last hour trying to hash out a sane model which matches the browser. I slowly started diverging from the browser each time something didn't feel quite right until I arrived at node.js's current behavior. Node is right, the browser is wrong.

@addaleax
Copy link
Member Author

addaleax commented Mar 9, 2019

@chjj So… where would you stand on this PR itself? I agree with you in that the browser behaviour is odd, but I also see value in explicitly aligning with the Web spec here.

Then again, I’m not even sure that the difference is guaranteed to be observable, because in theory receiving a message can take an arbitrary amount of time (and thus just “randomly” happen when a new onmessage listener has been attached).

I’m personally happy to close this and just document the difference, as you suggested above?

@chjj
Copy link
Contributor

chjj commented Mar 9, 2019

@addaleax, as far as the PR, I'd say the Cannot send data on closed port error should still be removed, but no changes should be made to the onmessage or .on('message') start/stop behavior. I think the current node behavior is good. Documenting the differences from the browser is probably sufficient.

@addaleax addaleax force-pushed the worker-messageport-noerror branch from ab4fae7 to 77f6b8c Compare March 10, 2019 11:13
@addaleax
Copy link
Member Author

@chjj Okay, I think we’re in agreement – I’ve removed the changes for .onmessage and added docs for the divergence from the browser.

@gireeshpunathil @benjamingr Do you want to take another look?

@gireeshpunathil
Copy link
Member

still LGTM.

@BridgeAR
Copy link
Member

BridgeAR commented Mar 10, 2019

CI https://ci.nodejs.org/job/node-test-pull-request/21404/ (:heavy_check_mark:)

@BridgeAR BridgeAR added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Mar 10, 2019
@addaleax
Copy link
Member Author

Landed in a52aede, 137d3d2

@addaleax addaleax closed this Mar 11, 2019
@addaleax addaleax deleted the worker-messageport-noerror branch March 11, 2019 09:59
addaleax added a commit that referenced this pull request Mar 11, 2019
This aligns `MessagePort`s more with the web API.

Refs: #26463

PR-URL: #26487
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Gireesh Punathil <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
addaleax added a commit that referenced this pull request Mar 11, 2019
Fixes: #26463

PR-URL: #26487
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Gireesh Punathil <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
BridgeAR pushed a commit that referenced this pull request Mar 13, 2019
This aligns `MessagePort`s more with the web API.

Refs: #26463

PR-URL: #26487
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Gireesh Punathil <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
BridgeAR pushed a commit that referenced this pull request Mar 13, 2019
Fixes: #26463

PR-URL: #26487
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Gireesh Punathil <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
BridgeAR pushed a commit that referenced this pull request Mar 14, 2019
This aligns `MessagePort`s more with the web API.

Refs: #26463

PR-URL: #26487
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Gireesh Punathil <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
BridgeAR pushed a commit that referenced this pull request Mar 14, 2019
Fixes: #26463

PR-URL: #26487
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Gireesh Punathil <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. c++ Issues and PRs that require attention from people who are familiar with C++. worker Issues and PRs related to Worker support.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

worker_threads: inconsistent stop/start behavior with MessagePort.onmessage
8 participants