UNPKG

@stencil/core

Version:

A Compiler for Web Components and Progressive Web Apps

311 lines (305 loc) • 10.8 kB
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 };