capricorn86 / happy-dom

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

Fix: Fragile cloneNode implementation #1284

Closed itutto closed 7 months ago

itutto commented 8 months ago

Fixes break of immediate attributeChanged callback when using cloneNode.

Sample to recreate the issue

// sample.mjs
import * as happyDom from 'happy-dom';

const win = new happyDom.Window();
const doc = win.document;

class Test extends win.HTMLElement {
    attributeChangedCallback() {
        // This will fail because the cloned element does not have a tagname (yet).
        this.querySelectorAll('label');
        /**
         * SelectorItem.js:42
            if (this.tagName !== '*' && this.tagName !== element[PropertySymbol.tagName].toUpperCase()) {
         */
    }
}
Test.observedAttributes = ['my-test'];

win.customElements.define('x-test',Test);

const template = doc.createElement('template');
template.innerHTML = `<template><x-test my-test="fail"></x-test></template>`;
template.content.cloneNode(true)

Run

node sample.mjs

What is the fix?

I propose to move the tagName, localName and namespaceUri initialization before the attribute clone.