Skip to content

Commit

Permalink
Don't throw if ChildPart.parentNode is null (#3615)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinfagnani committed Feb 2, 2023
1 parent 1d8a38e commit 4d69843
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/early-snakes-complain.md
@@ -0,0 +1,5 @@
---
'lit-html': patch
---

Don't throw in `ChildPart.parentNode` if the `parentNode` is null
2 changes: 1 addition & 1 deletion packages/lit-html/src/lit-html.ts
Expand Up @@ -1318,7 +1318,7 @@ class ChildPart implements Disconnectable {
const parent = this._$parent;
if (
parent !== undefined &&
parentNode.nodeType === 11 /* Node.DOCUMENT_FRAGMENT */
parentNode?.nodeType === 11 /* Node.DOCUMENT_FRAGMENT */
) {
// If the parentNode is a DocumentFragment, it may be because the DOM is
// still in the cloned fragment during initial render; if so, get the real
Expand Down
21 changes: 21 additions & 0 deletions packages/lit-html/src/test/lit-html_test.ts
Expand Up @@ -1715,7 +1715,12 @@ suite('lit-html', () => {
});

suite('ChildPart invariants for parentNode, startNode, endNode', () => {
// Let's us get a reference to a directive instance
let currentDirective: CheckNodePropertiesBehavior;

class CheckNodePropertiesBehavior extends Directive {
part?: ChildPart;

render(_parentId?: string, _done?: (err?: unknown) => void) {
return nothing;
}
Expand All @@ -1724,6 +1729,9 @@ suite('lit-html', () => {
part: ChildPart,
[parentId, done]: DirectiveParameters<this>
) {
this.part = part;
// eslint-disable-next-line
currentDirective = this;
try {
const {parentNode, startNode, endNode} = part;

Expand Down Expand Up @@ -1822,6 +1830,19 @@ suite('lit-html', () => {
await asyncCheckDivRendered;
});

test(`when the parentNode is null`, async () => {
const template = () => html`${checkPart('container')}`;

// Render the template to instantiate the directive
render(template(), container);

// Manually clear the container to detach the directive
container.innerHTML = '';

// Check that we can access parentNode
assert.equal(currentDirective.part!.parentNode, undefined);
});

test(`part's parentNode is correct when rendered into a document fragment`, async () => {
const fragment = document.createDocumentFragment();
(fragment as unknown as {id: string}).id = 'fragment';
Expand Down

0 comments on commit 4d69843

Please sign in to comment.