From 93fda88ed154da092665cebf317d6685be9cb09b Mon Sep 17 00:00:00 2001 From: Carson Gross Date: Sun, 22 Feb 2026 10:11:38 -0700 Subject: [PATCH] handle bad scroll selectors gracefully --- src/htmx.js | 12 ++++++----- test/tests/unit/__issueRequest.js | 34 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/htmx.js b/src/htmx.js index e75c975e..e0974c98 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -1128,15 +1128,17 @@ var htmx = (() => { __handleScroll(swapSpec, target) { if (swapSpec.scroll) { let scrollTarget = swapSpec.scrollTarget ? this.__findExt(swapSpec.scrollTarget) : target; - if (swapSpec.scroll === 'top') { - scrollTarget.scrollTop = 0; - } else if (swapSpec.scroll === 'bottom'){ - scrollTarget.scrollTop = scrollTarget.scrollHeight; + if (scrollTarget) { + if (swapSpec.scroll === 'top') { + scrollTarget.scrollTop = 0; + } else if (swapSpec.scroll === 'bottom'){ + scrollTarget.scrollTop = scrollTarget.scrollHeight; + } } } if (swapSpec.show) { let showTarget = swapSpec.showTarget ? this.__findExt(swapSpec.showTarget) : target; - showTarget.scrollIntoView(swapSpec.show === 'top') + showTarget?.scrollIntoView(swapSpec.show === 'top') } } diff --git a/test/tests/unit/__issueRequest.js b/test/tests/unit/__issueRequest.js index 6aef41ce..f4c439ce 100644 --- a/test/tests/unit/__issueRequest.js +++ b/test/tests/unit/__issueRequest.js @@ -258,6 +258,40 @@ describe('__issueRequest unit tests', function() { assert.isTrue(ctx.request.signal.aborted) }) + it('does not crash when scroll target selector matches nothing', async function () { + let div = createProcessedHTML('
') + let ctx = htmx.__createRequestContext(div, new Event('click')) + + ctx.fetch = async () => ({ + status: 200, + headers: new Headers(), + text: async () => '
Response
' + }) + + let errorFired = false + div.addEventListener('htmx:error', () => errorFired = true) + + await htmx.__issueRequest(ctx) + assert.isFalse(errorFired) + }) + + it('does not crash when show target selector matches nothing', async function () { + let div = createProcessedHTML('
') + let ctx = htmx.__createRequestContext(div, new Event('click')) + + ctx.fetch = async () => ({ + status: 200, + headers: new Headers(), + text: async () => '
Response
' + }) + + let errorFired = false + div.addEventListener('htmx:error', () => errorFired = true) + + await htmx.__issueRequest(ctx) + assert.isFalse(errorFired) + }) + it('throws clean error for unknown swap style with no extensions', async function () { let div = createProcessedHTML('
') let ctx = htmx.__createRequestContext(div, new Event('click'))