timepiece/node_modules/@lit-labs/ssr-dom-shim/index.js

124 lines
4.9 KiB
JavaScript

/**
* @license
* Copyright 2019 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
import { ElementInternalsShim } from './lib/element-internals.js';
export { ariaMixinAttributes, ElementInternals, HYDRATE_INTERNALS_ATTR_PREFIX, } from './lib/element-internals.js';
const attributes = new WeakMap();
const attributesForElement = (element) => {
let attrs = attributes.get(element);
if (attrs === undefined) {
attributes.set(element, (attrs = new Map()));
}
return attrs;
};
// The typings around the exports below are a little funky:
//
// 1. We want the `name` of the shim classes to match the real ones at runtime,
// hence e.g. `class Element`.
// 2. We can't shadow the global types with a simple class declaration, because
// then we can't reference the global types for casting, hence e.g.
// `const ElementShim = class Element`.
// 3. We want to export the classes typed as the real ones, hence e.g.
// `const ElementShimWithRealType = ElementShim as object as typeof Element;`.
// 4. We want the exported names to match the real ones, hence e.g.
// `export {ElementShimWithRealType as Element}`.
const ElementShim = class Element {
constructor() {
this.__shadowRootMode = null;
this.__shadowRoot = null;
this.__internals = null;
}
get attributes() {
return Array.from(attributesForElement(this)).map(([name, value]) => ({
name,
value,
}));
}
get shadowRoot() {
if (this.__shadowRootMode === 'closed') {
return null;
}
return this.__shadowRoot;
}
setAttribute(name, value) {
// Emulate browser behavior that silently casts all values to string. E.g.
// `42` becomes `"42"` and `{}` becomes `"[object Object]""`.
attributesForElement(this).set(name, String(value));
}
removeAttribute(name) {
attributesForElement(this).delete(name);
}
hasAttribute(name) {
return attributesForElement(this).has(name);
}
attachShadow(init) {
const shadowRoot = { host: this };
this.__shadowRootMode = init.mode;
if (init && init.mode === 'open') {
this.__shadowRoot = shadowRoot;
}
return shadowRoot;
}
attachInternals() {
if (this.__internals !== null) {
throw new Error(`Failed to execute 'attachInternals' on 'HTMLElement': ` +
`ElementInternals for the specified element was already attached.`);
}
const internals = new ElementInternalsShim(this);
this.__internals = internals;
return internals;
}
getAttribute(name) {
const value = attributesForElement(this).get(name);
return value ?? null;
}
};
const ElementShimWithRealType = ElementShim;
export { ElementShimWithRealType as Element };
const HTMLElementShim = class HTMLElement extends ElementShim {
};
const HTMLElementShimWithRealType = HTMLElementShim;
export { HTMLElementShimWithRealType as HTMLElement };
const CustomElementRegistryShim = class CustomElementRegistry {
constructor() {
this.__definitions = new Map();
}
define(name, ctor) {
if (this.__definitions.has(name)) {
if (process.env.NODE_ENV === 'development') {
console.warn(`'CustomElementRegistry' already has "${name}" defined. ` +
`This may have been caused by live reload or hot module ` +
`replacement in which case it can be safely ignored.\n` +
`Make sure to test your application with a production build as ` +
`repeat registrations will throw in production.`);
}
else {
throw new Error(`Failed to execute 'define' on 'CustomElementRegistry': ` +
`the name "${name}" has already been used with this registry`);
}
}
this.__definitions.set(name, {
ctor,
// Note it's important we read `observedAttributes` in case it is a getter
// with side-effects, as is the case in Lit, where it triggers class
// finalization.
//
// TODO(aomarks) To be spec compliant, we should also capture the
// registration-time lifecycle methods like `connectedCallback`. For them
// to be actually accessible to e.g. the Lit SSR element renderer, though,
// we'd need to introduce a new API for accessing them (since `get` only
// returns the constructor).
observedAttributes: ctor.observedAttributes ?? [],
});
}
get(name) {
const definition = this.__definitions.get(name);
return definition?.ctor;
}
};
const CustomElementRegistryShimWithRealType = CustomElementRegistryShim;
export { CustomElementRegistryShimWithRealType as CustomElementRegistry };
export const customElements = new CustomElementRegistryShimWithRealType();
//# sourceMappingURL=index.js.map