{"version":3,"file":"experimental-hydrate.js","sources":["src/experimental-hydrate.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport type {TemplateResult} from './lit-html.js';\n\nimport {noChange, RenderOptions, _$LH} from './lit-html.js';\nimport {AttributePartInfo, PartType} from './directive.js';\nimport {\n isPrimitive,\n isSingleExpression,\n isTemplateResult,\n isCompiledTemplateResult,\n} from './directive-helpers.js';\n\n// In the Node build, this import will be injected by Rollup:\n// import {Buffer} from 'buffer';\n\nconst NODE_MODE = false;\n\nconst {\n _TemplateInstance: TemplateInstance,\n _isIterable: isIterable,\n _resolveDirective: resolveDirective,\n _ChildPart: ChildPart,\n _ElementPart: ElementPart,\n} = _$LH;\n\ntype ChildPart = InstanceType;\ntype TemplateInstance = InstanceType;\n\n/**\n * Information needed to rehydrate a single TemplateResult.\n */\ntype ChildPartState =\n | {\n type: 'leaf';\n /** The ChildPart that the result is rendered to */\n part: ChildPart;\n }\n | {\n type: 'iterable';\n /** The ChildPart that the result is rendered to */\n part: ChildPart;\n value: Iterable;\n iterator: Iterator;\n done: boolean;\n }\n | {\n type: 'template-instance';\n /** The ChildPart that the result is rendered to */\n part: ChildPart;\n\n result: TemplateResult;\n\n /** The TemplateInstance created from the TemplateResult */\n instance: TemplateInstance;\n\n /**\n * The index of the next Template part to be hydrated. This is mutable and\n * updated as the tree walk discovers new part markers at the right level in\n * the template instance tree. Note there is only one Template part per\n * attribute with (one or more) bindings.\n */\n templatePartIndex: number;\n\n /**\n * The index of the next TemplateInstance part to be hydrated. This is used\n * to retrieve the value from the TemplateResult and initialize the\n * TemplateInstance parts' values for dirty-checking on first render.\n */\n instancePartIndex: number;\n };\n\n/**\n * hydrate() operates on a container with server-side rendered content and\n * restores the client side data structures needed for lit-html updates such as\n * TemplateInstances and Parts. After calling `hydrate`, lit-html will behave as\n * if it initially rendered the DOM, and any subsequent updates will update\n * efficiently, the same as if lit-html had rendered the DOM on the client.\n *\n * hydrate() must be called on DOM that adheres the to lit-ssr structure for\n * parts. ChildParts must be represented with both a start and end comment\n * marker, and ChildParts that contain a TemplateInstance must have the template\n * digest written into the comment data.\n *\n * Since render() encloses its output in a ChildPart, there must always be a root\n * ChildPart.\n *\n * Example (using for # ... for annotations in HTML)\n *\n * Given this input:\n *\n * html`
${y}
`\n *\n * The SSR DOM is:\n *\n * # Start marker for the root ChildPart created\n * # by render(). Includes the digest of the\n * # template\n *
\n * # Indicates there are attribute bindings here\n * # The number is the depth-first index of the parent\n * # node in the template.\n * # Start marker for the ${x} expression\n * TEST_Y\n * # End marker for the ${x} expression\n *
\n *\n * # End marker for the root ChildPart\n *\n * @param rootValue\n * @param container\n * @param userOptions\n *\n * @deprecated This has been moved to `@lit-labs/ssr-client` and will be removed\n * in a future release.\n */\nexport const hydrate = (\n rootValue: unknown,\n container: Element | DocumentFragment,\n options: Partial = {}\n) => {\n console.warn(\n 'Importing `hydrate()` from `lit-html/experimental-hydrate.js` is deprecated.' +\n 'Import from `@lit-labs/ssr-client` instead.'\n );\n\n // TODO(kschaaf): Do we need a helper for _$litPart$ (\"part for node\")?\n // This property needs to remain unminified.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((container as any)['_$litPart$'] !== undefined) {\n throw new Error('container already contains a live render');\n }\n\n // Since render() creates a ChildPart to render into, we'll always have\n // exactly one root part. We need to hold a reference to it so we can set\n // it in the parts cache.\n let rootPart: ChildPart | undefined = undefined;\n\n // Used for error messages\n let rootPartMarker: Comment | undefined = undefined;\n\n // When we are in-between ChildPart markers, this is the current ChildPart.\n // It's needed to be able to set the ChildPart's endNode when we see a\n // close marker\n let currentChildPart: ChildPart | undefined = undefined;\n\n // Used to remember parent template state as we recurse into nested\n // templates\n const stack: Array = [];\n\n const walker = document.createTreeWalker(\n container,\n NodeFilter.SHOW_COMMENT,\n null,\n false\n );\n let marker: Comment | null;\n\n // Walk the DOM looking for part marker comments\n while ((marker = walker.nextNode() as Comment | null) !== null) {\n const markerText = marker.data;\n if (markerText.startsWith('lit-part')) {\n if (stack.length === 0 && rootPart !== undefined) {\n throw new Error(\n `There must be only one root part per container. ` +\n `Found a part marker (${marker}) when we already have a root ` +\n `part marker (${rootPartMarker})`\n );\n }\n // Create a new ChildPart and push it onto the stack\n currentChildPart = openChildPart(rootValue, marker, stack, options);\n rootPart ??= currentChildPart;\n rootPartMarker ??= marker;\n } else if (markerText.startsWith('lit-node')) {\n // Create and hydrate attribute parts into the current ChildPart on the\n // stack\n createAttributeParts(marker, stack, options);\n } else if (markerText.startsWith('/lit-part')) {\n // Close the current ChildPart, and pop the previous one off the stack\n if (stack.length === 1 && currentChildPart !== rootPart) {\n throw new Error('internal error');\n }\n currentChildPart = closeChildPart(marker, currentChildPart, stack);\n }\n }\n if (rootPart === undefined) {\n const elementMessage =\n container instanceof ShadowRoot\n ? `{container.host.localName}'s shadow root`\n : container instanceof DocumentFragment\n ? 'DocumentFragment'\n : container.localName;\n console.error(\n `There should be exactly one root part in a render container, ` +\n `but we didn't find any in ${elementMessage}.`\n );\n } // This property needs to remain unminified.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (container as any)['_$litPart$'] = rootPart;\n};\n\nconst openChildPart = (\n rootValue: unknown,\n marker: Comment,\n stack: Array,\n options: RenderOptions\n) => {\n let value: unknown;\n // We know the startNode now. We'll know the endNode when we get to\n // the matching marker and set it in closeChildPart()\n // TODO(kschaaf): Current constructor takes both nodes\n let part;\n if (stack.length === 0) {\n part = new ChildPart(marker, null, undefined, options);\n value = rootValue;\n } else {\n const state = stack[stack.length - 1];\n if (state.type === 'template-instance') {\n part = new ChildPart(marker, null, state.instance, options);\n state.instance._$parts.push(part);\n value = state.result.values[state.instancePartIndex++];\n state.templatePartIndex++;\n } else if (state.type === 'iterable') {\n part = new ChildPart(marker, null, state.part, options);\n const result = state.iterator.next();\n if (result.done) {\n value = undefined;\n state.done = true;\n throw new Error('Unhandled shorter than expected iterable');\n } else {\n value = result.value;\n }\n (state.part._$committedValue as Array).push(part);\n } else {\n // state.type === 'leaf'\n // TODO(kschaaf): This is unexpected, and likely a result of a primitive\n // been rendered on the client when a TemplateResult was rendered on the\n // server; this part will be hydrated but not used. We can detect it, but\n // we need to decide what to do in this case. Note that this part won't be\n // retained by any parent TemplateInstance, since a primitive had been\n // rendered in its place.\n // https://github.com/lit/lit/issues/1434\n // throw new Error('Hydration value mismatch: Found a TemplateInstance' +\n // 'where a leaf value was expected');\n part = new ChildPart(marker, null, state.part, options);\n }\n }\n\n // Initialize the ChildPart state depending on the type of value and push\n // it onto the stack. This logic closely follows the ChildPart commit()\n // cascade order:\n // 1. directive\n // 2. noChange\n // 3. primitive (note strings must be handled before iterables, since they\n // are iterable)\n // 4. TemplateResult\n // 5. Node (not yet implemented, but fallback handling is fine)\n // 6. Iterable\n // 7. nothing (handled in fallback)\n // 8. Fallback for everything else\n value = resolveDirective(part, value);\n if (value === noChange) {\n stack.push({part, type: 'leaf'});\n } else if (isPrimitive(value)) {\n stack.push({part, type: 'leaf'});\n part._$committedValue = value;\n // TODO(kschaaf): We can detect when a primitive is being hydrated on the\n // client where a TemplateResult was rendered on the server, but we need to\n // decide on a strategy for what to do next.\n // https://github.com/lit/lit/issues/1434\n // if (marker.data !== 'lit-part') {\n // throw new Error('Hydration value mismatch: Primitive found where TemplateResult expected');\n // }\n } else if (isTemplateResult(value)) {\n if (isCompiledTemplateResult(value)) {\n throw new Error('compiled templates are not supported');\n }\n // Check for a template result digest\n const markerWithDigest = `lit-part ${digestForTemplateResult(value)}`;\n if (marker.data === markerWithDigest) {\n const template = ChildPart.prototype._$getTemplate(value);\n const instance = new TemplateInstance(template, part);\n stack.push({\n type: 'template-instance',\n instance,\n part,\n templatePartIndex: 0,\n instancePartIndex: 0,\n result: value,\n });\n // For TemplateResult values, we set the part value to the\n // generated TemplateInstance\n part._$committedValue = instance;\n } else {\n // TODO: if this isn't the server-rendered template, do we\n // need to stop hydrating this subtree? Clear it? Add tests.\n throw new Error(\n 'Hydration value mismatch: Unexpected TemplateResult rendered to part'\n );\n }\n } else if (isIterable(value)) {\n // currentChildPart.value will contain an array of ChildParts\n stack.push({\n part: part,\n type: 'iterable',\n value,\n iterator: value[Symbol.iterator](),\n done: false,\n });\n part._$committedValue = [];\n } else {\n // Fallback for everything else (nothing, Objects, Functions,\n // etc.): we just initialize the part's value\n // Note that `Node` value types are not currently supported during\n // SSR, so that part of the cascade is missing.\n stack.push({part: part, type: 'leaf'});\n part._$committedValue = value == null ? '' : value;\n }\n return part;\n};\n\nconst closeChildPart = (\n marker: Comment,\n part: ChildPart | undefined,\n stack: Array\n): ChildPart | undefined => {\n if (part === undefined) {\n throw new Error('unbalanced part marker');\n }\n\n part._$endNode = marker;\n\n const currentState = stack.pop()!;\n\n if (currentState.type === 'iterable') {\n if (!currentState.iterator.next().done) {\n throw new Error('unexpected longer than expected iterable');\n }\n }\n\n if (stack.length > 0) {\n const state = stack[stack.length - 1];\n return state.part;\n } else {\n return undefined;\n }\n};\n\nconst createAttributeParts = (\n comment: Comment,\n stack: Array,\n options: RenderOptions\n) => {\n // Get the nodeIndex from DOM. We're only using this for an integrity\n // check right now, we might not need it.\n const match = /lit-node (\\d+)/.exec(comment.data)!;\n const nodeIndex = parseInt(match[1]);\n\n // Node markers are added as a previous sibling to identify elements\n // with attribute/property/element/event bindings or custom elements\n // whose `defer-hydration` attribute needs to be removed\n const node = comment.nextElementSibling;\n if (node === null) {\n throw new Error('could not find node for attribute parts');\n }\n // Remove `defer-hydration` attribute, if any\n node.removeAttribute('defer-hydration');\n\n const state = stack[stack.length - 1];\n if (state.type === 'template-instance') {\n const instance = state.instance;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n // If the next template part is in attribute-position on the current node,\n // create the instance part for it and prime its state\n const templatePart = instance._$template.parts[state.templatePartIndex];\n if (\n templatePart === undefined ||\n (templatePart.type !== PartType.ATTRIBUTE &&\n templatePart.type !== PartType.ELEMENT) ||\n templatePart.index !== nodeIndex\n ) {\n break;\n }\n\n if (templatePart.type === PartType.ATTRIBUTE) {\n // The instance part is created based on the constructor saved in the\n // template part\n const instancePart = new templatePart.ctor(\n node as HTMLElement,\n templatePart.name,\n templatePart.strings,\n state.instance,\n options\n );\n\n const value = isSingleExpression(\n instancePart as unknown as AttributePartInfo\n )\n ? state.result.values[state.instancePartIndex]\n : state.result.values;\n\n // Setting the attribute value primes committed value with the resolved\n // directive value; we only then commit that value for event/property\n // parts since those were not serialized, and pass `noCommit` for the\n // others to avoid perf impact of touching the DOM unnecessarily\n const noCommit = !(\n instancePart.type === PartType.EVENT ||\n instancePart.type === PartType.PROPERTY\n );\n instancePart._$setValue(\n value,\n instancePart,\n state.instancePartIndex,\n noCommit\n );\n state.instancePartIndex += templatePart.strings.length - 1;\n instance._$parts.push(instancePart);\n } else {\n // templatePart.type === PartType.ELEMENT\n const instancePart = new ElementPart(node, state.instance, options);\n resolveDirective(\n instancePart,\n state.result.values[state.instancePartIndex++]\n );\n instance._$parts.push(instancePart);\n }\n state.templatePartIndex++;\n }\n } else {\n throw new Error('internal error');\n }\n};\n\n// Number of 32 bit elements to use to create template digests\nconst digestSize = 2;\n// We need to specify a digest to use across rendering environments. This is a\n// simple digest build from a DJB2-ish hash modified from:\n// https://github.com/darkskyapp/string-hash/blob/master/index.js\n// It has been changed to an array of hashes to add additional bits.\n// Goals:\n// - Extremely low collision rate. We may not be able to detect collisions.\n// - Extremely fast.\n// - Extremely small code size.\n// - Safe to include in HTML comment text or attribute value.\n// - Easily specifiable and implementable in multiple languages.\n// We don't care about cryptographic suitability.\nexport const digestForTemplateResult = (templateResult: TemplateResult) => {\n const hashes = new Uint32Array(digestSize).fill(5381);\n\n for (const s of templateResult.strings) {\n for (let i = 0; i < s.length; i++) {\n hashes[i % digestSize] = (hashes[i % digestSize] * 33) ^ s.charCodeAt(i);\n }\n }\n const str = String.fromCharCode(...new Uint8Array(hashes.buffer));\n // Use `btoa` in browsers because it is supported universally.\n //\n // In Node, we are sometimes executing in an isolated VM context, which means\n // neither `btoa` nor `Buffer` will be globally available by default (also\n // note that `btoa` is only supported in Node 16+ anyway, and we still support\n // Node 14). Instead of requiring users to always provide an implementation\n // for `btoa` when they set up their VM context, we instead inject an import\n // for `Buffer` from Node's built-in `buffer` module in our Rollup config (see\n // note at the top of this file), and use that.\n return NODE_MODE ? Buffer.from(str, 'binary').toString('base64') : btoa(str);\n};\n"],"names":["_TemplateInstance","TemplateInstance","_isIterable","isIterable","_resolveDirective","resolveDirective","_ChildPart","ChildPart","_ElementPart","ElementPart","_$LH","hydrate","rootValue","container","options","console","warn","undefined","Error","rootPart","rootPartMarker","currentChildPart","stack","walker","document","createTreeWalker","NodeFilter","SHOW_COMMENT","marker","nextNode","markerText","data","startsWith","length","openChildPart","createAttributeParts","closeChildPart","elementMessage","ShadowRoot","DocumentFragment","localName","error","value","part","state","type","instance","_$parts","push","result","values","instancePartIndex","templatePartIndex","iterator","next","done","_$committedValue","noChange","isPrimitive","isTemplateResult","isCompiledTemplateResult","markerWithDigest","digestForTemplateResult","template","prototype","_$getTemplate","Symbol","_$endNode","currentState","pop","comment","match","exec","nodeIndex","parseInt","node","nextElementSibling","removeAttribute","templatePart","_$template","parts","PartType","ATTRIBUTE","ELEMENT","index","instancePart","ctor","name","strings","isSingleExpression","noCommit","EVENT","PROPERTY","_$setValue","templateResult","hashes","Uint32Array","fill","s","i","charCodeAt","str","String","fromCharCode","Uint8Array","buffer","btoa"],"mappings":"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"}