Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/htmx.js
Original file line number Diff line number Diff line change
Expand Up @@ -2288,7 +2288,11 @@ var htmx = (() => {
if (document.startViewTransition) {
let detail = {task, ctx};
this.__trigger(ctx.sourceElement, "htmx:before:viewTransition", detail)
await document.startViewTransition(detail.task).finished;
let vt = document.startViewTransition(detail.task);
// ready rejects when the document is hidden; unfinished catch
// still produces unhandledrejection unless we handle ready too
vt.ready?.catch(() => {});
await vt.finished;
this.__trigger(ctx.sourceElement, "htmx:after:viewTransition", detail)
} else {
await task();
Expand Down
24 changes: 24 additions & 0 deletions test/tests/unit/swap.js
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,30 @@ describe('swap() unit tests', function() {
assert.isTrue(true);
})

it('does not emit unhandledrejection when view transition ready rejects', async function() {
let unhandled = 0;
let onUnhandled = () => { unhandled++; };
window.addEventListener('unhandledrejection', onUnhandled);
const originalStartViewTransition = document.startViewTransition;
document.startViewTransition = (cb) => {
let finished = Promise.resolve().then(() => cb());
let ready = Promise.reject(new DOMException('Skipped ViewTransition due to document being hidden', 'InvalidStateError'));
return { ready, finished, skipped: Promise.resolve(), updateCallbackDone: finished };
};
try {
await htmx.swap({
target: "#test-playground",
text: "<div id='d1'>Content</div>",
swap: "innerHTML transition:true"
});
await htmx.timeout(50);
assert.equal(unhandled, 0);
} finally {
window.removeEventListener('unhandledrejection', onUnhandled);
document.startViewTransition = originalStartViewTransition;
}
})

// Gap #12: Extension content transformation result
it('uses array result from extension handle_swap', async function() {
mockResponse('GET', '/test', '<div>Content</div>');
Expand Down
Loading