From 88a40177de9be5d117a21e3da5414bd777872544 Mon Sep 17 00:00:00 2001 From: Justin Fagnani Date: Wed, 18 Jan 2023 11:43:10 -0800 Subject: [PATCH] Better hydration error messages (#3583) --- .changeset/wicked-baboons-pull.md | 5 ++++ packages/lit-html/src/experimental-hydrate.ts | 27 ++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 .changeset/wicked-baboons-pull.md diff --git a/.changeset/wicked-baboons-pull.md b/.changeset/wicked-baboons-pull.md new file mode 100644 index 0000000000..b2be348d1b --- /dev/null +++ b/.changeset/wicked-baboons-pull.md @@ -0,0 +1,5 @@ +--- +'lit-html': patch +--- + +Add more detail to some hydration errors diff --git a/packages/lit-html/src/experimental-hydrate.ts b/packages/lit-html/src/experimental-hydrate.ts index 670f07860a..4df91a1a34 100644 --- a/packages/lit-html/src/experimental-hydrate.ts +++ b/packages/lit-html/src/experimental-hydrate.ts @@ -131,6 +131,9 @@ export const hydrate = ( // it in the parts cache. let rootPart: ChildPart | undefined = undefined; + // Used for error messages + let rootPartMarker: Comment | undefined = undefined; + // When we are in-between ChildPart markers, this is the current ChildPart. // It's needed to be able to set the ChildPart's endNode when we see a // close marker @@ -153,11 +156,16 @@ export const hydrate = ( const markerText = marker.data; if (markerText.startsWith('lit-part')) { if (stack.length === 0 && rootPart !== undefined) { - throw new Error('there must be only one root part per container'); + throw new Error( + `There must be only one root part per container. ` + + `Found a part marker (${marker}) when we already have a root ` + + `part marker (${rootPartMarker})` + ); } // Create a new ChildPart and push it onto the stack currentChildPart = openChildPart(rootValue, marker, stack, options); rootPart ??= currentChildPart; + rootPartMarker ??= marker; } else if (markerText.startsWith('lit-node')) { // Create and hydrate attribute parts into the current ChildPart on the // stack @@ -170,11 +178,18 @@ export const hydrate = ( currentChildPart = closeChildPart(marker, currentChildPart, stack); } } - console.assert( - rootPart !== undefined, - 'there should be exactly one root part in a render container' - ); - // This property needs to remain unminified. + if (rootPart === undefined) { + const elementMessage = + container instanceof ShadowRoot + ? `{container.host.localName}'s shadow root` + : container instanceof DocumentFragment + ? 'DocumentFragment' + : container.localName; + console.error( + `There should be exactly one root part in a render container, ` + + `but we didn't find any in ${elementMessage}.` + ); + } // This property needs to remain unminified. // eslint-disable-next-line @typescript-eslint/no-explicit-any (container as any)['_$litPart$'] = rootPart; };