capricorn86 / happy-dom

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

document.createElement does not create SVGGraphicsElement #1079

Open runarberg opened 1 year ago

runarberg commented 1 year ago

Describe the bug

When you create an element with document.createElement or document.createElementNS it will incorrectly create some SVGGraphicsElements as SVGElements

To Reproduce Steps to reproduce the behavior:

const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");

rect.constructor.name
// SVGElement

rect instanceof SVGGraphicsElement
// false

Expected behavior

const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");

rect.constructor.name
// SVGRectElement

rect instanceof SVGGraphicsElement
// true
knownasilya commented 9 months ago

Also this:

const element = document.createElement('input');

element instanceof HTMLBodyElement;
// true
onx2 commented 2 months ago

This seems to be a problem in general. I tested a few different elements and it is giving me the similar incorrect results.

const element = document.createElement("span");
console.log(element instanceof HTMLBodyElement); // true
console.log(element instanceof HTMLDivElement); // true
const element = document.createElement("input");
console.log(element instanceof HTMLBodyElement); // true
console.log(element instanceof HTMLDivElement); // true
console.log(element instanceof HTMLSpanElement); // true
const element = document.createElement("div");
console.log(element instanceof HTMLBodyElement); // true
console.log(element instanceof HTMLSpanElement); // true

Output from normal browser env

image

I wonder if this is related? Perhaps because it is "unimplemented" but actually defined as HTMLElement is always equals true? https://github.com/capricorn86/happy-dom/blob/afd256b2e4f0260adb22432c1a354f558cda6623/packages/happy-dom/src/window/BrowserWindow.ts#L256

onx2 commented 2 months ago

I tested each unimplemented one and they all were true for span, div, input, ol, ul, li, and I'm sure others as well. So I think this is why @knownasilya

console.log(element instanceof HTMLHeadElement); // true
console.log(element instanceof HTMLTitleElement); // true
console.log(element instanceof HTMLBodyElement); // true
console.log(element instanceof HTMLHeadingElement); // true
console.log(element instanceof HTMLParagraphElement); // true
console.log(element instanceof HTMLHRElement); // true
console.log(element instanceof HTMLPreElement); // true
console.log(element instanceof HTMLUListElement); // true
console.log(element instanceof HTMLOListElement); // true
console.log(element instanceof HTMLMenuElement); // true
console.log(element instanceof HTMLDListElement); // true
console.log(element instanceof HTMLDivElement); // true
console.log(element instanceof HTMLAreaElement); // true
console.log(element instanceof HTMLBRElement); // true
console.log(element instanceof HTMLCanvasElement); // true
console.log(element instanceof HTMLDataElement); // true
console.log(element instanceof HTMLDataListElement); // true
console.log(element instanceof HTMLDetailsElement); // true
console.log(element instanceof HTMLDirectoryElement); // true
console.log(element instanceof HTMLFieldSetElement); // true
console.log(element instanceof HTMLFontElement); // true
console.log(element instanceof HTMLHtmlElement); // true
console.log(element instanceof HTMLLegendElement); // true
console.log(element instanceof HTMLMapElement); // true
console.log(element instanceof HTMLMarqueeElement); // true
console.log(element instanceof HTMLMeterElement); // true
console.log(element instanceof HTMLModElement); // true
console.log(element instanceof HTMLOutputElement); // true
console.log(element instanceof HTMLPictureElement); // true
console.log(element instanceof HTMLProgressElement); // true
console.log(element instanceof HTMLQuoteElement); // true
console.log(element instanceof HTMLSourceElement); // true
console.log(element instanceof HTMLSpanElement); // true
console.log(element instanceof HTMLTableCaptionElement); // true
console.log(element instanceof HTMLTableCellElement); // true
console.log(element instanceof HTMLTableColElement); // true
console.log(element instanceof HTMLTableElement); // true
console.log(element instanceof HTMLTableRowElement); // true
console.log(element instanceof HTMLTableSectionElement); // true
console.log(element instanceof HTMLFrameElement); // true
console.log(element instanceof HTMLFrameSetElement); // true
console.log(element instanceof HTMLEmbedElement); // true
console.log(element instanceof HTMLObjectElement); // true
console.log(element instanceof HTMLParamElement); // true
console.log(element instanceof HTMLTrackElement); // true
rijenkii commented 2 weeks ago

I guess this is in the same boat:

const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
const check = g instanceof SVGGElement;
// ReferenceError: SVGGElement is not defined (should be true)
const name = g.constructor.name;
// "SVGElement" (should be "SVGGElement")
onx2 commented 2 weeks ago

@rijenkii Probably so, but it looks like @capricorn86 is actively working on this issue (https://github.com/capricorn86/happy-dom/commit/1a0f2474dcc7a289509d76e78d93db2c56f1c8fb, https://github.com/capricorn86/happy-dom/commit/1ec0724e6687454e1fa4c732d512d8841e650d3e) 😄