vendor: 1,464 bytes, lines 1-59
1const NAMESPACE = 'promotion-offer'; 2 3/** 4 * Virtual DOM patching algorithm based on Snabbdom by 5 * Simon Friis Vindum (@paldepind) 6 * Licensed under the MIT License 7 * https://github.com/snabbdom/snabbdom/blob/master/LICENSE 8 * 9 * Modified for Stencil's renderer and slot projection 10 */ 11let scopeId; 12let contentRef; 13let hostTagName; 14let useNativeShadowDom = false; 15let checkSlotFallbackVisibility = false; 16let checkSlotRelocate = false; 17let isSvgMode = false; 18let queuePending = false; 19const getAssetPath = (path) => { 20 const assetUrl = new URL(path, plt.$resourcesUrl$); 21 return assetUrl.origin !== win.location.origin ? assetUrl.href : assetUrl.pathname; 22}; 23const createTime = (fnName, tagName = '') => { 24 { 25 return () => { 26 return; 27 }; 28 } 29}; 30const uniqueTime = (key, measureText) => { 31 { 32 return () => { 33 return; 34 }; 35 } 36}; 37const HYDRATED_CSS = '{visibility:hidden}.hydrated{visibility:inherit}'; 38const XLINK_NS = 'http://www.w3.org/1999/xlink'; 39/** 40 * Default style mode id 41 */ 42/** 43 * Reusable empty obj/array 44 * Don't add values to these!! 45 */ 46const EMPTY_OBJ = {}; 47/** 48 * Namespaces 49 */ 50const SVG_NS = 'http://www.w3.org/2000/svg'; 51const HTML_NS = 'http://www.w3.org/1999/xhtml'; 52const isDef = (v) => v != null; 53/** 54 * Check whether a value is a 'complex type', defined here as an object or a 55 * function. 56 * 57 * @param o the value to check 58 * @returns whether it's a complex type or not 59 */
vendor: 4,447 bytes, lines 59-197
59 60const isComplexType = (o) => { 61 // https://jsperf.com/typeof-fn-object/5 62 o = typeof o; 63 return o === 'object' || o === 'function'; 64}; 65/** 66 * Helper method for querying a `meta` tag that contains a nonce value 67 * out of a DOM's head. 68 * 69 * @param doc The DOM containing the `head` to query against 70 * @returns The content of the meta tag representing the nonce value, or `undefined` if no tag 71 * exists or the tag has no content. 72 */ 73function queryNonceMetaTagContent(doc) { 74 var _a, _b, _c; 75 return (_c = (_b = (_a = doc.head) === null || _a === void 0 ? void 0 : _a.querySelector('meta[name="csp-nonce"]')) === null || _b === void 0 ? void 0 : _b.getAttribute('content')) !== null && _c !== void 0 ? _c : undefined; 76} 77/** 78 * Production h() function based on Preact by 79 * Jason Miller (@developit) 80 * Licensed under the MIT License 81 * https://github.com/developit/preact/blob/master/LICENSE 82 * 83 * Modified for Stencil's compiler and vdom 84 */ 85// export function h(nodeName: string | d.FunctionalComponent, vnodeData: d.PropsType, child?: d.ChildType): d.VNode; 86// export function h(nodeName: string | d.FunctionalComponent, vnodeData: d.PropsType, ...children: d.ChildType[]): d.VNode; 87const h = (nodeName, vnodeData, ...children) => { 88 let child = null; 89 let key = null; 90 let slotName = null; 91 let simple = false; 92 let lastSimple = false; 93 const vNodeChildren = []; 94 const walk = (c) => { 95 for (let i = 0; i < c.length; i++) { 96 child = c[i]; 97 if (Array.isArray(child)) { 98 walk(child); 99 } 100 else if (child != null && typeof child !== 'boolean') { 101 if ((simple = typeof nodeName !== 'function' && !isComplexType(child))) { 102 child = String(child); 103 } 104 if (simple && lastSimple) { 105 // If the previous child was simple (string), we merge both 106 vNodeChildren[vNodeChildren.length - 1].$text$ += child; 107 } 108 else { 109 // Append a new vNode, if it's text, we create a text vNode 110 vNodeChildren.push(simple ? newVNode(null, child) : child); 111 } 112 lastSimple = simple; 113 } 114 } 115 }; 116 walk(children); 117 if (vnodeData) { 118 // normalize class / classname attributes 119 if (vnodeData.key) { 120 key = vnodeData.key; 121 } 122 if (vnodeData.name) { 123 slotName = vnodeData.name; 124 } 125 { 126 const classData = vnodeData.className || vnodeData.class; 127 if (classData) { 128 vnodeData.class = 129 typeof classData !== 'object' 130 ? classData 131 : Object.keys(classData) 132 .filter((k) => classData[k]) 133 .join(' '); 134 } 135 } 136 } 137 if (typeof nodeName === 'function') { 138 // nodeName is a functional component 139 return nodeName(vnodeData === null ? {} : vnodeData, vNodeChildren, vdomFnUtils); 140 } 141 const vnode = newVNode(nodeName, null); 142 vnode.$attrs$ = vnodeData; 143 if (vNodeChildren.length > 0) { 144 vnode.$children$ = vNodeChildren; 145 } 146 { 147 vnode.$key$ = key; 148 } 149 { 150 vnode.$name$ = slotName; 151 } 152 return vnode; 153}; 154/** 155 * A utility function for creating a virtual DOM node from a tag and some 156 * possible text content. 157 * 158 * @param tag the tag for this element 159 * @param text possible text content for the node 160 * @returns a newly-minted virtual DOM node 161 */ 162const newVNode = (tag, text) => { 163 const vnode = { 164 $flags$: 0, 165 $tag$: tag, 166 $text$: text, 167 $elm$: null, 168 $children$: null, 169 }; 170 { 171 vnode.$attrs$ = null; 172 } 173 { 174 vnode.$key$ = null; 175 } 176 { 177 vnode.$name$ = null; 178 } 179 return vnode; 180}; 181const Host = {}; 182/** 183 * Check whether a given node is a Host node or not 184 * 185 * @param node the virtual DOM node to check 186 * @returns whether it's a Host node or not 187 */ 188const isHost = (node) => node && node.$tag$ === Host; 189/** 190 * Implementation of {@link d.FunctionalUtilities} for Stencil's VDom. 191 * 192 * Note that these functions convert from {@link d.VNode} to 193 * {@link d.ChildNode} to give functional component developers a friendly 194 * interface. 195 */ 196const vdomFnUtils = { 197 forEach: (children, cb) =>
vendor: 6,497 bytes, lines 197-358
197 children.map(convertToPublic).forEach(cb), 198 map: (children, cb) => children.map(convertToPublic).map(cb).map(convertToPrivate), 199}; 200/** 201 * Convert a {@link d.VNode} to a {@link d.ChildNode} in order to present a 202 * friendlier public interface (hence, 'convertToPublic'). 203 * 204 * @param node the virtual DOM node to convert 205 * @returns a converted child node 206 */ 207const convertToPublic = (node) => ({ 208 vattrs: node.$attrs$, 209 vchildren: node.$children$, 210 vkey: node.$key$, 211 vname: node.$name$, 212 vtag: node.$tag$, 213 vtext: node.$text$, 214}); 215/** 216 * Convert a {@link d.ChildNode} back to an equivalent {@link d.VNode} in 217 * order to use the resulting object in the virtual DOM. The initial object was 218 * likely created as part of presenting a public API, so converting it back 219 * involved making it 'private' again (hence, `convertToPrivate`). 220 * 221 * @param node the child node to convert 222 * @returns a converted virtual DOM node 223 */ 224const convertToPrivate = (node) => { 225 if (typeof node.vtag === 'function') { 226 const vnodeData = Object.assign({}, node.vattrs); 227 if (node.vkey) { 228 vnodeData.key = node.vkey; 229 } 230 if (node.vname) { 231 vnodeData.name = node.vname; 232 } 233 return h(node.vtag, vnodeData, ...(node.vchildren || [])); 234 } 235 const vnode = newVNode(node.vtag, node.vtext); 236 vnode.$attrs$ = node.vattrs; 237 vnode.$children$ = node.vchildren; 238 vnode.$key$ = node.vkey; 239 vnode.$name$ = node.vname; 240 return vnode; 241}; 242/** 243 * Parse a new property value for a given property type. 244 * 245 * While the prop value can reasonably be expected to be of `any` type as far as TypeScript's type checker is concerned, 246 * it is not safe to assume that the string returned by evaluating `typeof propValue` matches: 247 * 1. `any`, the type given to `propValue` in the function signature 248 * 2. the type stored from `propType`. 249 * 250 * This function provides the capability to parse/coerce a property's value to potentially any other JavaScript type. 251 * 252 * Property values represented in TSX preserve their type information. In the example below, the number 0 is passed to 253 * a component. This `propValue` will preserve its type information (`typeof propValue === 'number'`). Note that is 254 * based on the type of the value being passed in, not the type declared of the class member decorated with `@Prop`. 255 * ```tsx 256 * <my-cmp prop-val={0}></my-cmp> 257 * ``` 258 * 259 * HTML prop values on the other hand, will always a string 260 * 261 * @param propValue the new value to coerce to some type 262 * @param propType the type of the prop, expressed as a binary number 263 * @returns the parsed/coerced value 264 */ 265const parsePropertyValue = (propValue, propType) => { 266 // ensure this value is of the correct prop type 267 if (propValue != null && !isComplexType(propValue)) { 268 if (propType & 4 /* MEMBER_FLAGS.Boolean */) { 269 // per the HTML spec, any string value means it is a boolean true value 270 // but we'll cheat here and say that the string "false" is the boolean false 271 return propValue === 'false' ? false : propValue === '' || !!propValue; 272 } 273 if (propType & 2 /* MEMBER_FLAGS.Number */) { 274 // force it to be a number 275 return parseFloat(propValue); 276 } 277 if (propType & 1 /* MEMBER_FLAGS.String */) { 278 // could have been passed as a number or boolean 279 // but we still want it as a string 280 return String(propValue); 281 } 282 // redundant return here for better minification 283 return propValue; 284 } 285 // not sure exactly what type we want 286 // so no need to change to a different type 287 return propValue; 288}; 289const getElement = (ref) => (getHostRef(ref).$hostElement$ ); 290const createEvent = (ref, name, flags) => { 291 const elm = getElement(ref); 292 return { 293 emit: (detail) => { 294 return emitEvent(elm, name, { 295 bubbles: !!(flags & 4 /* EVENT_FLAGS.Bubbles */), 296 composed: !!(flags & 2 /* EVENT_FLAGS.Composed */), 297 cancelable: !!(flags & 1 /* EVENT_FLAGS.Cancellable */), 298 detail, 299 }); 300 }, 301 }; 302}; 303/** 304 * Helper function to create & dispatch a custom Event on a provided target 305 * @param elm the target of the Event 306 * @param name the name to give the custom Event 307 * @param opts options for configuring a custom Event 308 * @returns the custom Event 309 */ 310const emitEvent = (elm, name, opts) => { 311 const ev = plt.ce(name, opts); 312 elm.dispatchEvent(ev); 313 return ev; 314}; 315const rootAppliedStyles = /*@__PURE__*/ new WeakMap(); 316const registerStyle = (scopeId, cssText, allowCS) => { 317 let style = styles.get(scopeId); 318 if (supportsConstructableStylesheets && allowCS) { 319 style = (style || new CSSStyleSheet()); 320 if (typeof style === 'string') { 321 style = cssText; 322 } 323 else { 324 style.replaceSync(cssText); 325 } 326 } 327 else { 328 style = cssText; 329 } 330 styles.set(scopeId, style); 331}; 332const addStyle = (styleContainerNode, cmpMeta, mode) => { 333 var _a; 334 const scopeId = getScopeId(cmpMeta); 335 const style = styles.get(scopeId); 336 // if an element is NOT connected then getRootNode() will return the wrong root node 337 // so the fallback is to always use the document for the root node in those cases 338 styleContainerNode = styleContainerNode.nodeType === 11 /* NODE_TYPE.DocumentFragment */ ? styleContainerNode : doc; 339 if (style) { 340 if (typeof style === 'string') { 341 styleContainerNode = styleContainerNode.head || styleContainerNode; 342 let appliedStyles = rootAppliedStyles.get(styleContainerNode); 343 let styleElm; 344 if (!appliedStyles) { 345 rootAppliedStyles.set(styleContainerNode, (appliedStyles = new Set())); 346 } 347 if (!appliedStyles.has(scopeId)) { 348 { 349 styleElm = doc.createElement('style'); 350 styleElm.innerHTML = style; 351 // Apply CSP nonce to the style tag if it exists 352 const nonce = (_a = plt.$nonce$) !== null && _a !== void 0 ? _a : queryNonceMetaTagContent(doc); 353 if (nonce != null) { 354 styleElm.setAttribute('nonce', nonce); 355 } 356 styleContainerNode.insertBefore(styleElm, styleContainerNode.querySelector('link')); 357 } 358
vendor: 2,231 bytes, lines 358-413
358if (appliedStyles) { 359 appliedStyles.add(scopeId); 360 } 361 } 362 } 363 else if (!styleContainerNode.adoptedStyleSheets.includes(style)) { 364 styleContainerNode.adoptedStyleSheets = [...styleContainerNode.adoptedStyleSheets, style]; 365 } 366 } 367 return scopeId; 368}; 369const attachStyles = (hostRef) => { 370 const cmpMeta = hostRef.$cmpMeta$; 371 const elm = hostRef.$hostElement$; 372 const flags = cmpMeta.$flags$; 373 const endAttachStyles = createTime('attachStyles', cmpMeta.$tagName$); 374 const scopeId = addStyle(elm.getRootNode(), cmpMeta); 375 if (flags & 10 /* CMP_FLAGS.needsScopedEncapsulation */) { 376 // only required when we're NOT using native shadow dom (slot) 377 // or this browser doesn't support native shadow dom 378 // and this host element was NOT created with SSR 379 // let's pick out the inner content for slot projection 380 // create a node to represent where the original 381 // content was first placed, which is useful later on 382 // DOM WRITE!! 383 elm['s-sc'] = scopeId; 384 elm.classList.add(scopeId + '-h'); 385 if (flags & 2 /* CMP_FLAGS.scopedCssEncapsulation */) { 386 elm.classList.add(scopeId + '-s'); 387 } 388 } 389 endAttachStyles(); 390}; 391const getScopeId = (cmp, mode) => 'sc-' + (cmp.$tagName$); 392/** 393 * Production setAccessor() function based on Preact by 394 * Jason Miller (@developit) 395 * Licensed under the MIT License 396 * https://github.com/developit/preact/blob/master/LICENSE 397 * 398 * Modified for Stencil's compiler and vdom 399 */ 400/** 401 * When running a VDom render set properties present on a VDom node onto the 402 * corresponding HTML element. 403 * 404 * Note that this function has special functionality for the `class`, 405 * `style`, `key`, and `ref` attributes, as well as event handlers (like 406 * `onClick`, etc). All others are just passed through as-is. 407 * 408 * @param elm the HTMLElement onto which attributes should be set 409 * @param memberName the name of the attribute to set 410 * @param oldValue the old value for the attribute 411 * @param newValue the new value for the attribute 412 * @param isSvg whether we're in an svg context or not 413 * @param flags bitflags for Vdom variables
vendor: 6,812 bytes, lines 413-569
413 414 */ 415const setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags) => { 416 if (oldValue !== newValue) { 417 let isProp = isMemberInElement(elm, memberName); 418 let ln = memberName.toLowerCase(); 419 if (memberName === 'class') { 420 const classList = elm.classList; 421 const oldClasses = parseClassList(oldValue); 422 const newClasses = parseClassList(newValue); 423 classList.remove(...oldClasses.filter((c) => c && !newClasses.includes(c))); 424 classList.add(...newClasses.filter((c) => c && !oldClasses.includes(c))); 425 } 426 else if (memberName === 'style') { 427 // update style attribute, css properties and values 428 { 429 for (const prop in oldValue) { 430 if (!newValue || newValue[prop] == null) { 431 if (prop.includes('-')) { 432 elm.style.removeProperty(prop); 433 } 434 else { 435 elm.style[prop] = ''; 436 } 437 } 438 } 439 } 440 for (const prop in newValue) { 441 if (!oldValue || newValue[prop] !== oldValue[prop]) { 442 if (prop.includes('-')) { 443 elm.style.setProperty(prop, newValue[prop]); 444 } 445 else { 446 elm.style[prop] = newValue[prop]; 447 } 448 } 449 } 450 } 451 else if (memberName === 'key') 452 ; 453 else if (memberName === 'ref') { 454 // minifier will clean this up 455 if (newValue) { 456 newValue(elm); 457 } 458 } 459 else if ((!isProp ) && 460 memberName[0] === 'o' && 461 memberName[1] === 'n') { 462 // Event Handlers 463 // so if the member name starts with "on" and the 3rd characters is 464 // a capital letter, and it's not already a member on the element, 465 // then we're assuming it's an event listener 466 if (memberName[2] === '-') { 467 // on- prefixed events 468 // allows to be explicit about the dom event to listen without any magic 469 // under the hood: 470 // <my-cmp on-click> // listens for "click" 471 // <my-cmp on-Click> // listens for "Click" 472 // <my-cmp on-ionChange> // listens for "ionChange" 473 // <my-cmp on-EVENTS> // listens for "EVENTS" 474 memberName = memberName.slice(3); 475 } 476 else if (isMemberInElement(win, ln)) { 477 // standard event 478 // the JSX attribute could have been "onMouseOver" and the 479 // member name "onmouseover" is on the window's prototype 480 // so let's add the listener "mouseover", which is all lowercased 481 memberName = ln.slice(2); 482 } 483 else { 484 // custom event 485 // the JSX attribute could have been "onMyCustomEvent" 486 // so let's trim off the "on" prefix and lowercase the first character 487 // and add the listener "myCustomEvent" 488 // except for the first character, we keep the event name case 489 memberName = ln[2] + memberName.slice(3); 490 } 491 if (oldValue) { 492 plt.rel(elm, memberName, oldValue, false); 493 } 494 if (newValue) { 495 plt.ael(elm, memberName, newValue, false); 496 } 497 } 498 else { 499 // Set property if it exists and it's not a SVG 500 const isComplex = isComplexType(newValue); 501 if ((isProp || (isComplex && newValue !== null)) && !isSvg) { 502 try { 503 if (!elm.tagName.includes('-')) { 504 const n = newValue == null ? '' : newValue; 505 // Workaround for Safari, moving the <input> caret when re-assigning the same valued 506 if (memberName === 'list') { 507 isProp = false; 508 } 509 else if (oldValue == null || elm[memberName] != n) { 510 elm[memberName] = n; 511 } 512 } 513 else { 514 elm[memberName] = newValue; 515 } 516 } 517 catch (e) { } 518 } 519 /** 520 * Need to manually update attribute if: 521 * - memberName is not an attribute 522 * - if we are rendering the host element in order to reflect attribute 523 * - if it's a SVG, since properties might not work in <svg> 524 * - if the newValue is null/undefined or 'false'. 525 */ 526 let xlink = false; 527 { 528 if (ln !== (ln = ln.replace(/^xlink\:?/, ''))) { 529 memberName = ln; 530 xlink = true; 531 } 532 } 533 if (newValue == null || newValue === false) { 534 if (newValue !== false || elm.getAttribute(memberName) === '') { 535 if (xlink) { 536 elm.removeAttributeNS(XLINK_NS, memberName); 537 } 538 else { 539 elm.removeAttribute(memberName); 540 } 541 } 542 } 543 else if ((!isProp || flags & 4 /* VNODE_FLAGS.isHost */ || isSvg) && !isComplex) { 544 newValue = newValue === true ? '' : newValue; 545 if (xlink) { 546 elm.setAttributeNS(XLINK_NS, memberName, newValue); 547 } 548 else { 549 elm.setAttribute(memberName, newValue); 550 } 551 } 552 } 553 } 554}; 555const parseClassListRegex = /\s/; 556const parseClassList = (value) => (!value ? [] : value.split(parseClassListRegex)); 557const updateElement = (oldVnode, newVnode, isSvgMode, memberName) => { 558 // if the element passed in is a shadow root, which is a document fragment 559 // then we want to be adding attrs/props to the shadow root's "host" element 560 // if it's not a shadow root, then we add attrs/props to the same element 561 const elm = newVnode.$elm$.nodeType === 11 /* NODE_TYPE.DocumentFragment */ && newVnode.$elm$.host 562 ? newVnode.$elm$.host 563 : newVnode.$elm$; 564 const oldVnodeAttrs = (oldVnode && oldVnode.$attrs$) || EMPTY_OBJ; 565 const newVnodeAttrs = newVnode.$attrs$ || EMPTY_OBJ; 566 { 567 // remove attributes no longer present on the vnode by setting them to undefined 568 for (memberName in oldVnodeAttrs) { 569 if (!(memberName in newVnodeAttrs)) {
vendor: 6,705 bytes, lines 570-725
570 setAccessor(elm, memberName, oldVnodeAttrs[memberName], undefined, isSvgMode, newVnode.$flags$); 571 } 572 } 573 } 574 // add new & update changed attributes 575 for (memberName in newVnodeAttrs) { 576 setAccessor(elm, memberName, oldVnodeAttrs[memberName], newVnodeAttrs[memberName], isSvgMode, newVnode.$flags$); 577 } 578}; 579/** 580 * Create a DOM Node corresponding to one of the children of a given VNode. 581 * 582 * @param oldParentVNode the parent VNode from the previous render 583 * @param newParentVNode the parent VNode from the current render 584 * @param childIndex the index of the VNode, in the _new_ parent node's 585 * children, for which we will create a new DOM node 586 * @param parentElm the parent DOM node which our new node will be a child of 587 * @returns the newly created node 588 */ 589const createElm = (oldParentVNode, newParentVNode, childIndex, parentElm) => { 590 // tslint:disable-next-line: prefer-const 591 const newVNode = newParentVNode.$children$[childIndex]; 592 let i = 0; 593 let elm; 594 let childNode; 595 let oldVNode; 596 if (!useNativeShadowDom) { 597 // remember for later we need to check to relocate nodes 598 checkSlotRelocate = true; 599 if (newVNode.$tag$ === 'slot') { 600 if (scopeId) { 601 // scoped css needs to add its scoped id to the parent element 602 parentElm.classList.add(scopeId + '-s'); 603 } 604 newVNode.$flags$ |= newVNode.$children$ 605 ? // slot element has fallback content 606 2 /* VNODE_FLAGS.isSlotFallback */ 607 : // slot element does not have fallback content 608 1 /* VNODE_FLAGS.isSlotReference */; 609 } 610 } 611 if (newVNode.$text$ !== null) { 612 // create text node 613 elm = newVNode.$elm$ = doc.createTextNode(newVNode.$text$); 614 } 615 else if (newVNode.$flags$ & 1 /* VNODE_FLAGS.isSlotReference */) { 616 // create a slot reference node 617 elm = newVNode.$elm$ = 618 doc.createTextNode(''); 619 } 620 else { 621 if (!isSvgMode) { 622 isSvgMode = newVNode.$tag$ === 'svg'; 623 } 624 // create element 625 elm = newVNode.$elm$ = (doc.createElementNS(isSvgMode ? SVG_NS : HTML_NS, newVNode.$flags$ & 2 /* VNODE_FLAGS.isSlotFallback */ 626 ? 'slot-fb' 627 : newVNode.$tag$) 628 ); 629 if (isSvgMode && newVNode.$tag$ === 'foreignObject') { 630 isSvgMode = false; 631 } 632 // add css classes, attrs, props, listeners, etc. 633 { 634 updateElement(null, newVNode, isSvgMode); 635 } 636 if (isDef(scopeId) && elm['s-si'] !== scopeId) { 637 // if there is a scopeId and this is the initial render 638 // then let's add the scopeId as a css class 639 elm.classList.add((elm['s-si'] = scopeId)); 640 } 641 if (newVNode.$children$) { 642 for (i = 0; i < newVNode.$children$.length; ++i) { 643 // create the node 644 childNode = createElm(oldParentVNode, newVNode, i, elm); 645 // return node could have been null 646 if (childNode) { 647 // append our new node 648 elm.appendChild(childNode); 649 } 650 } 651 } 652 { 653 if (newVNode.$tag$ === 'svg') { 654 // Only reset the SVG context when we're exiting <svg> element 655 isSvgMode = false; 656 } 657 else if (elm.tagName === 'foreignObject') { 658 // Reenter SVG context when we're exiting <foreignObject> element 659 isSvgMode = true; 660 } 661 } 662 } 663 { 664 elm['s-hn'] = hostTagName; 665 if (newVNode.$flags$ & (2 /* VNODE_FLAGS.isSlotFallback */ | 1 /* VNODE_FLAGS.isSlotReference */)) { 666 // remember the content reference comment 667 elm['s-sr'] = true; 668 // remember the content reference comment 669 elm['s-cr'] = contentRef; 670 // remember the slot name, or empty string for default slot 671 elm['s-sn'] = newVNode.$name$ || ''; 672 // check if we've got an old vnode for this slot 673 oldVNode = oldParentVNode && oldParentVNode.$children$ && oldParentVNode.$children$[childIndex]; 674 if (oldVNode && oldVNode.$tag$ === newVNode.$tag$ && oldParentVNode.$elm$) { 675 // we've got an old slot vnode and the wrapper is being replaced 676 // so let's move the old slot content back to it's original location 677 putBackInOriginalLocation(oldParentVNode.$elm$, false); 678 } 679 } 680 } 681 return elm; 682}; 683const putBackInOriginalLocation = (parentElm, recursive) => { 684 plt.$flags$ |= 1 /* PLATFORM_FLAGS.isTmpDisconnected */; 685 const oldSlotChildNodes = parentElm.childNodes; 686 for (let i = oldSlotChildNodes.length - 1; i >= 0; i--) { 687 const childNode = oldSlotChildNodes[i]; 688 if (childNode['s-hn'] !== hostTagName && childNode['s-ol']) { 689 // // this child node in the old element is from another component 690 // // remove this node from the old slot's parent 691 // childNode.remove(); 692 // and relocate it back to it's original location 693 parentReferenceNode(childNode).insertBefore(childNode, referenceNode(childNode)); 694 // remove the old original location comment entirely 695 // later on the patch function will know what to do 696 // and move this to the correct spot in need be 697 childNode['s-ol'].remove(); 698 childNode['s-ol'] = undefined; 699 checkSlotRelocate = true; 700 } 701 if (recursive) { 702 putBackInOriginalLocation(childNode, recursive); 703 } 704 } 705 plt.$flags$ &= ~1 /* PLATFORM_FLAGS.isTmpDisconnected */; 706}; 707/** 708 * Create DOM nodes corresponding to a list of {@link d.Vnode} objects and 709 * add them to the DOM in the appropriate place. 710 * 711 * @param parentElm the DOM node which should be used as a parent for the new 712 * DOM nodes 713 * @param before a child of the `parentElm` which the new children should be 714 * inserted before (optional) 715 * @param parentVNode the parent virtual DOM node 716 * @param vnodes the new child virtual DOM nodes to produce DOM nodes for 717 * @param startIdx the index in the child virtual DOM nodes at which to start 718 * creating DOM nodes (inclusive) 719 * @param endIdx the index in the child virtual DOM nodes at which to stop 720 * creating DOM nodes (inclusive) 721 */ 722const addVnodes = (parentElm, before, parentVNode, vnodes, startIdx, endIdx) => { 723 let containerElm = ((parentElm['s-cr'] && parentElm['s-cr'].parentNode) || parentElm); 724 let childNode; 725
vendor: 1,821 bytes, lines 725-769
725for (; startIdx <= endIdx; ++startIdx) { 726 if (vnodes[startIdx]) { 727 childNode = createElm(null, parentVNode, startIdx, parentElm); 728 if (childNode) { 729 vnodes[startIdx].$elm$ = childNode; 730 containerElm.insertBefore(childNode, referenceNode(before) ); 731 } 732 } 733 } 734}; 735/** 736 * Remove the DOM elements corresponding to a list of {@link d.VNode} objects. 737 * This can be used to, for instance, clean up after a list of children which 738 * should no longer be shown. 739 * 740 * This function also handles some of Stencil's slot relocation logic. 741 * 742 * @param vnodes a list of virtual DOM nodes to remove 743 * @param startIdx the index at which to start removing nodes (inclusive) 744 * @param endIdx the index at which to stop removing nodes (inclusive) 745 */ 746const removeVnodes = (vnodes, startIdx, endIdx) => { 747 for (let index = startIdx; index <= endIdx; ++index) { 748 const vnode = vnodes[index]; 749 if (vnode) { 750 const elm = vnode.$elm$; 751 nullifyVNodeRefs(vnode); 752 if (elm) { 753 { 754 // we're removing this element 755 // so it's possible we need to show slot fallback content now 756 checkSlotFallbackVisibility = true; 757 if (elm['s-ol']) { 758 // remove the original location comment 759 elm['s-ol'].remove(); 760 } 761 else { 762 // it's possible that child nodes of the node 763 // that's being removed are slot nodes 764 putBackInOriginalLocation(elm, true); 765 } 766 } 767 // remove the vnode's element from the dom 768 elm.remove(); 769 }
vendor: 23,118 bytes, lines 769-1249
769 770 } 771 } 772}; 773/** 774 * Reconcile the children of a new VNode with the children of an old VNode by 775 * traversing the two collections of children, identifying nodes that are 776 * conserved or changed, calling out to `patch` to make any necessary 777 * updates to the DOM, and rearranging DOM nodes as needed. 778 * 779 * The algorithm for reconciling children works by analyzing two 'windows' onto 780 * the two arrays of children (`oldCh` and `newCh`). We keep track of the 781 * 'windows' by storing start and end indices and references to the 782 * corresponding array entries. Initially the two 'windows' are basically equal 783 * to the entire array, but we progressively narrow the windows until there are 784 * no children left to update by doing the following: 785 * 786 * 1. Skip any `null` entries at the beginning or end of the two arrays, so 787 * that if we have an initial array like the following we'll end up dealing 788 * only with a window bounded by the highlighted elements: 789 * 790 * [null, null, VNode1 , ... , VNode2, null, null] 791 * ^^^^^^ ^^^^^^ 792 * 793 * 2. Check to see if the elements at the head and tail positions are equal 794 * across the windows. This will basically detect elements which haven't 795 * been added, removed, or changed position, i.e. if you had the following 796 * VNode elements (represented as HTML): 797 * 798 * oldVNode: `<div><p><span>HEY</span></p></div>` 799 * newVNode: `<div><p><span>THERE</span></p></div>` 800 * 801 * Then when comparing the children of the `<div>` tag we check the equality 802 * of the VNodes corresponding to the `<p>` tags and, since they are the 803 * same tag in the same position, we'd be able to avoid completely 804 * re-rendering the subtree under them with a new DOM element and would just 805 * call out to `patch` to handle reconciling their children and so on. 806 * 807 * 3. Check, for both windows, to see if the element at the beginning of the 808 * window corresponds to the element at the end of the other window. This is 809 * a heuristic which will let us identify _some_ situations in which 810 * elements have changed position, for instance it _should_ detect that the 811 * children nodes themselves have not changed but merely moved in the 812 * following example: 813 * 814 * oldVNode: `<div><element-one /><element-two /></div>` 815 * newVNode: `<div><element-two /><element-one /></div>` 816 * 817 * If we find cases like this then we also need to move the concrete DOM 818 * elements corresponding to the moved children to write the re-order to the 819 * DOM. 820 * 821 * 4. Finally, if VNodes have the `key` attribute set on them we check for any 822 * nodes in the old children which have the same key as the first element in 823 * our window on the new children. If we find such a node we handle calling 824 * out to `patch`, moving relevant DOM nodes, and so on, in accordance with 825 * what we find. 826 * 827 * Finally, once we've narrowed our 'windows' to the point that either of them 828 * collapse (i.e. they have length 0) we then handle any remaining VNode 829 * insertion or deletion that needs to happen to get a DOM state that correctly 830 * reflects the new child VNodes. If, for instance, after our window on the old 831 * children has collapsed we still have more nodes on the new children that 832 * we haven't dealt with yet then we need to add them, or if the new children 833 * collapse but we still have unhandled _old_ children then we need to make 834 * sure the corresponding DOM nodes are removed. 835 * 836 * @param parentElm the node into which the parent VNode is rendered 837 * @param oldCh the old children of the parent node 838 * @param newVNode the new VNode which will replace the parent 839 * @param newCh the new children of the parent node 840 */ 841const updateChildren = (parentElm, oldCh, newVNode, newCh) => { 842 let oldStartIdx = 0; 843 let newStartIdx = 0; 844 let idxInOld = 0; 845 let i = 0; 846 let oldEndIdx = oldCh.length - 1; 847 let oldStartVnode = oldCh[0]; 848 let oldEndVnode = oldCh[oldEndIdx]; 849 let newEndIdx = newCh.length - 1; 850 let newStartVnode = newCh[0]; 851 let newEndVnode = newCh[newEndIdx]; 852 let node; 853 let elmToMove; 854 while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { 855 if (oldStartVnode == null) { 856 // VNode might have been moved left 857 oldStartVnode = oldCh[++oldStartIdx]; 858 } 859 else if (oldEndVnode == null) { 860 oldEndVnode = oldCh[--oldEndIdx]; 861 } 862 else if (newStartVnode == null) { 863 newStartVnode = newCh[++newStartIdx]; 864 } 865 else if (newEndVnode == null) { 866 newEndVnode = newCh[--newEndIdx]; 867 } 868 else if (isSameVnode(oldStartVnode, newStartVnode)) { 869 // if the start nodes are the same then we should patch the new VNode 870 // onto the old one, and increment our `newStartIdx` and `oldStartIdx` 871 // indices to reflect that. We don't need to move any DOM Nodes around 872 // since things are matched up in order. 873 patch(oldStartVnode, newStartVnode); 874 oldStartVnode = oldCh[++oldStartIdx]; 875 newStartVnode = newCh[++newStartIdx]; 876 } 877 else if (isSameVnode(oldEndVnode, newEndVnode)) { 878 // likewise, if the end nodes are the same we patch new onto old and 879 // decrement our end indices, and also likewise in this case we don't 880 // need to move any DOM Nodes. 881 patch(oldEndVnode, newEndVnode); 882 oldEndVnode = oldCh[--oldEndIdx]; 883 newEndVnode = newCh[--newEndIdx]; 884 } 885 else if (isSameVnode(oldStartVnode, newEndVnode)) { 886 // case: "Vnode moved right" 887 // 888 // We've found that the last node in our window on the new children is 889 // the same VNode as the _first_ node in our window on the old children 890 // we're dealing with now. Visually, this is the layout of these two 891 // nodes: 892 // 893 // newCh: [..., newStartVnode , ... , newEndVnode , ...] 894 // ^^^^^^^^^^^ 895 // oldCh: [..., oldStartVnode , ... , oldEndVnode , ...] 896 // ^^^^^^^^^^^^^ 897 // 898 // In this situation we need to patch `newEndVnode` onto `oldStartVnode` 899 // and move the DOM element for `oldStartVnode`. 900 if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) { 901 putBackInOriginalLocation(oldStartVnode.$elm$.parentNode, false); 902 } 903 patch(oldStartVnode, newEndVnode); 904 // We need to move the element for `oldStartVnode` into a position which 905 // will be appropriate for `newEndVnode`. For this we can use 906 // `.insertBefore` and `oldEndVnode.$elm$.nextSibling`. If there is a 907 // sibling for `oldEndVnode.$elm$` then we want to move the DOM node for 908 // `oldStartVnode` between `oldEndVnode` and it's sibling, like so: 909 // 910 // <old-start-node /> 911 // <some-intervening-node /> 912 // <old-end-node /> 913 // <!-- -> <-- `oldStartVnode.$elm$` should be inserted here 914 // <next-sibling /> 915 // 916 // If instead `oldEndVnode.$elm$` has no sibling then we just want to put 917 // the node for `oldStartVnode` at the end of the children of 918 // `parentElm`. Luckily, `Node.nextSibling` will return `null` if there 919 // aren't any siblings, and passing `null` to `Node.insertBefore` will 920 // append it to the children of the parent element. 921 parentElm.insertBefore(oldStartVnode.$elm$, oldEndVnode.$elm$.nextSibling); 922 oldStartVnode = oldCh[++oldStartIdx]; 923 newEndVnode = newCh[--newEndIdx]; 924 } 925 else if (isSameVnode(oldEndVnode, newStartVnode)) { 926 // case: "Vnode moved left" 927 // 928 // We've found that the first node in our window on the new children is 929 // the same VNode as the _last_ node in our window on the old children. 930 // Visually, this is the layout of these two nodes: 931 // 932 // newCh: [..., newStartVnode , ... , newEndVnode , ...] 933 // ^^^^^^^^^^^^^ 934 // oldCh: [..., oldStartVnode , ... , oldEndVnode , ...] 935 // ^^^^^^^^^^^ 936 // 937 // In this situation we need to patch `newStartVnode` onto `oldEndVnode` 938 // (which will handle updating any changed attributes, reconciling their 939 // children etc) but we also need to move the DOM node to which 940 // `oldEndVnode` corresponds. 941 if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) { 942 putBackInOriginalLocation(oldEndVnode.$elm$.parentNode, false); 943 } 944 patch(oldEndVnode, newStartVnode); 945 // We've already checked above if `oldStartVnode` and `newStartVnode` are 946 // the same node, so since we're here we know that they are not. Thus we 947 // can move the element for `oldEndVnode` _before_ the element for 948 // `oldStartVnode`, leaving `oldStartVnode` to be reconciled in the 949 // future. 950 parentElm.insertBefore(oldEndVnode.$elm$, oldStartVnode.$elm$); 951 oldEndVnode = oldCh[--oldEndIdx]; 952 newStartVnode = newCh[++newStartIdx]; 953 } 954 else { 955 // Here we do some checks to match up old and new nodes based on the 956 // `$key$` attribute, which is set by putting a `key="my-key"` attribute 957 // in the JSX for a DOM element in the implementation of a Stencil 958 // component. 959 // 960 // First we check to see if there are any nodes in the array of old 961 // children which have the same key as the first node in the new 962 // children. 963 idxInOld = -1; 964 { 965 for (i = oldStartIdx; i <= oldEndIdx; ++i) { 966 if (oldCh[i] && oldCh[i].$key$ !== null && oldCh[i].$key$ === newStartVnode.$key$) { 967 idxInOld = i; 968 break; 969 } 970 } 971 } 972 if (idxInOld >= 0) { 973 // We found a node in the old children which matches up with the first 974 // node in the new children! So let's deal with that 975 elmToMove = oldCh[idxInOld]; 976 if (elmToMove.$tag$ !== newStartVnode.$tag$) { 977 // the tag doesn't match so we'll need a new DOM element 978 node = createElm(oldCh && oldCh[newStartIdx], newVNode, idxInOld, parentElm); 979 } 980 else { 981 patch(elmToMove, newStartVnode); 982 // invalidate the matching old node so that we won't try to update it 983 // again later on 984 oldCh[idxInOld] = undefined; 985 node = elmToMove.$elm$; 986 } 987 newStartVnode = newCh[++newStartIdx]; 988 } 989 else { 990 // We either didn't find an element in the old children that matches 991 // the key of the first new child OR the build is not using `key` 992 // attributes at all. In either case we need to create a new element 993 // for the new node. 994 node = createElm(oldCh && oldCh[newStartIdx], newVNode, newStartIdx, parentElm); 995 newStartVnode = newCh[++newStartIdx]; 996 } 997 if (node) { 998 // if we created a new node then handle inserting it to the DOM 999 { 1000 parentReferenceNode(oldStartVnode.$elm$).insertBefore(node, referenceNode(oldStartVnode.$elm$)); 1001 } 1002 } 1003 } 1004 } 1005 if (oldStartIdx > oldEndIdx) { 1006 // we have some more new nodes to add which don't match up with old nodes 1007 addVnodes(parentElm, newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].$elm$, newVNode, newCh, newStartIdx, newEndIdx); 1008 } 1009 else if (newStartIdx > newEndIdx) { 1010 // there are nodes in the `oldCh` array which no longer correspond to nodes 1011 // in the new array, so lets remove them (which entails cleaning up the 1012 // relevant DOM nodes) 1013 removeVnodes(oldCh, oldStartIdx, oldEndIdx); 1014 } 1015}; 1016/** 1017 * Compare two VNodes to determine if they are the same 1018 * 1019 * **NB**: This function is an equality _heuristic_ based on the available 1020 * information set on the two VNodes and can be misleading under certain 1021 * circumstances. In particular, if the two nodes do not have `key` attrs 1022 * (available under `$key$` on VNodes) then the function falls back on merely 1023 * checking that they have the same tag. 1024 * 1025 * So, in other words, if `key` attrs are not set on VNodes which may be 1026 * changing order within a `children` array or something along those lines then 1027 * we could obtain a false negative and then have to do needless re-rendering 1028 * (i.e. we'd say two VNodes aren't equal when in fact they should be). 1029 * 1030 * @param leftVNode the first VNode to check 1031 * @param rightVNode the second VNode to check 1032 * @returns whether they're equal or not 1033 */ 1034const isSameVnode = (leftVNode, rightVNode) => { 1035 // compare if two vnode to see if they're "technically" the same 1036 // need to have the same element tag, and same key to be the same 1037 if (leftVNode.$tag$ === rightVNode.$tag$) { 1038 if (leftVNode.$tag$ === 'slot') { 1039 return leftVNode.$name$ === rightVNode.$name$; 1040 } 1041 // this will be set if components in the build have `key` attrs set on them 1042 { 1043 return leftVNode.$key$ === rightVNode.$key$; 1044 } 1045 } 1046 return false; 1047}; 1048const referenceNode = (node) => { 1049 // this node was relocated to a new location in the dom 1050 // because of some other component's slot 1051 // but we still have an html comment in place of where 1052 // it's original location was according to it's original vdom 1053 return (node && node['s-ol']) || node; 1054}; 1055const parentReferenceNode = (node) => (node['s-ol'] ? node['s-ol'] : node).parentNode; 1056/** 1057 * Handle reconciling an outdated VNode with a new one which corresponds to 1058 * it. This function handles flushing updates to the DOM and reconciling the 1059 * children of the two nodes (if any). 1060 * 1061 * @param oldVNode an old VNode whose DOM element and children we want to update 1062 * @param newVNode a new VNode representing an updated version of the old one 1063 */ 1064const patch = (oldVNode, newVNode) => { 1065 const elm = (newVNode.$elm$ = oldVNode.$elm$); 1066 const oldChildren = oldVNode.$children$; 1067 const newChildren = newVNode.$children$; 1068 const tag = newVNode.$tag$; 1069 const text = newVNode.$text$; 1070 let defaultHolder; 1071 if (text === null) { 1072 { 1073 // test if we're rendering an svg element, or still rendering nodes inside of one 1074 // only add this to the when the compiler sees we're using an svg somewhere 1075 isSvgMode = tag === 'svg' ? true : tag === 'foreignObject' ? false : isSvgMode; 1076 } 1077 { 1078 if (tag === 'slot') 1079 ; 1080 else { 1081 // either this is the first render of an element OR it's an update 1082 // AND we already know it's possible it could have changed 1083 // this updates the element's css classes, attrs, props, listeners, etc. 1084 updateElement(oldVNode, newVNode, isSvgMode); 1085 } 1086 } 1087 if (oldChildren !== null && newChildren !== null) { 1088 // looks like there's child vnodes for both the old and new vnodes 1089 // so we need to call `updateChildren` to reconcile them 1090 updateChildren(elm, oldChildren, newVNode, newChildren); 1091 } 1092 else if (newChildren !== null) { 1093 // no old child vnodes, but there are new child vnodes to add 1094 if (oldVNode.$text$ !== null) { 1095 // the old vnode was text, so be sure to clear it out 1096 elm.textContent = ''; 1097 } 1098 // add the new vnode children 1099 addVnodes(elm, null, newVNode, newChildren, 0, newChildren.length - 1); 1100 } 1101 else if (oldChildren !== null) { 1102 // no new child vnodes, but there are old child vnodes to remove 1103 removeVnodes(oldChildren, 0, oldChildren.length - 1); 1104 } 1105 if (isSvgMode && tag === 'svg') { 1106 isSvgMode = false; 1107 } 1108 } 1109 else if ((defaultHolder = elm['s-cr'])) { 1110 // this element has slotted content 1111 defaultHolder.parentNode.textContent = text; 1112 } 1113 else if (oldVNode.$text$ !== text) { 1114 // update the text content for the text only vnode 1115 // and also only if the text is different than before 1116 elm.data = text; 1117 } 1118}; 1119const updateFallbackSlotVisibility = (elm) => { 1120 // tslint:disable-next-line: prefer-const 1121 const childNodes = elm.childNodes; 1122 let childNode; 1123 let i; 1124 let ilen; 1125 let j; 1126 let slotNameAttr; 1127 let nodeType; 1128 for (i = 0, ilen = childNodes.length; i < ilen; i++) { 1129 childNode = childNodes[i]; 1130 if (childNode.nodeType === 1 /* NODE_TYPE.ElementNode */) { 1131 if (childNode['s-sr']) { 1132 // this is a slot fallback node 1133 // get the slot name for this slot reference node 1134 slotNameAttr = childNode['s-sn']; 1135 // by default always show a fallback slot node 1136 // then hide it if there are other slots in the light dom 1137 childNode.hidden = false; 1138 for (j = 0; j < ilen; j++) { 1139 nodeType = childNodes[j].nodeType; 1140 if (childNodes[j]['s-hn'] !== childNode['s-hn'] || slotNameAttr !== '') { 1141 // this sibling node is from a different component OR is a named fallback slot node 1142 if (nodeType === 1 /* NODE_TYPE.ElementNode */ && slotNameAttr === childNodes[j].getAttribute('slot')) { 1143 childNode.hidden = true; 1144 break; 1145 } 1146 } 1147 else { 1148 // this is a default fallback slot node 1149 // any element or text node (with content) 1150 // should hide the default fallback slot node 1151 if (nodeType === 1 /* NODE_TYPE.ElementNode */ || 1152 (nodeType === 3 /* NODE_TYPE.TextNode */ && childNodes[j].textContent.trim() !== '')) { 1153 childNode.hidden = true; 1154 break; 1155 } 1156 } 1157 } 1158 } 1159 // keep drilling down 1160 updateFallbackSlotVisibility(childNode); 1161 } 1162 } 1163}; 1164const relocateNodes = []; 1165const relocateSlotContent = (elm) => { 1166 // tslint:disable-next-line: prefer-const 1167 let childNode; 1168 let node; 1169 let hostContentNodes; 1170 let slotNameAttr; 1171 let relocateNodeData; 1172 let j; 1173 let i = 0; 1174 const childNodes = elm.childNodes; 1175 const ilen = childNodes.length; 1176 for (; i < ilen; i++) { 1177 childNode = childNodes[i]; 1178 if (childNode['s-sr'] && (node = childNode['s-cr']) && node.parentNode) { 1179 // first got the content reference comment node 1180 // then we got it's parent, which is where all the host content is in now 1181 hostContentNodes = node.parentNode.childNodes; 1182 slotNameAttr = childNode['s-sn']; 1183 for (j = hostContentNodes.length - 1; j >= 0; j--) { 1184 node = hostContentNodes[j]; 1185 if (!node['s-cn'] && !node['s-nr'] && node['s-hn'] !== childNode['s-hn']) { 1186 // let's do some relocating to its new home 1187 // but never relocate a content reference node 1188 // that is suppose to always represent the original content location 1189 if (isNodeLocatedInSlot(node, slotNameAttr)) { 1190 // it's possible we've already decided to relocate this node 1191 relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node); 1192 // made some changes to slots 1193 // let's make sure we also double check 1194 // fallbacks are correctly hidden or shown 1195 checkSlotFallbackVisibility = true; 1196 node['s-sn'] = node['s-sn'] || slotNameAttr; 1197 if (relocateNodeData) { 1198 // previously we never found a slot home for this node 1199 // but turns out we did, so let's remember it now 1200 relocateNodeData.$slotRefNode$ = childNode; 1201 } 1202 else { 1203 // add to our list of nodes to relocate 1204 relocateNodes.push({ 1205 $slotRefNode$: childNode, 1206 $nodeToRelocate$: node, 1207 }); 1208 } 1209 if (node['s-sr']) { 1210 relocateNodes.map((relocateNode) => { 1211 if (isNodeLocatedInSlot(relocateNode.$nodeToRelocate$, node['s-sn'])) { 1212 relocateNodeData = relocateNodes.find((r) => r.$nodeToRelocate$ === node); 1213 if (relocateNodeData && !relocateNode.$slotRefNode$) { 1214 relocateNode.$slotRefNode$ = relocateNodeData.$slotRefNode$; 1215 } 1216 } 1217 }); 1218 } 1219 } 1220 else if (!relocateNodes.some((r) => r.$nodeToRelocate$ === node)) { 1221 // so far this element does not have a slot home, not setting slotRefNode on purpose 1222 // if we never find a home for this element then we'll need to hide it 1223 relocateNodes.push({ 1224 $nodeToRelocate$: node, 1225 }); 1226 } 1227 } 1228 } 1229 } 1230 if (childNode.nodeType === 1 /* NODE_TYPE.ElementNode */) { 1231 relocateSlotContent(childNode); 1232 } 1233 } 1234}; 1235const isNodeLocatedInSlot = (nodeToRelocate, slotNameAttr) => { 1236 if (nodeToRelocate.nodeType === 1 /* NODE_TYPE.ElementNode */) { 1237 if (nodeToRelocate.getAttribute('slot') === null && slotNameAttr === '') { 1238 return true; 1239 } 1240 if (nodeToRelocate.getAttribute('slot') === slotNameAttr) { 1241 return true; 1242 } 1243 return false; 1244 } 1245 if (nodeToRelocate['s-sn'] === slotNameAttr) { 1246 return true; 1247 } 1248 return slotNameAttr === ''; 1249};
1250/** 1251 * 'Nullify' any VDom `ref` callbacks on a VDom node or its children by 1252 * calling them with `null`. This signals that the DOM element corresponding to 1253 * the VDom node has been removed from the DOM. 1254 * 1255 * @param vNode a virtual DOM node 1256 */ 1257const nullifyVNodeRefs = (vNode) => { 1258 { 1259 vNode.$attrs$ && vNode.$attrs$.ref && vNode.$attrs$.ref(null); 1260 vNode.$children$ && vNode.$children$.map(nullifyVNodeRefs); 1261 } 1262}; 1263/** 1264 * The main entry point for Stencil's virtual DOM-based rendering engine 1265 * 1266 * Given a {@link d.HostRef} container and some virtual DOM nodes, this 1267 * function will handle creating a virtual DOM tree with a single root, patching 1268 * the current virtual DOM tree onto an old one (if any), dealing with slot 1269 * relocation, and reflecting attributes. 1270 * 1271 * @param hostRef data needed to root and render the virtual DOM tree, such as 1272 * the DOM node into which it should be rendered. 1273 * @param renderFnResults the virtual DOM nodes to be rendered 1274 * @param isInitialLoad whether or not this is the first call after page load 1275 */ 1276const renderVdom = (hostRef, renderFnResults, isInitialLoad = false) => { 1277 const hostElm = hostRef.$hostElement$; 1278 const cmpMeta = hostRef.$cmpMeta$; 1279 const oldVNode = hostRef.$vnode$ || newVNode(null, null); 1280 // if `renderFnResults` is a Host node then we can use it directly. If not, 1281 // we need to call `h` again to wrap the children of our component in a 1282 // 'dummy' Host node (well, an empty vnode) since `renderVdom` assumes 1283 // implicitly that the top-level vdom node is 1) an only child and 2) 1284 // contains attrs that need to be set on the host element. 1285 const rootVnode = isHost(renderFnResults) ? renderFnResults : h(null, null, renderFnResults); 1286 hostTagName = hostElm.tagName; 1287 // On the first render and *only* on the first render we want to check for 1288 // any attributes set on the host element which are also set on the vdom 1289 // node. If we find them, we override the value on the VDom node attrs with 1290 // the value from the host element, which allows developers building apps 1291 // with Stencil components to override e.g. the `role` attribute on a 1292 // component even if it's already set on the `Host`. 1293 if (isInitialLoad && rootVnode.$attrs$) { 1294 for (const key of Object.keys(rootVnode.$attrs$)) { 1295 // We have a special implementation in `setAccessor` for `style` and 1296 // `class` which reconciles values coming from the VDom with values 1297 // already present on the DOM element, so we don't want to override those 1298 // attributes on the VDom tree with values from the host element if they 1299 // are present. 1300 // 1301 // Likewise, `ref` and `key` are special internal values for the Stencil 1302 // runtime and we don't want to override those either. 1303 if (hostElm.hasAttribute(key) && !['key', 'ref', 'style', 'class'].includes(key)) { 1304 rootVnode.$attrs$[key] = hostElm[key]; 1305 } 1306 } 1307 } 1308 rootVnode.$tag$ = null; 1309 rootVnode.$flags$ |= 4 /* VNODE_FLAGS.isHost */; 1310 hostRef.$vnode$ = rootVnode; 1311 rootVnode.$elm$ = oldVNode.$elm$ = (hostElm); 1312 { 1313 scopeId = hostElm['s-sc']; 1314 }
vendor: 7,746 bytes, lines 1314-1473
1314 1315 { 1316 contentRef = hostElm['s-cr']; 1317 useNativeShadowDom = (cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */) !== 0; 1318 // always reset 1319 checkSlotFallbackVisibility = false; 1320 } 1321 // synchronous patch 1322 patch(oldVNode, rootVnode); 1323 { 1324 // while we're moving nodes around existing nodes, temporarily disable 1325 // the disconnectCallback from working 1326 plt.$flags$ |= 1 /* PLATFORM_FLAGS.isTmpDisconnected */; 1327 if (checkSlotRelocate) { 1328 relocateSlotContent(rootVnode.$elm$); 1329 let relocateData; 1330 let nodeToRelocate; 1331 let orgLocationNode; 1332 let parentNodeRef; 1333 let insertBeforeNode; 1334 let refNode; 1335 let i = 0; 1336 for (; i < relocateNodes.length; i++) { 1337 relocateData = relocateNodes[i]; 1338 nodeToRelocate = relocateData.$nodeToRelocate$; 1339 if (!nodeToRelocate['s-ol']) { 1340 // add a reference node marking this node's original location 1341 // keep a reference to this node for later lookups 1342 orgLocationNode = 1343 doc.createTextNode(''); 1344 orgLocationNode['s-nr'] = nodeToRelocate; 1345 nodeToRelocate.parentNode.insertBefore((nodeToRelocate['s-ol'] = orgLocationNode), nodeToRelocate); 1346 } 1347 } 1348 for (i = 0; i < relocateNodes.length; i++) { 1349 relocateData = relocateNodes[i]; 1350 nodeToRelocate = relocateData.$nodeToRelocate$; 1351 if (relocateData.$slotRefNode$) { 1352 // by default we're just going to insert it directly 1353 // after the slot reference node 1354 parentNodeRef = relocateData.$slotRefNode$.parentNode; 1355 insertBeforeNode = relocateData.$slotRefNode$.nextSibling; 1356 orgLocationNode = nodeToRelocate['s-ol']; 1357 while ((orgLocationNode = orgLocationNode.previousSibling)) { 1358 refNode = orgLocationNode['s-nr']; 1359 if (refNode && refNode['s-sn'] === nodeToRelocate['s-sn'] && parentNodeRef === refNode.parentNode) { 1360 refNode = refNode.nextSibling; 1361 if (!refNode || !refNode['s-nr']) { 1362 insertBeforeNode = refNode; 1363 break; 1364 } 1365 } 1366 } 1367 if ((!insertBeforeNode && parentNodeRef !== nodeToRelocate.parentNode) || 1368 nodeToRelocate.nextSibling !== insertBeforeNode) { 1369 // we've checked that it's worth while to relocate 1370 // since that the node to relocate 1371 // has a different next sibling or parent relocated 1372 if (nodeToRelocate !== insertBeforeNode) { 1373 if (!nodeToRelocate['s-hn'] && nodeToRelocate['s-ol']) { 1374 // probably a component in the index.html that doesn't have it's hostname set 1375 nodeToRelocate['s-hn'] = nodeToRelocate['s-ol'].parentNode.nodeName; 1376 } 1377 // add it back to the dom but in its new home 1378 parentNodeRef.insertBefore(nodeToRelocate, insertBeforeNode); 1379 } 1380 } 1381 } 1382 else { 1383 // this node doesn't have a slot home to go to, so let's hide it 1384 if (nodeToRelocate.nodeType === 1 /* NODE_TYPE.ElementNode */) { 1385 nodeToRelocate.hidden = true; 1386 } 1387 } 1388 } 1389 } 1390 if (checkSlotFallbackVisibility) { 1391 updateFallbackSlotVisibility(rootVnode.$elm$); 1392 } 1393 // done moving nodes around 1394 // allow the disconnect callback to work again 1395 plt.$flags$ &= ~1 /* PLATFORM_FLAGS.isTmpDisconnected */; 1396 // always reset 1397 relocateNodes.length = 0; 1398 } 1399}; 1400const attachToAncestor = (hostRef, ancestorComponent) => { 1401 if (ancestorComponent && !hostRef.$onRenderResolve$ && ancestorComponent['s-p']) { 1402 ancestorComponent['s-p'].push(new Promise((r) => (hostRef.$onRenderResolve$ = r))); 1403 } 1404}; 1405const scheduleUpdate = (hostRef, isInitialLoad) => { 1406 { 1407 hostRef.$flags$ |= 16 /* HOST_FLAGS.isQueuedForUpdate */; 1408 } 1409 if (hostRef.$flags$ & 4 /* HOST_FLAGS.isWaitingForChildren */) { 1410 hostRef.$flags$ |= 512 /* HOST_FLAGS.needsRerender */; 1411 return; 1412 } 1413 attachToAncestor(hostRef, hostRef.$ancestorComponent$); 1414 // there is no ancestor component or the ancestor component 1415 // has already fired off its lifecycle update then 1416 // fire off the initial update 1417 const dispatch = () => dispatchHooks(hostRef, isInitialLoad); 1418 return writeTask(dispatch) ; 1419}; 1420/** 1421 * Dispatch initial-render and update lifecycle hooks, enqueuing calls to 1422 * component lifecycle methods like `componentWillLoad` as well as 1423 * {@link updateComponent}, which will kick off the virtual DOM re-render. 1424 * 1425 * @param hostRef a reference to a host DOM node 1426 * @param isInitialLoad whether we're on the initial load or not 1427 * @returns an empty Promise which is used to enqueue a series of operations for 1428 * the component 1429 */ 1430const dispatchHooks = (hostRef, isInitialLoad) => { 1431 const endSchedule = createTime('scheduleUpdate', hostRef.$cmpMeta$.$tagName$); 1432 const instance = hostRef.$lazyInstance$ ; 1433 // We're going to use this variable together with `enqueue` to implement a 1434 // little promise-based queue. We start out with it `undefined`. When we add 1435 // the first function to the queue we'll set this variable to be that 1436 // function's return value. When we attempt to add subsequent values to the 1437 // queue we'll check that value and, if it was a `Promise`, we'll then chain 1438 // the new function off of that `Promise` using `.then()`. This will give our 1439 // queue two nice properties: 1440 // 1441 // 1. If all functions added to the queue are synchronous they'll be called 1442 // synchronously right away. 1443 // 2. If all functions added to the queue are asynchronous they'll all be 1444 // called in order after `dispatchHooks` exits. 1445 let maybePromise; 1446 if (isInitialLoad) { 1447 { 1448 hostRef.$flags$ |= 256 /* HOST_FLAGS.isListenReady */; 1449 if (hostRef.$queuedListeners$) { 1450 hostRef.$queuedListeners$.map(([methodName, event]) => safeCall(instance, methodName, event)); 1451 hostRef.$queuedListeners$ = undefined; 1452 } 1453 } 1454 { 1455 // If `componentWillLoad` returns a `Promise` then we want to wait on 1456 // whatever's going on in that `Promise` before we launch into 1457 // rendering the component, doing other lifecycle stuff, etc. So 1458 // in that case we assign the returned promise to the variable we 1459 // declared above to hold a possible 'queueing' Promise 1460 maybePromise = safeCall(instance, 'componentWillLoad'); 1461 } 1462 } 1463 else { 1464 { 1465 // Like `componentWillLoad` above, we allow Stencil component 1466 // authors to return a `Promise` from this lifecycle callback, and 1467 // we specify that our runtime will wait for that `Promise` to 1468 // resolve before the component re-renders. So if the method 1469 // returns a `Promise` we need to keep it around! 1470 maybePromise = safeCall(instance, 'componentWillUpdate'); 1471 } 1472 } 1473
vendor: 3,305 bytes, lines 1473-1553
1473endSchedule(); 1474 return enqueue(maybePromise, () => updateComponent(hostRef, instance, isInitialLoad)); 1475}; 1476/** 1477 * This function uses a Promise to implement a simple first-in, first-out queue 1478 * of functions to be called. 1479 * 1480 * The queue is ordered on the basis of the first argument. If it's 1481 * `undefined`, then nothing is on the queue yet, so the provided function can 1482 * be called synchronously (although note that this function may return a 1483 * `Promise`). The idea is that then the return value of that enqueueing 1484 * operation is kept around, so that if it was a `Promise` then subsequent 1485 * functions can be enqueued by calling this function again with that `Promise` 1486 * as the first argument. 1487 * 1488 * @param maybePromise either a `Promise` which should resolve before the next function is called or an 'empty' sentinel 1489 * @param fn a function to enqueue 1490 * @returns either a `Promise` or the return value of the provided function 1491 */ 1492const enqueue = (maybePromise, fn) => isPromisey(maybePromise) ? maybePromise.then(fn) : fn(); 1493/** 1494 * Check that a value is a `Promise`. To check, we first see if the value is an 1495 * instance of the `Promise` global. In a few circumstances, in particular if 1496 * the global has been overwritten, this is could be misleading, so we also do 1497 * a little 'duck typing' check to see if the `.then` property of the value is 1498 * defined and a function. 1499 * 1500 * @param maybePromise it might be a promise! 1501 * @returns whether it is or not 1502 */ 1503const isPromisey = (maybePromise) => maybePromise instanceof Promise || 1504 (maybePromise && maybePromise.then && typeof maybePromise.then === 'function'); 1505/** 1506 * Update a component given reference to its host elements and so on. 1507 * 1508 * @param hostRef an object containing references to the element's host node, 1509 * VDom nodes, and other metadata 1510 * @param instance a reference to the underlying host element where it will be 1511 * rendered 1512 * @param isInitialLoad whether or not this function is being called as part of 1513 * the first render cycle 1514 */ 1515const updateComponent = async (hostRef, instance, isInitialLoad) => { 1516 var _a; 1517 const elm = hostRef.$hostElement$; 1518 const endUpdate = createTime('update', hostRef.$cmpMeta$.$tagName$); 1519 const rc = elm['s-rc']; 1520 if (isInitialLoad) { 1521 // DOM WRITE! 1522 attachStyles(hostRef); 1523 } 1524 const endRender = createTime('render', hostRef.$cmpMeta$.$tagName$); 1525 { 1526 callRender(hostRef, instance, elm, isInitialLoad); 1527 } 1528 if (rc) { 1529 // ok, so turns out there are some child host elements 1530 // waiting on this parent element to load 1531 // let's fire off all update callbacks waiting 1532 rc.map((cb) => cb()); 1533 elm['s-rc'] = undefined; 1534 } 1535 endRender(); 1536 endUpdate(); 1537 { 1538 const childrenPromises = (_a = elm['s-p']) !== null && _a !== void 0 ? _a : []; 1539 const postUpdate = () => postUpdateComponent(hostRef); 1540 if (childrenPromises.length === 0) { 1541 postUpdate(); 1542 } 1543 else { 1544 Promise.all(childrenPromises).then(postUpdate); 1545 hostRef.$flags$ |= 4 /* HOST_FLAGS.isWaitingForChildren */; 1546 childrenPromises.length = 0; 1547 } 1548 } 1549}; 1550/** 1551 * Handle making the call to the VDom renderer with the proper context given 1552 * various build variables 1553 *
1554 * @param hostRef an object containing references to the element's host node, 1555 * VDom nodes, and other metadata 1556 * @param instance a reference to the underlying host element where it will be 1557 * rendered 1558 * @param elm the Host element for the component 1559 * @param isInitialLoad whether or not this function is being called as part of 1560 * @returns an empty promise 1561 */ 1562const callRender = (hostRef, instance, elm, isInitialLoad) => { 1563 try { 1564 instance = instance.render() ; 1565 { 1566 hostRef.$flags$ &= ~16 /* HOST_FLAGS.isQueuedForUpdate */; 1567 } 1568 { 1569 hostRef.$flags$ |= 2 /* HOST_FLAGS.hasRendered */; 1570 } 1571 { 1572 { 1573 // looks like we've got child nodes to render into this host element 1574 // or we need to update the css class/attrs on the host element 1575 // DOM WRITE! 1576 { 1577 renderVdom(hostRef, instance, isInitialLoad); 1578 } 1579 } 1580 } 1581 } 1582 catch (e) { 1583 consoleError(e, hostRef.$hostElement$); 1584 } 1585 return null; 1586}; 1587const postUpdateComponent = (hostRef) => { 1588 const tagName = hostRef.$cmpMeta$.$tagName$; 1589 const elm = hostRef.$hostElement$; 1590 const endPostUpdate = createTime('postUpdate', tagName); 1591 const instance = hostRef.$lazyInstance$ ; 1592 const ancestorComponent = hostRef.$ancestorComponent$; 1593 { 1594 safeCall(instance, 'componentDidRender'); 1595 } 1596 if (!(hostRef.$flags$ & 64 /* HOST_FLAGS.hasLoadedComponent */)) { 1597 hostRef.$flags$ |= 64 /* HOST_FLAGS.hasLoadedComponent */; 1598 { 1599 // DOM WRITE! 1600 addHydratedFlag(elm); 1601 } 1602 { 1603 safeCall(instance, 'componentDidLoad'); 1604 } 1605 endPostUpdate(); 1606 { 1607 hostRef.$onReadyResolve$(elm); 1608 if (!ancestorComponent) { 1609 appDidLoad(); 1610 } 1611 } 1612 } 1613 else { 1614 { 1615 safeCall(instance, 'componentDidUpdate'); 1616 } 1617 endPostUpdate(); 1618 } 1619 { 1620 hostRef.$onInstanceResolve$(elm); 1621 } 1622 // load events fire from bottom to top 1623 // the deepest elements load first then bubbles up 1624 { 1625 if (hostRef.$onRenderResolve$) { 1626 hostRef.$onRenderResolve$(); 1627 hostRef.$onRenderResolve$ = undefined; 1628 } 1629 if (hostRef.$flags$ & 512 /* HOST_FLAGS.needsRerender */) { 1630 nextTick(() => scheduleUpdate(hostRef, false)); 1631 } 1632 hostRef.$flags$ &= ~(4 /* HOST_FLAGS.isWaitingForChildren */ | 512 /* HOST_FLAGS.needsRerender */); 1633 } 1634 // ( â¢_â¢) 1635 // ( â¢_â¢)>ââ -â 1636 // (ââ _â ) 1637}; 1638const appDidLoad = (who) => { 1639 // on appload 1640 // we have finish the first big initial render 1641 { 1642 addHydratedFlag(doc.documentElement); 1643 } 1644 nextTick(() => emitEvent(win, 'appload', { detail: { namespace: NAMESPACE } })); 1645}; 1646const safeCall = (instance, method, arg) => { 1647 if (instance && instance[method]) { 1648 try { 1649 return instance[method](arg); 1650 } 1651 catch (e) { 1652 consoleError(e); 1653 } 1654 } 1655 return undefined
vendor: 5,186 bytes, lines 1655-1758
1655; 1656}; 1657const addHydratedFlag = (elm) => elm.classList.add('hydrated') 1658 ; 1659const getValue = (ref, propName) => getHostRef(ref).$instanceValues$.get(propName); 1660const setValue = (ref, propName, newVal, cmpMeta) => { 1661 // check our new property value against our internal value 1662 const hostRef = getHostRef(ref); 1663 const elm = hostRef.$hostElement$ ; 1664 const oldVal = hostRef.$instanceValues$.get(propName); 1665 const flags = hostRef.$flags$; 1666 const instance = hostRef.$lazyInstance$ ; 1667 newVal = parsePropertyValue(newVal, cmpMeta.$members$[propName][0]); 1668 // explicitly check for NaN on both sides, as `NaN === NaN` is always false 1669 const areBothNaN = Number.isNaN(oldVal) && Number.isNaN(newVal); 1670 const didValueChange = newVal !== oldVal && !areBothNaN; 1671 if ((!(flags & 8 /* HOST_FLAGS.isConstructingInstance */) || oldVal === undefined) && didValueChange) { 1672 // gadzooks! the property's value has changed!! 1673 // set our new value! 1674 hostRef.$instanceValues$.set(propName, newVal); 1675 if (instance) { 1676 // get an array of method names of watch functions to call 1677 if (cmpMeta.$watchers$ && flags & 128 /* HOST_FLAGS.isWatchReady */) { 1678 const watchMethods = cmpMeta.$watchers$[propName]; 1679 if (watchMethods) { 1680 // this instance is watching for when this property changed 1681 watchMethods.map((watchMethodName) => { 1682 try { 1683 // fire off each of the watch methods that are watching this property 1684 instance[watchMethodName](newVal, oldVal, propName); 1685 } 1686 catch (e) { 1687 consoleError(e, elm); 1688 } 1689 }); 1690 } 1691 } 1692 if ((flags & (2 /* HOST_FLAGS.hasRendered */ | 16 /* HOST_FLAGS.isQueuedForUpdate */)) === 2 /* HOST_FLAGS.hasRendered */) { 1693 // looks like this value actually changed, so we've got work to do! 1694 // but only if we've already rendered, otherwise just chill out 1695 // queue that we need to do an update, but don't worry about queuing 1696 // up millions cuz this function ensures it only runs once 1697 scheduleUpdate(hostRef, false); 1698 } 1699 } 1700 } 1701}; 1702/** 1703 * Attach a series of runtime constructs to a compiled Stencil component 1704 * constructor, including getters and setters for the `@Prop` and `@State` 1705 * decorators, callbacks for when attributes change, and so on. 1706 * 1707 * @param Cstr the constructor for a component that we need to process 1708 * @param cmpMeta metadata collected previously about the component 1709 * @param flags a number used to store a series of bit flags 1710 * @returns a reference to the same constructor passed in (but now mutated) 1711 */ 1712const proxyComponent = (Cstr, cmpMeta, flags) => { 1713 if (cmpMeta.$members$) { 1714 if (Cstr.watchers) { 1715 cmpMeta.$watchers$ = Cstr.watchers; 1716 } 1717 // It's better to have a const than two Object.entries() 1718 const members = Object.entries(cmpMeta.$members$); 1719 const prototype = Cstr.prototype; 1720 members.map(([memberName, [memberFlags]]) => { 1721 if ((memberFlags & 31 /* MEMBER_FLAGS.Prop */ || 1722 ((flags & 2 /* PROXY_FLAGS.proxyState */) && memberFlags & 32 /* MEMBER_FLAGS.State */))) { 1723 // proxyComponent - prop 1724 Object.defineProperty(prototype, memberName, { 1725 get() { 1726 // proxyComponent, get value 1727 return getValue(this, memberName); 1728 }, 1729 set(newValue) { 1730 // proxyComponent, set value 1731 setValue(this, memberName, newValue, cmpMeta); 1732 }, 1733 configurable: true, 1734 enumerable: true, 1735 }); 1736 } 1737 else if (flags & 1 /* PROXY_FLAGS.isElementConstructor */ && 1738 memberFlags & 64 /* MEMBER_FLAGS.Method */) { 1739 // proxyComponent - method 1740 Object.defineProperty(prototype, memberName, { 1741 value(...args) { 1742 const ref = getHostRef(this); 1743 return ref.$onInstancePromise$.then(() => ref.$lazyInstance$[memberName](...args)); 1744 }, 1745 }); 1746 } 1747 }); 1748 if ((flags & 1 /* PROXY_FLAGS.isElementConstructor */)) { 1749 const attrNameToPropName = new Map(); 1750 prototype.attributeChangedCallback = function (attrName, _oldValue, newValue) { 1751 plt.jmp(() => { 1752 const propName = attrNameToPropName.get(attrName); 1753 // In a web component lifecycle the attributeChangedCallback runs prior to connectedCallback 1754 // in the case where an attribute was set inline. 1755 // ```html 1756 // <my-component some-attribute="some-value"></my-component> 1757 // ``` 1758 //
vendor: 5,865 bytes, lines 1759-1864
1759 // There is an edge case where a developer sets the attribute inline on a custom element and then 1760 // programmatically changes it before it has been upgraded as shown below: 1761 // 1762 // ```html 1763 // <!-- this component has _not_ been upgraded yet --> 1764 // <my-component id="test" some-attribute="some-value"></my-component> 1765 // <script> 1766 // // grab non-upgraded component 1767 // el = document.querySelector("#test"); 1768 // el.someAttribute = "another-value"; 1769 // // upgrade component 1770 // customElements.define('my-component', MyComponent); 1771 // </script> 1772 // ``` 1773 // In this case if we do not unshadow here and use the value of the shadowing property, attributeChangedCallback 1774 // will be called with `newValue = "some-value"` and will set the shadowed property (this.someAttribute = "another-value") 1775 // to the value that was set inline i.e. "some-value" from above example. When 1776 // the connectedCallback attempts to unshadow it will use "some-value" as the initial value rather than "another-value" 1777 // 1778 // The case where the attribute was NOT set inline but was not set programmatically shall be handled/unshadowed 1779 // by connectedCallback as this attributeChangedCallback will not fire. 1780 // 1781 // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties 1782 // 1783 // TODO(STENCIL-16) we should think about whether or not we actually want to be reflecting the attributes to 1784 // properties here given that this goes against best practices outlined here 1785 // https://developers.google.com/web/fundamentals/web-components/best-practices#avoid-reentrancy 1786 if (this.hasOwnProperty(propName)) { 1787 newValue = this[propName]; 1788 delete this[propName]; 1789 } 1790 else if (prototype.hasOwnProperty(propName) && 1791 typeof this[propName] === 'number' && 1792 this[propName] == newValue) { 1793 // if the propName exists on the prototype of `Cstr`, this update may be a result of Stencil using native 1794 // APIs to reflect props as attributes. Calls to `setAttribute(someElement, propName)` will result in 1795 // `propName` to be converted to a `DOMString`, which may not be what we want for other primitive props. 1796 return; 1797 } 1798 this[propName] = newValue === null && typeof this[propName] === 'boolean' ? false : newValue; 1799 }); 1800 }; 1801 // create an array of attributes to observe 1802 // and also create a map of html attribute name to js property name 1803 Cstr.observedAttributes = members 1804 .filter(([_, m]) => m[0] & 15 /* MEMBER_FLAGS.HasAttribute */) // filter to only keep props that should match attributes 1805 .map(([propName, m]) => { 1806 const attrName = m[1] || propName; 1807 attrNameToPropName.set(attrName, propName); 1808 return attrName; 1809 }); 1810 } 1811 } 1812 return Cstr; 1813}; 1814const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId, Cstr) => { 1815 // initializeComponent 1816 if ((hostRef.$flags$ & 32 /* HOST_FLAGS.hasInitializedComponent */) === 0) { 1817 // Let the runtime know that the component has been initialized 1818 hostRef.$flags$ |= 32 /* HOST_FLAGS.hasInitializedComponent */; 1819 { 1820 // lazy loaded components 1821 // request the component's implementation to be 1822 // wired up with the host element 1823 Cstr = loadModule(cmpMeta); 1824 if (Cstr.then) { 1825 // Await creates a micro-task avoid if possible 1826 const endLoad = uniqueTime(); 1827 Cstr = await Cstr; 1828 endLoad(); 1829 } 1830 if (!Cstr.isProxied) { 1831 // we've never proxied this Constructor before 1832 // let's add the getters/setters to its prototype before 1833 // the first time we create an instance of the implementation 1834 { 1835 cmpMeta.$watchers$ = Cstr.watchers; 1836 } 1837 proxyComponent(Cstr, cmpMeta, 2 /* PROXY_FLAGS.proxyState */); 1838 Cstr.isProxied = true; 1839 } 1840 const endNewInstance = createTime('createInstance', cmpMeta.$tagName$); 1841 // ok, time to construct the instance 1842 // but let's keep track of when we start and stop 1843 // so that the getters/setters don't incorrectly step on data 1844 { 1845 hostRef.$flags$ |= 8 /* HOST_FLAGS.isConstructingInstance */; 1846 } 1847 // construct the lazy-loaded component implementation 1848 // passing the hostRef is very important during 1849 // construction in order to directly wire together the 1850 // host element and the lazy-loaded instance 1851 try { 1852 new Cstr(hostRef); 1853 } 1854 catch (e) { 1855 consoleError(e); 1856 } 1857 { 1858 hostRef.$flags$ &= ~8 /* HOST_FLAGS.isConstructingInstance */; 1859 } 1860 { 1861 hostRef.$flags$ |= 128 /* HOST_FLAGS.isWatchReady */; 1862 } 1863 endNewInstance(); 1864
vendor: 3,677 bytes, lines 1864-1935
1864 fireConnectedCallback(hostRef.$lazyInstance$); 1865 } 1866 if (Cstr.style) { 1867 // this component has styles but we haven't registered them yet 1868 let style = Cstr.style; 1869 const scopeId = getScopeId(cmpMeta); 1870 if (!styles.has(scopeId)) { 1871 const endRegisterStyles = createTime('registerStyles', cmpMeta.$tagName$); 1872 registerStyle(scopeId, style, !!(cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */)); 1873 endRegisterStyles(); 1874 } 1875 } 1876 } 1877 // we've successfully created a lazy instance 1878 const ancestorComponent = hostRef.$ancestorComponent$; 1879 const schedule = () => scheduleUpdate(hostRef, true); 1880 if (ancestorComponent && ancestorComponent['s-rc']) { 1881 // this is the initial load and this component it has an ancestor component 1882 // but the ancestor component has NOT fired its will update lifecycle yet 1883 // so let's just cool our jets and wait for the ancestor to continue first 1884 // this will get fired off when the ancestor component 1885 // finally gets around to rendering its lazy self 1886 // fire off the initial update 1887 ancestorComponent['s-rc'].push(schedule); 1888 } 1889 else { 1890 schedule(); 1891 } 1892}; 1893const fireConnectedCallback = (instance) => { 1894 { 1895 safeCall(instance, 'connectedCallback'); 1896 } 1897}; 1898const connectedCallback = (elm) => { 1899 if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) { 1900 const hostRef = getHostRef(elm); 1901 const cmpMeta = hostRef.$cmpMeta$; 1902 const endConnected = createTime('connectedCallback', cmpMeta.$tagName$); 1903 if (!(hostRef.$flags$ & 1 /* HOST_FLAGS.hasConnected */)) { 1904 // first time this component has connected 1905 hostRef.$flags$ |= 1 /* HOST_FLAGS.hasConnected */; 1906 { 1907 // initUpdate 1908 // if the slot polyfill is required we'll need to put some nodes 1909 // in here to act as original content anchors as we move nodes around 1910 // host element has been connected to the DOM 1911 if ((// TODO(STENCIL-854): Remove code related to legacy shadowDomShim field 1912 cmpMeta.$flags$ & (4 /* CMP_FLAGS.hasSlotRelocation */ | 8 /* CMP_FLAGS.needsShadowDomShim */))) { 1913 setContentReference(elm); 1914 } 1915 } 1916 { 1917 // find the first ancestor component (if there is one) and register 1918 // this component as one of the actively loading child components for its ancestor 1919 let ancestorComponent = elm; 1920 while ((ancestorComponent = ancestorComponent.parentNode || ancestorComponent.host)) { 1921 // climb up the ancestors looking for the first 1922 // component that hasn't finished its lifecycle update yet 1923 if (ancestorComponent['s-p']) { 1924 // we found this components first ancestor component 1925 // keep a reference to this component's ancestor component 1926 attachToAncestor(hostRef, (hostRef.$ancestorComponent$ = ancestorComponent)); 1927 break; 1928 } 1929 } 1930 } 1931 // Lazy properties 1932 // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties 1933 if (cmpMeta.$members$) { 1934 Object.entries(cmpMeta.$members$).map(([memberName, [memberFlags]]) => { 1935 if (memberFlags & 31 /* MEMBER_FLAGS.Prop */ && elm.hasOwnProperty(memberN
1935ame)) { 1936 const value = elm[memberName]; 1937 delete elm[memberName]; 1938 elm[memberName] = value; 1939 } 1940 }); 1941 } 1942 { 1943 initializeComponent(elm, hostRef, cmpMeta); 1944 } 1945 } 1946 else { 1947 // not the first time this has connected 1948 // reattach any event listeners to the host 1949 // since they would have been removed when disconnected 1950 addHostEventListeners(elm, hostRef, cmpMeta.$listeners$); 1951 // fire off connectedCallback() on component instance 1952 if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$lazyInstance$) { 1953 fireConnectedCallback(hostRef.$lazyInstance$); 1954 } 1955 else if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$onReadyPromise$) { 1956 hostRef.$onReadyPromise$.then(() => fireConnectedCallback(hostRef.$lazyInstance$)); 1957 } 1958 } 1959 endConnected(); 1960 } 1961}; 1962const setContentReference = (elm) => { 1963 // only required when we're NOT using native shadow dom (slot) 1964 // or this browser doesn't support native shadow dom 1965 // and this host element was NOT created with SSR 1966 // let's pick out the inner content for slot projection 1967 // create a node to represent where the original 1968 // content was first placed, which is useful later on 1969 const contentRefElm = (elm['s-cr'] = doc.createComment('')); 1970 contentRefElm['s-cn'] = true; 1971 elm.insertBefore(contentRefElm, elm.firstChild); 1972}; 1973const disconnectInstance = (instance) => { 1974 { 1975 safeCall(instance, 'disconnectedCallback'); 1976 } 1977}; 1978const disconnectedCallback = async (elm) => { 1979 if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) { 1980 const hostRef = getHostRef(elm); 1981 { 1982 if (hostRef.$rmListeners$) { 1983 hostRef.$rmListeners$.map((rmListener) => rmListener()); 1984 hostRef.$rmListeners$ = undefined; 1985 } 1986 } 1987 if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$lazyInstance$) { 1988 disconnectInstance(hostRef.$lazyInstance$); 1989 } 1990 else if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$onReadyPromise$) { 1991 hostRef.$onReadyPromise$.then(() => disconnectInstance(hostRef.$lazyInstance$)); 1992 } 1993 } 1994}; 1995const bootstrapLazy = (lazyBundles, options = {}) => { 1996 var _a; 1997 const endBootstrap = createTime(); 1998 const cmpTags = []; 1999 const exclude = options.exclude || []; 2000 const customElements = win.customElements; 2001 const head = doc.head; 2002 const metaCharset = /*@__PURE__*/ head.querySelector('meta[charset]'); 2003 const visibilityStyle = /*@__PURE__*/ doc.createElement('style'); 2004 const deferredConnectedCallbacks = []; 2005 let appLoadFallback; 2006 let isBootstrapping = true; 2007 Object.assign(plt, options); 2008 plt.$resourcesUrl$ = new URL(options.resourcesUrl || './', doc.baseURI).href; 2009 lazyBundles.map((lazyBundle) => { 2010 lazyBundle[1].map((compactMeta) => { 2011 const cmpMeta = { 2012 $flags$: compactMeta[0], 2013 $tagName$: compactMeta[1], 2014 $members$: compactMeta[2], 2015 $listeners$: compactMeta[3], 2016 }; 2017 { 2018 cmpMeta.$members$ = compactMeta[2]; 2019 } 2020 { 2021 cmpMeta.$listeners$ = compactMeta[3]; 2022 } 2023 { 2024 cmpMeta.$watchers$ = {}; 2025 } 2026 const tagName = cmpMeta.$tagName$; 2027 const HostElement = class extends HTMLElement { 2028 // StencilLazyHost 2029 constructor(self) { 2030 // @ts-ignore 2031 super(self); 2032 self = this; 2033 registerHost(self, cmpMeta); 2034 } 2035 connectedCallback() { 2036 if (appLoadFallback) { 2037 clearTimeout(appLoadFallback); 2038 appLoadFallback = null; 2039 } 2040 if (isBootstrapping) { 2041 // connectedCallback will be processed once all components have been registered 2042 deferredConnectedCallbacks.push(this); 2043 } 2044 else { 2045 plt.jmp(() => connectedCallback(this)); 2046 } 2047 } 2048 disconnectedCallback() { 2049 plt.jmp(() => disconnectedCallback(this)); 2050 } 2051 componentOnReady() { 2052 return getHostRef(this).$onReadyPromise$; 2053 } 2054 }; 2055 cmpMeta.$lazyBundleId$ = lazyBundle[0]; 2056 if (!exclude.includes(tagName) && !customElements.get(tagName)) { 2057 cmpTags.push(tagName); 2058 customElements.define(tagName, proxyComponent(HostElement, cmpMeta, 1 /* PROXY_FLAGS.isElementConstructor */)); 2059 } 2060 }); 2061 }); 2062 {
vendor: 6,478 bytes, lines 2063-2241
2063 visibilityStyle.innerHTML = cmpTags + HYDRATED_CSS; 2064 visibilityStyle.setAttribute('data-styles', ''); 2065 // Apply CSP nonce to the style tag if it exists 2066 const nonce = (_a = plt.$nonce$) !== null && _a !== void 0 ? _a : queryNonceMetaTagContent(doc); 2067 if (nonce != null) { 2068 visibilityStyle.setAttribute('nonce', nonce); 2069 } 2070 head.insertBefore(visibilityStyle, metaCharset ? metaCharset.nextSibling : head.firstChild); 2071 } 2072 // Process deferred connectedCallbacks now all components have been registered 2073 isBootstrapping = false; 2074 if (deferredConnectedCallbacks.length) { 2075 deferredConnectedCallbacks.map((host) => host.connectedCallback()); 2076 } 2077 else { 2078 { 2079 plt.jmp(() => (appLoadFallback = setTimeout(appDidLoad, 30))); 2080 } 2081 } 2082 // Fallback appLoad event 2083 endBootstrap(); 2084}; 2085const Fragment = (_, children) => children; 2086const addHostEventListeners = (elm, hostRef, listeners, attachParentListeners) => { 2087 if (listeners) { 2088 listeners.map(([flags, name, method]) => { 2089 const target = getHostListenerTarget(elm, flags) ; 2090 const handler = hostListenerProxy(hostRef, method); 2091 const opts = hostListenerOpts(flags); 2092 plt.ael(target, name, handler, opts); 2093 (hostRef.$rmListeners$ = hostRef.$rmListeners$ || []).push(() => plt.rel(target, name, handler, opts)); 2094 }); 2095 } 2096}; 2097const hostListenerProxy = (hostRef, methodName) => (ev) => { 2098 try { 2099 { 2100 if (hostRef.$flags$ & 256 /* HOST_FLAGS.isListenReady */) { 2101 // instance is ready, let's call it's member method for this event 2102 hostRef.$lazyInstance$[methodName](ev); 2103 } 2104 else { 2105 (hostRef.$queuedListeners$ = hostRef.$queuedListeners$ || []).push([methodName, ev]); 2106 } 2107 } 2108 } 2109 catch (e) { 2110 consoleError(e); 2111 } 2112}; 2113const getHostListenerTarget = (elm, flags) => { 2114 if (flags & 8 /* LISTENER_FLAGS.TargetWindow */) 2115 return win; 2116 if (flags & 16 /* LISTENER_FLAGS.TargetBody */) 2117 return doc.body; 2118 return elm; 2119}; 2120// prettier-ignore 2121const hostListenerOpts = (flags) => (flags & 2 /* LISTENER_FLAGS.Capture */) !== 0; 2122/** 2123 * Assigns the given value to the nonce property on the runtime platform object. 2124 * During runtime, this value is used to set the nonce attribute on all dynamically created script and style tags. 2125 * @param nonce The value to be assigned to the platform nonce property. 2126 * @returns void 2127 */ 2128const setNonce = (nonce) => (plt.$nonce$ = nonce); 2129const hostRefs = /*@__PURE__*/ new WeakMap(); 2130const getHostRef = (ref) => hostRefs.get(ref); 2131const registerInstance = (lazyInstance, hostRef) => hostRefs.set((hostRef.$lazyInstance$ = lazyInstance), hostRef); 2132const registerHost = (elm, cmpMeta) => { 2133 const hostRef = { 2134 $flags$: 0, 2135 $hostElement$: elm, 2136 $cmpMeta$: cmpMeta, 2137 $instanceValues$: new Map(), 2138 }; 2139 { 2140 hostRef.$onInstancePromise$ = new Promise((r) => (hostRef.$onInstanceResolve$ = r)); 2141 } 2142 { 2143 hostRef.$onReadyPromise$ = new Promise((r) => (hostRef.$onReadyResolve$ = r)); 2144 elm['s-p'] = []; 2145 elm['s-rc'] = []; 2146 } 2147 addHostEventListeners(elm, hostRef, cmpMeta.$listeners$); 2148 return hostRefs.set(elm, hostRef); 2149}; 2150const isMemberInElement = (elm, memberName) => memberName in elm; 2151const consoleError = (e, el) => (0, console.error)(e, el); 2152const cmpModules = /*@__PURE__*/ new Map(); 2153const loadModule = (cmpMeta, hostRef, hmrVersionId) => { 2154 // loadModuleImport 2155 const exportName = cmpMeta.$tagName$.replace(/-/g, '_'); 2156 const bundleId = cmpMeta.$lazyBundleId$; 2157 const module = cmpModules.get(bundleId) ; 2158 if (module) { 2159 return module[exportName]; 2160 } 2161 /*!__STENCIL_STATIC_IMPORT_SWITCH__*/ 2162 return import( 2163 /* @vite-ignore */ 2164 /* webpackInclude: /\.entry\.js$/ */ 2165 /* webpackExclude: /\.system\.entry\.js$/ */ 2166 /* webpackMode: "lazy" */ 2167 `./${bundleId}.entry.js${''}`).then((importedModule) => { 2168 { 2169 cmpModules.set(bundleId, importedModule); 2170 } 2171 return importedModule[exportName]; 2172 }, consoleError); 2173}; 2174const styles = /*@__PURE__*/ new Map(); 2175const win = typeof window !== 'undefined' ? window : {}; 2176const doc = win.document || { head: {} }; 2177const plt = { 2178 $flags$: 0, 2179 $resourcesUrl$: '', 2180 jmp: (h) => h(), 2181 raf: (h) => requestAnimationFrame(h), 2182 ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts), 2183 rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts), 2184 ce: (eventName, opts) => new CustomEvent(eventName, opts), 2185}; 2186const promiseResolve = (v) => Promise.resolve(v); 2187const supportsConstructableStylesheets = /*@__PURE__*/ (() => { 2188 try { 2189 new CSSStyleSheet(); 2190 return typeof new CSSStyleSheet().replaceSync === 'function'; 2191 } 2192 catch (e) { } 2193 return false; 2194 })() 2195 ; 2196const queueDomReads = []; 2197const queueDomWrites = []; 2198const queueTask = (queue, write) => (cb) => { 2199 queue.push(cb); 2200 if (!queuePending) { 2201 queuePending = true; 2202 if (write && plt.$flags$ & 4 /* PLATFORM_FLAGS.queueSync */) { 2203 nextTick(flush); 2204 } 2205 else { 2206 plt.raf(flush); 2207 } 2208 } 2209}; 2210const consume = (queue) => { 2211 for (let i = 0; i < queue.length; i++) { 2212 try { 2213 queue[i](performance.now()); 2214 } 2215 catch (e) { 2216 consoleError(e); 2217 } 2218 } 2219 queue.length = 0; 2220}; 2221const flush = () => { 2222 // always force a bunch of medium callbacks to run, but still have 2223 // a throttle on how many can run in a certain time 2224 // DOM READS!!! 2225 consume(queueDomReads); 2226 // DOM WRITES!!! 2227 { 2228 consume(queueDomWrites); 2229 if ((queuePending = queueDomReads.length > 0)) { 2230 // still more to do yet, but we've run out of time 2231 // let's let this thing cool off and try again in the next tick 2232 plt.raf(flush); 2233 } 2234 } 2235}; 2236const nextTick = /*@__PURE__*/ (cb) => promiseResolve().then(cb); 2237const writeTask = /*@__PURE__*/ queueTask(queueDomWrites, true); 2238 2239export { Fragment as F, Host as H, getAssetPath as a, bootstrapLazy as b, createEvent as c, getElement as g, h, promiseResolve as p, registerInstance as r, setNonce as s }; 2240 2241//# sourceMappingURL=index-07e11767.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.