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

Unable to correctly cloneNode through Node.prototype #1392

Closed
mcous opened this issue Apr 7, 2024 · 1 comment · Fixed by #1393
Closed

Unable to correctly cloneNode through Node.prototype #1392

mcous opened this issue Apr 7, 2024 · 1 comment · Fixed by #1393
Labels
bug Something isn't working

Comments

@mcous
Copy link

mcous commented Apr 7, 2024

Describe the bug

Hello again! My last experience filing a bug was so good I thought I'd do another one 😄

The upcoming Svelte v5 calls various Node and Element methods through their prototypes to "avoid doing expensive prototype chain lookups."

node_prototype = Node.prototype;
// ...
clone_node_method = node_prototype.cloneNode;
// ...
export function clone_node(node, deep) {
	return clone_node_method.call(node, deep);
}

This works fine in the browser, but in happy-dom, due to (if I'm reading the code correctly) how subclasses of Node override cloneNode, Svelte v5 fails to properly clone nodes. This is problematic, because cloneNode is used to initially mount components into the DOM.

Svelte calls the following methods through the prototype. From a quick scan of the code, I think cloneNode is the only problematic one, but I'd want to verify through tests.

  • Node.prototype.cloneNode - Does not work
  • Node.prototype.appendChild - Looks ok
  • Node.prototype.firstChild - Looks ok
  • Node.prototype.nextSibling - Looks ok
  • Element.prototype.className - Looks ok

Related to:

To Reproduce

An easy way to see how things get messed up is to check the tagName of a cloned node. If you use Node.prototype.cloneNode.call, the clone will have a tagName of null, which will break other things internally to happy-dom and downstream.

// index.js
import { Window } from "happy-dom";

const window = new Window({ url: "http://localhost:3000" });
const document = window.document;
const cloneNode = window.Node.prototype.cloneNode;

const element = document.createElement("div");
const clone = element.cloneNode();
const prototypeClone = cloneNode.call(element);

console.log("clone", clone.tagName);
console.log("prototypeClone", prototypeClone.tagName);
> node index.js
clone1 DIV
clone2 null

Expected behavior

I expect the various Node.prototype methods, such as cloneNode, to fully work on all node types, as they do in the browser.

Additional context

Tested on [email protected]

This issue has already been reported as a feature request in #1165, but I felt it was important to highlight as a bug, because it is a material difference in how happy-dom behaves vs the browser. Feel free to close out as a duplicate if you feel this is already adequately tracked!

@mcous mcous added the bug Something isn't working label Apr 7, 2024
capricorn86 added a commit that referenced this issue Apr 7, 2024
…ment), Node.prototype.appendChild.call(element), Node.prototype.removeChild.call(element), Node.prototype.insertBefore.call(element) and Node.prototype.replaceChild.call(element)
capricorn86 added a commit that referenced this issue Apr 7, 2024
…onenode-through-nodeprototype

fix: [#1392] Adds support for using Node.prototype.cloneNode.call(ele…
@capricorn86
Copy link
Owner

capricorn86 commented Apr 7, 2024

Thank you for reporting @mcous! 🙂

The problem has been fixed now:
https://github.com/capricorn86/happy-dom/releases/tag/v14.7.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants