fix(scoped-elements): define unused lazy scoped elements

This commit is contained in:
Manuel Martin
2020-04-01 10:37:29 +02:00
committed by Lars den Bakker
parent 4ac8a8501f
commit 5b863a2bba
3 changed files with 88 additions and 13 deletions

View File

@@ -17,6 +17,19 @@ import { shadyTemplateFactory } from './shadyTemplateFactory.js';
*/
const templateCaches = new WeakMap();
/**
* Retrieves or creates a templateCache for a specific key
* @param {Function} key
* @returns {Map<TemplateStringsArray, TemplateStringsArray>}
*/
const getTemplateCache = key => {
if (!templateCaches.has(key)) {
templateCaches.set(key, new Map());
}
return templateCaches.get(key);
};
/**
* Tags caches
*
@@ -24,6 +37,19 @@ const templateCaches = new WeakMap();
*/
const tagsCaches = new WeakMap();
/**
* Retrieves or creates a tagsCache for a specific key
* @param {object} key
* @returns {Map<string, string>}
*/
const getTagsCache = key => {
if (!tagsCaches.has(key)) {
tagsCaches.set(key, new Map());
}
return tagsCaches.get(key);
};
/**
* Transforms an array of TemplateResults or arrays into another one with resolved scoped elements
*
@@ -91,15 +117,8 @@ export const ScopedElementsMixin = dedupeMixin(
}
const { scopeName } = options;
if (!templateCaches.has(this)) {
templateCaches.set(this, new Map());
}
if (!tagsCaches.has(this)) {
tagsCaches.set(this, new Map());
}
const templateCache = templateCaches.get(this);
const tagsCache = tagsCaches.get(this);
const templateCache = getTemplateCache(this);
const tagsCache = getTagsCache(this);
const { scopedElements } = this;
// @ts-ignore
@@ -121,7 +140,7 @@ export const ScopedElementsMixin = dedupeMixin(
* @param {typeof HTMLElement} klass
*/
defineScopedElement(tagName, klass) {
return defineScopedElement(tagName, klass, tagsCaches.get(this.constructor));
return defineScopedElement(tagName, klass, getTagsCache(this.constructor));
}
/**
@@ -134,8 +153,8 @@ export const ScopedElementsMixin = dedupeMixin(
const klass = this.scopedElements[tagName];
return klass
? registerElement(tagName, klass, tagsCaches.get(this))
: tagsCaches.get(this).get(tagName);
? registerElement(tagName, klass, getTagsCache(this))
: getTagsCache(this).get(tagName);
}
},
);

View File

@@ -76,5 +76,9 @@ export function registerElement(tagName, klass, tagsCache = undefined) {
export function defineScopedElement(tagName, klass, tagsCache) {
const tag = tagsCache.get(tagName);
defineElement(tag, klass, customElements);
if (tag) {
defineElement(tag, klass, customElements);
} else {
tagsCache.set(tagName, registerElement(tagName, klass, tagsCache));
}
}

View File

@@ -294,6 +294,58 @@ describe('ScopedElementsMixin', () => {
expect(el.shadowRoot.children[1]).to.be.an.instanceOf(FeatureB);
});
it("support define a lazy element even if it's not used in previous templates", async () => {
class LazyElement extends LitElement {
render() {
return html`
<div>Lazy element</div>
`;
}
}
const tag = defineCE(
class extends ScopedElementsMixin(LitElement) {
static get scopedElements() {
return {
'feature-a': FeatureA,
};
}
constructor() {
super();
const defineScopedElement = this.defineScopedElement.bind(this);
this.loading = new Promise(resolve => {
defineScopedElement('lazy-element', LazyElement);
resolve(
html`
<lazy-element></lazy-element>
`,
);
});
}
render() {
return html`
<feature-a></feature-a>
${until(
this.loading,
html`
<div>Loading...</div>
`,
)}
`;
}
},
);
const el = await fixture(`<${tag}></${tag}>`);
await waitUntil(() => el.shadowRoot.children[1] instanceof LazyElement);
});
describe('getScopedTagName', () => {
it('should return the scoped tag name for a registered element', async () => {
const chars = `-|\\.|[0-9]|[a-z]`;