@stencil/core
Version:
A Compiler for Web Components and Progressive Web Apps
311 lines (305 loc) • 10.8 kB
JavaScript
import { parsePropertyValue, getValue, setValue, connectedCallback, postUpdateComponent, insertVdomAnnotations } from '@stencil/core/runtime';
export * from '@stencil/core/runtime';
function proxyHostElement(elm, cmpMeta) {
if (typeof elm.componentOnReady !== 'function') {
elm.componentOnReady = componentOnReady;
}
if (typeof elm.forceUpdate !== 'function') {
elm.forceUpdate = forceUpdate;
}
if (cmpMeta.$members$ != null) {
const hostRef = getHostRef(elm);
const members = Object.entries(cmpMeta.$members$);
members.forEach(([memberName, m]) => {
const memberFlags = m[0];
if (memberFlags & 31) {
const attributeName = (m[1] || memberName);
const attrValue = elm.getAttribute(attributeName);
if (attrValue != null) {
const parsedAttrValue = parsePropertyValue(attrValue, memberFlags);
hostRef.$instanceValues$.set(memberName, parsedAttrValue);
}
const ownValue = elm[memberName];
if (ownValue !== undefined) {
hostRef.$instanceValues$.set(memberName, ownValue);
delete elm[memberName];
}
Object.defineProperty(elm, memberName, {
get() {
return getValue(this, memberName);
},
set(newValue) {
setValue(this, memberName, newValue, cmpMeta);
},
configurable: true,
enumerable: true
});
}
else if (memberFlags & 64) {
Object.defineProperty(elm, memberName, {
value() {
const ref = getHostRef(this);
const args = arguments;
return ref.$onReadyPromise$.then(() => ref.$lazyInstance$[memberName].apply(ref.$lazyInstance$, args)).catch(consoleError);
}
});
}
});
}
}
function componentOnReady() {
return getHostRef(this).$onReadyPromise$;
}
function forceUpdate() { }
function hydrateComponent(win, results, tagName, elm, waitPromises) {
const Cstr = getComponent(tagName);
if (Cstr != null) {
const cmpMeta = Cstr.cmpMeta;
if (cmpMeta != null) {
const hydratePromise = new Promise(async (resolve) => {
try {
registerHost(elm);
proxyHostElement(elm, cmpMeta);
connectedCallback(elm, cmpMeta);
await elm.componentOnReady();
results.hydratedCount++;
const ref = getHostRef(elm);
const modeName = !ref.$modeName$ ? '$' : ref.$modeName$;
if (!results.hydratedComponents.some(c => c.tag === tagName && c.mode === modeName)) {
results.hydratedComponents.push({
tag: tagName,
mode: modeName
});
}
}
catch (e) {
win.console.error(e);
}
resolve();
});
waitPromises.push(hydratePromise);
}
}
}
function bootstrapHydrate(win, opts, done) {
const results = {
hydratedCount: 0,
hydratedComponents: []
};
plt.$resourcesUrl$ = new URL(opts.resourcesUrl || '/', win.location.href).href;
try {
const connectedElements = new Set();
const waitPromises = [];
const patchedConnectedCallback = function patchedConnectedCallback() {
connectElements(win, opts, results, this, connectedElements, waitPromises);
};
const patchedComponentInit = function patchedComponentInit() {
const hostRef = getHostRef(this);
if (hostRef != null) {
postUpdateComponent(this, hostRef);
}
};
const patchComponent = function (elm) {
const tagName = elm.nodeName.toLowerCase();
if (elm.tagName.includes('-')) {
const Cstr = getComponent(tagName);
if (Cstr != null) {
if (typeof elm.connectedCallback !== 'function') {
elm.connectedCallback = patchedConnectedCallback;
}
if (typeof elm['s-init'] !== 'function') {
elm['s-rc'] = [];
elm['s-init'] = patchedComponentInit;
}
}
}
};
let orgDocumentCreateElement = win.document.createElement;
win.document.createElement = function patchedCreateElement(tagName) {
const elm = orgDocumentCreateElement.call(win.document, tagName);
patchComponent(elm);
return elm;
};
const patchChild = (elm) => {
if (elm != null && elm.nodeType === 1) {
patchComponent(elm);
const children = elm.children;
for (let i = 0, ii = children.length; i < ii; i++) {
patchChild(children[i]);
}
}
};
patchChild(win.document.body);
const initConnectElement = (elm) => {
if (elm != null && elm.nodeType === 1) {
if (typeof elm.connectedCallback === 'function') {
elm.connectedCallback();
}
const children = elm.children;
for (let i = 0, ii = children.length; i < ii; i++) {
initConnectElement(children[i]);
}
}
};
initConnectElement(win.document.body);
Promise.all(waitPromises)
.then(() => {
try {
waitPromises.length = 0;
connectedElements.clear();
if (opts.clientHydrateAnnotations) {
insertVdomAnnotations(win.document);
}
win.document.createElement = orgDocumentCreateElement;
win = opts = orgDocumentCreateElement = null;
}
catch (e) {
win.console.error(e);
}
done(results);
})
.catch(e => {
try {
win.console.error(e);
waitPromises.length = 0;
connectedElements.clear();
win.document.createElement = orgDocumentCreateElement;
win = opts = orgDocumentCreateElement = null;
}
catch (e) { }
done(results);
});
}
catch (e) {
win.console.error(e);
win = opts = null;
done(results);
}
}
function connectElements(win, opts, results, elm, connectedElements, waitPromises) {
if (elm != null && elm.nodeType === 1 && results.hydratedCount < opts.maxHydrateCount && shouldHydrate(elm)) {
const tagName = elm.nodeName.toLowerCase();
if (tagName.includes('-') && !connectedElements.has(elm)) {
connectedElements.add(elm);
hydrateComponent(win, results, tagName, elm, waitPromises);
}
const children = elm.children;
if (children != null) {
for (let i = 0, ii = children.length; i < ii; i++) {
connectElements(win, opts, results, children[i], connectedElements, waitPromises);
}
}
}
}
function shouldHydrate(elm) {
if (NO_HYDRATE_TAGS.has(elm.nodeName)) {
return false;
}
if (elm.hasAttribute('no-prerender')) {
return false;
}
const parentNode = elm.parentNode;
if (parentNode == null) {
return true;
}
return shouldHydrate(parentNode);
}
const NO_HYDRATE_TAGS = new Set([
'CODE',
'HEAD',
'IFRAME',
'INPUT',
'OBJECT',
'OUTPUT',
'NOSCRIPT',
'PRE',
'SCRIPT',
'SELECT',
'STYLE',
'TEMPLATE',
'TEXTAREA'
]);
const cstrs = new Map();
const loadModule = (cmpMeta, _hostRef, _hmrVersionId) => {
return new Promise(resolve => {
resolve(cstrs.get(cmpMeta.$tagName$));
});
};
const getComponent = (tagName) => {
return cstrs.get(tagName);
};
const isMemberInElement = (elm, memberName) => {
if (elm != null) {
if (memberName in elm) {
return true;
}
const hostRef = getComponent(elm.nodeName.toLowerCase());
if (hostRef != null && hostRef.cmpMeta != null && hostRef.cmpMeta.$members$ != null) {
return memberName in hostRef.cmpMeta.$members$;
}
}
return false;
};
const registerComponents = (Cstrs) => {
Cstrs.forEach(Cstr => {
cstrs.set(Cstr.cmpMeta.$tagName$, Cstr);
});
};
const win = window;
const doc = win.document;
const readTask = (cb) => {
process.nextTick(() => {
try {
cb();
}
catch (e) {
consoleError(e);
}
});
};
const writeTask = (cb) => {
process.nextTick(() => {
try {
cb();
}
catch (e) {
consoleError(e);
}
});
};
const nextTick = (cb) => Promise.resolve().then(cb);
const consoleError = (e) => {
if (e != null) {
console.error(e.stack || e.message || e);
}
};
const Context = {};
const plt = {
$flags$: 0,
$resourcesUrl$: '',
raf: (h) => requestAnimationFrame(h),
ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts),
rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts),
};
const supportsShadowDom = false;
const supportsListenerOptions = false;
const supportsConstructibleStylesheets = false;
const hostRefs = new WeakMap();
const getHostRef = (ref) => hostRefs.get(ref);
const registerInstance = (lazyInstance, hostRef) => hostRefs.set(hostRef.$lazyInstance$ = lazyInstance, hostRef);
const registerHost = (elm) => {
const hostRef = {
$flags$: 0,
$hostElement$: elm,
$instanceValues$: new Map(),
};
hostRef.$onReadyPromise$ = new Promise(r => hostRef.$onReadyResolve$ = r);
return hostRefs.set(elm, hostRef);
};
const Build = {
isDev: false,
isBrowser: false
};
const styles = new Map();
const cssVarShim = false;
export { Build, Context, bootstrapHydrate, consoleError, cssVarShim, doc, getComponent, getHostRef, isMemberInElement, loadModule, nextTick, plt, readTask, registerComponents, registerHost, registerInstance, styles, supportsConstructibleStylesheets, supportsListenerOptions, supportsShadowDom, win, writeTask };