-
Notifications
You must be signed in to change notification settings - Fork 458
Html element onerror eventhandler override #2272
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?
Html element onerror eventhandler override #2272
Conversation
|
Thanks for the PR! This section of the codebase is owned by @saschanaz - if they write a comment saying "LGTM" then it will be merged. |
|
This one is ready for review @saschanaz. |
saschanaz
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.
Sorry for the long delay, wasn't quite sure what to do with this PR. Now I sorta do...
| * | ||
| * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) | ||
| */ | ||
| addEventListener(type: string, listener: ((event: Event) => void) | ((event: UIEvent) => void)): void; |
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.
This is not quite right as this affects all other events. And still not sure about UIEvent:
- MDN's description is a copypaste of what UI Events spec says in https://w3c.github.io/uievents/#event-type-error:
UIEvent if generated from a user interface, Event otherwise.
- But then the same spec says otherwise in https://w3c.github.io/uievents/#event-types-list, where it only says Error for error event. So does HTML in https://html.spec.whatwg.org/multipage/webappapis.html#event-handlers-on-elements,-document-objects,-and-window-objects.
- Nothing in UI Events says exactly when UIEvent is used for error event.
- UI Events also argues load event uses UIEvent, which is untrue.
- UI Events hasn't been well maintained, see also the "Future of UI Events" discussion in https://docs.google.com/document/d/1fOjXiGUFf_krkfYaWf5drbqzY7CTxn7EcDYr5ZWjzFg/preview.
So I'd like to suggest excluding UIEvent in this PR.
| onended: ((this: GlobalEventHandlers, ev: Event) => any) | null; | ||
| /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/error_event) */ | ||
| onerror: OnErrorEventHandler; | ||
| onerror: DocumentOrGlobalOnErrorEventHandler; |
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.
This also affects all other interfaces so it partially repeats the same issue of OnErrorEventHandler, and also not quite I suggested in #2148 (comment)...
I was thinking about:
interface DocumentOrElementEventHandlers extends GlobalEventHandlers {
onerror: ((this: GlobalEventHandlers, ev: Event) => any) | null;
};And make others inherit this instead of GlobalEventHandlers when appropriate. Wdyt?
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.
But that as-is has an assignability issue. Hmm.
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 do have extendConflictsBaseTypes in emitter.ts which can help here... it's sad to add more there but it does make sense here.
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.
Doing so would make subinterfaces to fail to assign to a variable typed as GlobalEventHandlers, which is a bit worrisome.
Hmmmmm. Maybe a better way is to make it reversed?
interface GlobalEventHandlers {
// remove OnErrorEventHandler and make it general here
onerror: ((this: GlobalEventHandlers, ev: Event) => any) | null;
}
interface GlobalErrorEventHandlers extends GlobalEventHandlers {
onerror: OnErrorEventHandler;
}
// Make global interfaces extend GlobalErrorEventHandlers instead of GlobalEventHandlers.
// Ideally this should be replaced automatically by emitter than overridingTypes, as
// the latter wouldn't support any upcoming new globals.
// Checking `global` property for each interface should allow it.
interface Window extends GlobalErrorEventHandlers {
// ...
}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.
Err. Actually if we are going to check globals then we don't need GlobalErrorEventHandlers at all. The emitter can just add an overridden onerror property directly to each global interface.
interface GlobalEventHandlers {
// Remove OnErrorEventHandler and make it general here.
// Replacing it to a general EventHandler would do this automatically.
onerror: ((this: GlobalEventHandlers, ev: Event) => any) | null;
}
interface Window extends GlobalEventHandlers {
onerror: OnErrorEventHandler;
}
This PR fixes microsoft/TypeScript#62075.
Originally, I created this #2148 (comment), but closed it as the that approach wasn't ideal.
I started with
Omit<GlobalEventHandlers, 'onerror'>as an approach. However, I quickly realized it isn't the correct path and creates a whole slew of new problems due to how event handlers are mapped to different elements during the emit phase. (if you're curious to see what exactly I ran into, I can push up a separate PR).What this change does:
Introduces a new type
DocumentOrGlobalOnErrorEventHandlerwhich extends theOnErrorEventHandlerNonNulltype with HTMLElement specific handlers. This type then overrides GlobalEventHandlers onerror property. This allow us to be backwards compatible and fix the bug.This did require a change to both
types.tsandemitter.tsso that exposed was accounted for when creating a new typedef. I needed the newDocumentOrGlobalOnErrorEventHandlerto only be exposed on the dom library.The
onerrorofGlobalEventHandlerscannot be overridden by theoverrideType.tsfile. I tried to a few times, in both mixin-ins and interfaces. It turns out it has to be overidden in thepatches/events.kdlfile.Let me know if I missed anything or another approach would be better. I think this threads the needle nicely as it works only on dom elements and still provides both the global and HTMLElement specific onerror handling types.