Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34.3k
events,bootstrap: make globalThis extend EventTarget#45993
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
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading. Please reload this page.
Conversation
KhafraDev commented Dec 28, 2022 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Fixesnodejs#45981 Changes: - Moves all EventTarget symbols to one symbol, to prevent exposing 4 symbols to globalThis. - Fallback to `globalThis` as the this value in EventTarget if this is null or undefined. This is needed to make the "floating" methods work (ie. `addEventListener(...)`).
nodejs-github-bot commented Dec 28, 2022
Review requested:
|
anonrig commented Dec 28, 2022
We can enable certain web platform tests with this, right? @KhafraDev |
anonrig commented Dec 28, 2022
If we are going to do this, and if this is a breaking change, I believe a flag is needed to enable this experimental feature |
KhafraDev commented Dec 28, 2022 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
I don't think so, I'm pretty sure the WPT runner will throw an error if previously failing tests started passing. edit: one test was enabled actually. |
aduh95 left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd need to forbid their use in lib/ as we do with other browser globals:
Lines 155 to 156 in 3ce4cef
| - name: console | |
| message: Use `const{console } = require('internal/console/global');` instead of the global. |
aduh95 commented Dec 28, 2022
@joyeecheung does this have an impact on the snapshotting effort? |
KhafraDev commented Dec 28, 2022
I updated the eslint config but I wasn't sure what they should be replaced with. |
Uh oh!
There was an error while loading. Please reload this page.
addaleax commented Dec 31, 2022
Do we feel like this is something we want in Node.js? I understand that this is something that other platforms do, but those platforms aren't Node.js and didn't have things like the I'm not even sure that browsers would do this nowadays with the benefit of hindsight in how JS developed as a language. But yeah, either way, definitely a significant breaking change, probably one where it's worth pinging @nodejs/collaborators. |
mcollina commented Dec 31, 2022
Tagging it tsc-agenda for awareness. |
mcollina commented Dec 31, 2022
I'm not convinced we should land this change. None of the cases mentioned in the linked issues are applicable to Node. Most of the useful cases are already handled by Node.js |
jasnell commented Jan 1, 2023
I'd say no right now. If we do ever make globalThis emit events then yes it should be EventTarget and not EventEmitter but I don't think there's enough justification for this now. |
benjamingr commented Jan 1, 2023
I'm also -1 on this for the previously mentioned reasons. |
ShogunPanda commented Jan 1, 2023
I'm neutral at the moment. |
GeoffreyBooth commented Jan 1, 2023
Is this something that perhaps users could opt into? Like a method on |
KhafraDev commented Jan 1, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Currently? No, because node doesn't implement it. In the future I can see libraries adopting it to emit events, rather than using the node-only process/EventEmitter combo. It helps writing isomorphic libraries, in a way that build tools (such as typescript, linters, etc) will be fine with. It should also be pointed out that both process and globalThis EventTarget can exist separately, without causing issues. globalThis doesn't need to re-implement all of process' events. Although I assume if this landed it would be requested.
I would say that this change isn't applicable because node doesn't implement it. If node's global object always extended EventTarget, there would undoubtedly be libraries/apps/scripts using it, rather than using process. The same argument could probably be used for any web standard - "x isn't applicable to node, you can use y instead" (even when the proposed alternative is a very loose fit IMO).
If there's not enough reason to add it now, I doubt there ever will be 😅. People aren't writing code that will hopefully work in node one day. |
mcollina commented Jan 1, 2023
My two cents: libraries emitting global events make the ecosystem more brittle. Sometimes certain behaviors must be global, but it's essentially a pattern to avoid whenever possible. I'm loosely -1, but I might be convinced to approve it if there is a fundamental use case to cover. |
joyeecheung commented Jan 2, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
I don't think so, as long as no events are emitted/handlers are added during bootstrap (I don't see any here). I am +1 to the idea of making |
KhafraDev commented Jan 3, 2023
Here are the events Deno has https://deno.land/[email protected]/runtime/program_lifecycle#program-lifecycle (load, beforeunload, unload, and unhandledrejection). |
GeoffreyBooth commented Jan 3, 2023
Just so that my question doesn’t get lost, is there a way to opt into this? So that the default behavior doesn’t change, but users who want this can enable it. I think that might make it much more palatable, and we can defer the decision on whether it should be enabled by default. |
srl295 commented Jan 3, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Question. Is there any hope/request that the browsers, deno, etc would move these out of global and into some proper scope? like Edit: per #45993 (comment)
this. (if you'll pardon the pun). What would they do? Probably something different, putting these events into a different scope than globalThis. |
KhafraDev commented Jan 3, 2023
No, there's no feasible way of adding EventTarget methods onto fetch (etc.). Deno has recently added events to globalThis, so it's unlikely they're gonna change anything either. Specs that were planning on emitting events already extend EventTarget, such as WebSocket, XMLHttpRequest, FileReader, and others. Plus, there are global events for fetch that work in service workers.
It could be done in a future PR, this PR doesn't change how events are emitted. |
mhdawson commented Jan 4, 2023
We discussed in the TSC meeting today, at this point the consensus seems to be that value |
Uh oh!
There was an error while loading. Please reload this page.
Qard commented Jan 5, 2023
It would be handy to implement things like Main thread: constfetchWorker=newFetchWorker('my-fetch-worker',{port: 1234})Worker thread: addEventListener('fetch',event=>{returnevent.respondWith(newResponse('Hello!'));});I feel like most of the interop cases where we'd benefit from having globalThis extend EventTarget are related to ServiceWorker features. Can anyone think of a case where we'd actually want that in the main thread? |
KhafraDev commented Jan 6, 2023
Same uses as process emitting events. I wouldn't call process a good alternative though, considering only one platform supports it. It could technically be used as an alternative to diagnostics_channel as well (FetchEvent is a good example of being able to use the global event listener to debug/log/intercept requests made). |
jimmywarting commented May 25, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
to listen to any of this events:
|
benjamingr commented May 25, 2023
What's |
tniessen commented May 25, 2023
Many of these events are questionable in the context of Node.js (e.g., |
KhafraDev commented May 25, 2023
I think I mentioned it in the PR, but the only events node would probably want to add would be the same as Deno: https://deno.com/[email protected]/runtime/program_lifecycle#program-lifecycle |
jcbhmr commented May 25, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
To quote myself from #45981 for those who are subscribed to this PR thread:
|
This comment was marked as off-topic.
This comment was marked as off-topic.
aduh95 commented May 26, 2023
That link doesn't mention any |
benjamingr commented May 26, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
(fwiw: There existed such an event in some spec drafts and discussions "back then" around 2015-2017 and I was curious if browsers ended up adding some sort of promise tracking eventually (which they were opposed to)). I am happy to hide these comments as off topic and I also think we need to open an issue or discussion rather than having this discussion in the PR since none of it is about the actual code in the PR edit: here: #45981 |
jasnell commented May 29, 2023
I'm still generally -1 on this given the confusion it is likely to cause with |
jimmywarting commented May 29, 2023
How about being able to opt into it like two have already suggested? Having it behind a flag and potentially only try it out in a un-even NodeJS release... import`node:util/attach-eventtarget-to-global`/* Would basically change the prototype of globalThis with Object.setPrototypeOf(...)and add postMessage, addEventListener, removeEventListener, dispatchEventdoing globalThis instanceof EventTarget would also be true then after importing this util*/but this seems very unconventional and weird? think a flag would be better to have |
jasnell commented May 29, 2023
If someone really wanted to opt in to that they could fairly easily do... |
jcbhmr commented May 29, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
The |
KhafraDev commented May 29, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Yes, somewhere in the webidl spec ( // Emits an event in browsers/Deno/etc., but does nothing in node.EventTarget.prototype.dispatchEvent.call(globalThis,newEvent('fetch')) |

This is probably a breaking change. I will add tests once the actual implementation's been approved just so I don't waste time writing tests for a feature that won't land 😄. Same with docs.
Changes:
symbols to globalThis.
globalThisas the this value in EventTarget if this isnull or undefined. This is needed to make the "floating" methods work
(ie.
addEventListener(...)). It's also a webidl thing,https://webidl.spec.whatwg.org/#dfn-create-operation-function
dispatchEvent,addEventListener,removeEventListener.Fixes: #45981