capricorn86 / happy-dom

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

attachInternals() does not exist. #957

Open loreanvictor opened 1 year ago

loreanvictor commented 1 year ago

Describe the bug The attachInternals() method does not exist on HTMLElement class.

To Reproduce Execute the following code (sandbox):

import { Window } from "happy-dom";

const window = new Window();

class MyEl extends window.HTMLElement {
  constructor() {
    super();
    this.attachInternals();
    this.root = this.attachShadow({ mode: "open" });
  }

  connectedCallback() {
    this.root.innerHTML = "<div>Hellow World</div>";
  }
}

window.document.write('<my-el name="world"></my-el>');
window.customElements.define("my-el", MyEl);

This is how browsers treat the same code.

Expected behavior That the attachInternals() method exists and behaves as specified here.

Additional Context This feature is needed for detecting when a custom element was pre-rendered with declarative shadow DOM, so without it basically there is no support for DSD.

This is the browser support for the feature. JSDOM also doesn't support the feature yet.

briandunn commented 7 months ago

I was able to get around this with a polyfill.

This is my vitest custom environment:

import { importModule } from "local-pkg";
import type { Environment } from "vitest";
import { builtinEnvironments } from "vitest/environments";

const happyDom = builtinEnvironments["happy-dom"];

// happy-dom is missing `attachInternals`
function polyfill() {
  importModule("@webcomponents/scoped-custom-element-registry");
}

export default <Environment>{
  ...happyDom,
  name: "hacky-dom",
  async setup(global, opts) {
    const teardown = await happyDom.setup(global, opts);
    polyfill();
    return teardown;
  }
}