Skip to content

Commit

Permalink
[labs/ssr-dom-shim] Patch localName and tagName with customElements.d…
Browse files Browse the repository at this point in the history
…efine call (#4553)
  • Loading branch information
kyubisation committed Jun 9, 2024
1 parent 9217527 commit 65bc240
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/lovely-suits-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@lit-labs/ssr-dom-shim': patch
---

Implement Element.localName and Element.tagName. Fixes [3375](https://github.com/lit/lit/issues/3375).
13 changes: 13 additions & 0 deletions packages/labs/ssr-dom-shim/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ const ElementShim = class Element {
}
return this.__shadowRoot;
}
get localName() {
return (this.constructor as NamedCustomHTMLElementConstructor).__localName;
}
get tagName() {
return this.localName?.toUpperCase();
}
setAttribute(name: string, value: unknown): void {
// Emulate browser behavior that silently casts all values to string. E.g.
// `42` becomes `"42"` and `{}` becomes `"[object Object]""`.
Expand Down Expand Up @@ -123,6 +129,11 @@ interface CustomHTMLElementConstructor {
observedAttributes?: string[];
}

interface NamedCustomHTMLElementConstructor
extends CustomHTMLElementConstructor {
__localName: string;
}

type CustomElementRegistration = {
ctor: {new (): HTMLElement};
observedAttributes: string[];
Expand All @@ -148,6 +159,8 @@ const CustomElementRegistryShim = class CustomElementRegistry {
);
}
}
// Provide tagName and localName for the component.
(ctor as NamedCustomHTMLElementConstructor).__localName = name;
this.__definitions.set(name, {
ctor,
// Note it's important we read `observedAttributes` in case it is a getter
Expand Down
30 changes: 29 additions & 1 deletion packages/labs/ssr-dom-shim/src/test/element-shim_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import {suite} from 'uvu';
// eslint-disable-next-line import/extensions
import * as assert from 'uvu/assert';
import {HTMLElement} from '@lit-labs/ssr-dom-shim';
import {customElements, HTMLElement} from '@lit-labs/ssr-dom-shim';

const test = suite('Element Shim');

Expand Down Expand Up @@ -45,4 +45,32 @@ test('setAttribute silently casts values to a string', () => {
assert.equal(shimmedEl.getAttribute('tomato'), '[object Object]');
});

test('localName and tagName should be available with constructor from customElements registry', () => {
const elementName = 'lit-test-registry';
customElements.define(elementName, class extends HTMLElement {});
const LitTestRegistry = customElements.get(elementName)!;

const shimmedEl = new LitTestRegistry();
assert.equal(shimmedEl.localName, elementName);
assert.equal(shimmedEl.tagName, elementName.toUpperCase());
});

test('localName and tagName should be available when registering with customElements', () => {
const elementName = 'lit-test-local';
class LitTestLocal extends HTMLElement {}
customElements.define(elementName, LitTestLocal);

const shimmedEl = new LitTestLocal();
assert.equal(shimmedEl.localName, elementName);
assert.equal(shimmedEl.tagName, elementName.toUpperCase());
});

test('localName and tagName usage should return undefined if not registered', () => {
class LitTestUnregistered extends HTMLElement {}

const shimmedEl = new LitTestUnregistered();
assert.equal(shimmedEl.localName, undefined);
assert.equal(shimmedEl.tagName, undefined);
});

test.run();

0 comments on commit 65bc240

Please sign in to comment.