-
Notifications
You must be signed in to change notification settings - Fork 421
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
cloneNode Return Type Must Be Active Class, Not Base Class (Node) #1723
base: main
Are you sure you want to change the base?
cloneNode Return Type Must Be Active Class, Not Base Class (Node) #1723
Conversation
The `cloneNode` return type is incorrect. The type before this change indicated that `cloneNode` returned a `Node`, which then broke any class that extended `Node`. In reality, `cloneNode` will return an instance of whatever the current class type is, a.k.a. `this` (`DocumentFragment#cloneNode` returns a `DocumentFragment`, not a `Node`).
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 comment has been minimized.
This comment has been minimized.
Have you read and fixed the issues from this item? |
@HolgerJeromin, I will test that later today. But that issue should be fixed as we aren't manually overriding each subclass'es |
Manual overridding was a workaround to reduce performance problem: #220 (comment) |
Ah, my mistake, @saschanaz. I missed that. If there's no possible workaround that is both performant and covariant, what is the project's focus, performance or accuracy? Making the change to |
You can run |
@saschanaz I took 50 samples before and after the change and averaged each sample set. Results
So it looks like an average total increase of 4 milliseconds on my system. MethodologyThe results were aggregated with some PowerShell. I ran the following script under the main branch, and then I changed Write-Output "Files,Lines,Identifiers,Symbols,Types,Instantiations,Memory used,I/O read,I/O write,Parse time,Bind time,Check time,Emit time,Total time" | Out-File -FilePath ..\before.csv; 1..50 | ForEach-Object { (npx tsc --diagnostics --lib es5 baselines/dom.generated.d.ts | ForEach-Object { ($_ -Split ':')[1].Trim() -ireplace '(s|k)' }) -Split "`n" -Join "," | Out-File -Append -FilePath ..\before.csv } |
@HolgerJeromin I did a little reproduction, and it looks like // Same type parameter as Tablesorter.
interface A<T = HTMLElement> {
x?: T;
}
type An<T = HTMLElement> = A<T>;
type ANode = A<Node>;
type AnElement = An<Element>;
type AnHTMLElement = An;
type AnHTMLAnchorElement = An<HTMLAnchorElement>;
let node: ANode = {};
let element: AnElement = {};
let htmlElement: AnHTMLElement = {};
let htmlAnchorElement: AnHTMLAnchorElement = {};
// All of the return types are correct!
let clonedNode: Node = node.x?.cloneNode()!;
let clonedElement: Element = element.x?.cloneNode()!;
let clonedHtmlElement: HTMLElement = htmlElement.x?.cloneNode()!;
let clonedHtmlAnchorElement: HTMLAnchorElement = htmlAnchorElement.x?.cloneNode()!;
htmlElement = htmlAnchorElement; // Covariance works! 👍🏻
htmlElement = element; // Contravariance doesn't work (as expected). |
@saschanaz Just wanted to follow up with a ping. This was my conclusion:
A 4 millisecond difference seems much more acceptable than the previous 700 millisecond difference. If you have any other concerns please let me know. |
I'm very happy to see work done on this and since it looks like perf impact is minimal, hope this will get merged soon. This would be a huge improvement for front end devs using typescript. |
The
cloneNode
return type is incorrect as per #283, #302, microsoft/TypeScript#17818 and #1578. The type before this PR indicated thatcloneNode
returned aNode
, which then broke any class that extendedNode
. In reality,cloneNode
will return an instance of whatever the current class type is, a.k.a.this
(DocumentFragment#cloneNode
returns aDocumentFragment
, not aNode
).This PR solves this issue by changing the return type of
Node#cloneNode
tothis
.