capricorn86 / happy-dom

A JavaScript implementation of a web browser without its graphical user interface
MIT License
3.09k stars 185 forks source link

Unable to correctly `cloneNode` through `Node.prototype` #1392

Closed mcous closed 3 months ago

mcous commented 3 months ago

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.

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 happy-dom@14.7.0

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!

capricorn86 commented 3 months ago

Thank you for reporting @mcous! :slightly_smiling_face:

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