From a82d678a6be173f3235f253e36a1c65bdeaf96d8 Mon Sep 17 00:00:00 2001 From: lizarusi Date: Thu, 13 Aug 2026 13:40:20 +0200 Subject: [PATCH 1/2] Add failing tests: outerHTML morph of a text or comment oldNode throws TypeError --- test/core.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/core.js b/test/core.js index 5e10210..7d559c8 100644 --- a/test/core.js +++ b/test/core.js @@ -121,6 +121,28 @@ describe("Core morphing tests", function () { ); }); + it("morphs outerHTML properly when oldNode is a text node", function () { + let parent = make("
Foo
"); + let initial = parent.firstChild; + Idiomorph.morph(initial, "", { + morphStyle: "outerHTML", + }); + parent.innerHTML.should.equal(""); + }); + + it("morphs outerHTML properly when oldNode is a comment node", function () { + let parent = make( + "

Before

After

", + ); + let initial = parent.childNodes[1]; + Idiomorph.morph(initial, "", { + morphStyle: "outerHTML", + }); + parent.innerHTML.should.equal( + "

Before

After

", + ); + }); + it("morphs innerHTML as content properly when argument is null", function () { let initial = make("
Foo
"); Idiomorph.morph(initial, null, { morphStyle: "innerHTML" }); From e68de56ebdb8095ae56bb862a7f34962cb31291b Mon Sep 17 00:00:00 2001 From: lizarusi Date: Thu, 13 Aug 2026 13:40:52 +0200 Subject: [PATCH 2/2] Guard findIdElements against roots without querySelectorAll Morphing a text or comment node with morphStyle: "outerHTML" throws "TypeError: root.querySelectorAll is not a function", because morph() passes the raw oldNode into createIdMaps -> findIdElements. Guarding with optional chaining (same pattern as the getAttribute guard below) lets the morph proceed; the rest of the algorithm already handles non-element nodes correctly. --- src/idiomorph.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/idiomorph.js b/src/idiomorph.js index 257c040..ab21454 100644 --- a/src/idiomorph.js +++ b/src/idiomorph.js @@ -1085,7 +1085,8 @@ var Idiomorph = (function () { * @returns {Element[]} */ function findIdElements(root) { - let elements = Array.from(root.querySelectorAll("[id]")); + // root could be a text or comment node which doesn't have `querySelectorAll` + let elements = Array.from(root.querySelectorAll?.("[id]") ?? []); // root could be a document fragment which doesn't have `getAttribute` if (root.getAttribute?.("id")) { elements.push(root);