Skip to content

Commit

Permalink
fix(scoped-elements): support lit2 elements (using ce registry polyfill)
Browse files Browse the repository at this point in the history
  • Loading branch information
tlouisse authored and daKmoR committed Jul 19, 2021
1 parent d8ecda8 commit 407c935
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/friendly-elephants-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@open-wc/scoped-elements': patch
---

support lit2 elements (using scoped-custom-element-registry) in ScopedElementsMixin v1
24 changes: 20 additions & 4 deletions packages/scoped-elements/src/registerElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,28 @@ import { createUniqueTag } from './createUniqueTag.js';
import { getFromGlobalTagsCache, addToGlobalTagsCache } from './globalTagsCache.js';

/**
* Checks if klass is a subclass of HTMLElement
*
* @param {typeof HTMLElement} klass
* Checks if klass is a subclass of native HTMLElement or polyfilled HTMLElement.
* We manually loop over the prototpe, so we can detect if we extend from native HTMLElement
* or the polyfilled one from scoped-custom-element-registry (window.HTMLElement)
* @param {typeof HTMLElement} klass a class, like LitElement
* @returns {boolean}
*/
const extendsHTMLElement = klass => Object.prototype.isPrototypeOf.call(HTMLElement, klass);
function extendsHTMLElement(klass) {
let currentClass = klass;
while (currentClass) {
// currentClass could either be:
// 1. unpatched, native HTMLElement (when polyfill not loaded this is always the case), or:
// 2. patched window.HTMLElement (can be the case when polyfill is loaded)
// If polyfill is loaded and currentClass is the native HTMLElement, we don't have a
// reference to it (polyfill calls it NativeHTMLElement, but doesn't expose it),
// so we check its name.
if (currentClass === window.HTMLElement || currentClass.name === 'HTMLElement') {
return true;
}
currentClass = Object.getPrototypeOf(currentClass);
}
return false;
}

/**
* Defines a custom element
Expand Down
27 changes: 27 additions & 0 deletions packages/scoped-elements/test-web/registerElement.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { expect, fixture } from '@open-wc/testing';
import { registerElement, defineScopedElement } from '../src/registerElement.js';
import { Cache } from '../src/Cache.js';

const NativeHTMLElement = window.HTMLElement;
function mimicScopedRegistryPolyFill() {
window.HTMLElement = function HTMLElement() {};
window.HTMLElement.prototype = NativeHTMLElement.prototype;
}
function restoreMimicScopedRegistryPolyFill() {
window.HTMLElement = NativeHTMLElement;
}

class Naboo extends HTMLElement {}

Expand All @@ -13,6 +23,23 @@ describe('registerElement', () => {
it('should throw an error with lazy components and no tags cache', () => {
expect(() => registerElement('naboo-planet', undefined)).to.throw();
});

it('should work when window.HTMLElement is polyfilled and native HTMLElement is provided', () => {
class Unpatched extends window.HTMLElement {}
mimicScopedRegistryPolyFill();
class Patched extends window.HTMLElement {}

const cache = new Cache();
registerElement('wc-unpatched', Unpatched, cache);
registerElement('wc-patched', Patched, cache);

// When the elements above would not extend HTMLElement (native or patched), they
// would be added to cache inside "storeLazyElementInCache" method.
// So cache should still be empty:
expect(cache._cache.size).to.equal(0);

restoreMimicScopedRegistryPolyFill();
});
});

describe('defineScopedElement', () => {
Expand Down

0 comments on commit 407c935

Please sign in to comment.