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
2 changes: 1 addition & 1 deletion e2e/react-start/basic-react-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-tsconfig-paths": "^5.1.4"
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-start/basic-tsr-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@types/node": "^22.10.2",
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"typescript": "^5.7.2"
}
}
2 changes: 1 addition & 1 deletion e2e/react-start/basic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite": "^7.1.7",
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-start/custom-basepath/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"autoprefixer": "^10.4.20",
"cross-env": "^10.0.0",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"tsx": "^4.20.3",
"typescript": "^5.7.2",
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-start/scroll-restoration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-tsconfig-paths": "^5.1.4"
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-start/selective-ssr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2"
}
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-start/serialization-adapters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2"
}
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-start/server-functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-tsconfig-paths": "^5.1.4"
Expand Down
79 changes: 50 additions & 29 deletions e2e/react-start/server-functions/src/routes/abort-signal.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,51 @@
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
import { createServerFn, createServerOnlyFn } from '@tanstack/react-start'
import { getRequest } from '@tanstack/react-start/server'
import React from 'react'

export const Route = createFileRoute('/abort-signal')({
component: RouteComponent,
component: () => {
return (
<div>
<Test method="post" fn={abortableServerFnPost} />
<hr />
<Test method="get" fn={abortableServerFnGet} />
</div>
)
},
})

const abortableServerFn = createServerFn().handler(
async ({ context, signal }) => {
console.log('server function started', { context, signal })
return new Promise<string>((resolve, reject) => {
if (signal.aborted) {
return reject(new Error('Aborted before start'))
}
const timerId = setTimeout(() => {
console.log('server function finished')
resolve('server function result')
}, 1000)
const onAbort = () => {
clearTimeout(timerId)
console.log('server function aborted')
reject(new Error('Aborted'))
}
signal.addEventListener('abort', onAbort, { once: true })
})
},
)
const fn = createServerOnlyFn(async () => {
const request = getRequest()
const signal = request.signal
console.log('server function started', { signal })
return new Promise<string>((resolve, reject) => {
if (signal.aborted) {
return reject(new Error('Aborted before start'))
}
const timerId = setTimeout(() => {
console.log('server function finished')
resolve('server function result')
}, 1000)
const onAbort = () => {
clearTimeout(timerId)
console.log('server function aborted')
reject(new Error('Aborted'))
}
signal.addEventListener('abort', onAbort, { once: true })
})
})
Comment on lines +18 to +37
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify request.signal availability after srvx dependency bump.

The abort handling logic is correct: early exit check, proper timeout cleanup, and { once: true } listener registration to prevent memory leaks. However, the code assumes request.signal is available via getRequest().

Since the PR description mentions this change depends on h3js/srvx#122, ensure the srvx dependency is bumped and that request.signal is properly exposed in the updated version.

Run the following script to verify the srvx version and check for related changes:


🏁 Script executed:

#!/bin/bash
# Verify srvx dependency version across the monorepo

echo "=== Checking srvx versions in package.json files ==="
fd -e json -x sh -c 'if grep -q "srvx" "$1"; then echo "$1:"; grep "srvx" "$1"; fi' sh {}

echo ""
echo "=== Searching for request.signal usage in codebase ==="
rg -n --type ts -C2 'request\.signal' -g '!node_modules'

Length of output: 3834


Bump srvx to a version that exposes request.signal
All package.json files remain at ^0.8.16, which doesn’t include the getRequest().signal change from h3js/srvx#122—update srvx to the released version that adds request.signal before merging.

🤖 Prompt for AI Agents
In e2e/react-start/server-functions/src/routes/abort-signal.tsx around lines 18
to 37, the code uses getRequest().signal but the repo's package.json still pins
srvx to ^0.8.16 which does not include the h3js/srvx#122 change; update the srvx
dependency in all package.json files to the released version that exposes
request.signal (e.g., bump to >=0.8.17 or the specific released version that
contains the PR), run package manager install to update lockfiles, and verify
the tests/build so the server function can access request.signal without runtime
errors.


const abortableServerFnPost = createServerFn({ method: 'POST' }).handler(fn)

function RouteComponent() {
const abortableServerFnGet = createServerFn({ method: 'GET' }).handler(fn)
function Test({
method,
fn,
}: {
method: string
fn: typeof abortableServerFnPost | typeof abortableServerFnGet
}) {
const [errorMessage, setErrorMessage] = React.useState<string | undefined>(
undefined,
)
Expand All @@ -39,12 +57,13 @@ function RouteComponent() {
}
return (
<div>
<h2>Test {method}</h2>
<button
data-testid="run-with-abort-btn"
data-testid={`run-with-abort-btn-${method}`}
onClick={async () => {
reset()
const controller = new AbortController()
const serverFnPromise = abortableServerFn({
const serverFnPromise = fn({
signal: controller.signal,
})
const timeoutPromise = new Promise((resolve) =>
Expand All @@ -64,21 +83,23 @@ function RouteComponent() {
</button>
<br />
<button
data-testid="run-without-abort-btn"
data-testid={`run-without-abort-btn-${method}`}
onClick={async () => {
reset()
const serverFnResult = await abortableServerFn()
const serverFnResult = await fn()
setResult(serverFnResult)
}}
>
call server function
</button>
<div className="p-2">
result: <p data-testid="result">{result ?? '$undefined'}</p>
result: <p data-testid={`result-${method}`}>{result ?? '$undefined'}</p>
</div>
<div className="p-2">
message:{' '}
<p data-testid="errorMessage">{errorMessage ?? '$undefined'}</p>
<p data-testid={`errorMessage-${method}`}>
{errorMessage ?? '$undefined'}
</p>
</div>
</div>
)
Expand Down
68 changes: 37 additions & 31 deletions e2e/react-start/server-functions/tests/server-functions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,46 +270,52 @@ test.describe('server function sets cookies', () => {
})

test.describe('aborting a server function call', () => {
test('without aborting', async ({ page }) => {
await page.goto('/abort-signal')
;['get', 'post'].forEach((method) => {
test(`without aborting ${method}`, async ({ page }) => {
await page.goto('/abort-signal')

await page.waitForLoadState('networkidle')
await page.waitForLoadState('networkidle')

await page.getByTestId('run-without-abort-btn').click()
await page.waitForLoadState('networkidle')
await page.waitForSelector(
'[data-testid="result"]:has-text("server function result")',
)
await page.waitForSelector(
'[data-testid="errorMessage"]:has-text("$undefined")',
)
await page.getByTestId(`run-without-abort-btn-${method}`).click()
await page.waitForLoadState('networkidle')
await page.waitForSelector(
`[data-testid="result-${method}"]:has-text("server function result")`,
)
await page.waitForSelector(
`[data-testid="errorMessage-${method}"]:has-text("$undefined")`,
)

const result = (await page.getByTestId('result').textContent()) || ''
expect(result).toBe('server function result')
const result =
(await page.getByTestId(`result-${method}`).textContent()) || ''
expect(result).toBe('server function result')

const errorMessage =
(await page.getByTestId('errorMessage').textContent()) || ''
expect(errorMessage).toBe('$undefined')
})
const errorMessage =
(await page.getByTestId(`errorMessage-${method}`).textContent()) || ''
expect(errorMessage).toBe('$undefined')
})

test('aborting', async ({ page }) => {
await page.goto('/abort-signal')
test(`aborting ${method}`, async ({ page }) => {
await page.goto('/abort-signal')

await page.waitForLoadState('networkidle')
await page.waitForLoadState('networkidle')

await page.getByTestId('run-with-abort-btn').click()
await page.waitForLoadState('networkidle')
await page.waitForSelector('[data-testid="result"]:has-text("$undefined")')
await page.waitForSelector(
'[data-testid="errorMessage"]:has-text("aborted")',
)
await page.getByTestId(`run-with-abort-btn-${method}`).click()
await page.waitForLoadState('networkidle')
await page.waitForSelector(
`[data-testid="result-${method}"]:has-text("$undefined")`,
)
await page.waitForSelector(
`[data-testid="errorMessage-${method}"]:has-text("aborted")`,
)

const result = (await page.getByTestId('result').textContent()) || ''
expect(result).toBe('$undefined')
const result =
(await page.getByTestId(`result-${method}`).textContent()) || ''
expect(result).toBe('$undefined')

const errorMessage =
(await page.getByTestId('errorMessage').textContent()) || ''
expect(errorMessage).toContain('abort')
const errorMessage =
(await page.getByTestId(`errorMessage-${method}`).textContent()) || ''
expect(errorMessage).toContain('abort')
})
})
})

Expand Down
2 changes: 1 addition & 1 deletion e2e/react-start/server-routes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-tsconfig-paths": "^5.1.4"
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-start/virtual-routes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-tsconfig-paths": "^5.1.4"
Expand Down
2 changes: 1 addition & 1 deletion e2e/react-start/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite": "^7.1.7",
Expand Down
2 changes: 1 addition & 1 deletion e2e/solid-start/basic-tsr-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"devDependencies": {
"@tanstack/router-e2e-utils": "workspace:^",
"@types/node": "^22.10.2",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"typescript": "^5.7.2",
"vite-plugin-solid": "^2.11.8",
"vite-tsconfig-paths": "^5.1.4"
Expand Down
2 changes: 1 addition & 1 deletion e2e/solid-start/basic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-plugin-solid": "^2.11.8",
Expand Down
2 changes: 1 addition & 1 deletion e2e/solid-start/custom-basepath/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"autoprefixer": "^10.4.20",
"cross-env": "^10.0.0",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"tsx": "^4.20.3",
"typescript": "^5.7.2",
Expand Down
2 changes: 1 addition & 1 deletion e2e/solid-start/scroll-restoration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-plugin-solid": "^2.11.8",
Expand Down
2 changes: 1 addition & 1 deletion e2e/solid-start/selective-ssr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"devDependencies": {
"@tanstack/router-e2e-utils": "workspace:^",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite": "^7.1.7",
Expand Down
2 changes: 1 addition & 1 deletion e2e/solid-start/server-functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-plugin-solid": "^2.11.8",
Expand Down
2 changes: 1 addition & 1 deletion e2e/solid-start/server-routes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"autoprefixer": "^10.4.20",
"combinate": "^1.1.11",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-plugin-solid": "^2.11.8",
Expand Down
2 changes: 1 addition & 1 deletion e2e/solid-start/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@types/node": "^22.10.2",
"autoprefixer": "^10.4.20",
"postcss": "^8.5.1",
"srvx": "^0.8.6",
"srvx": "^0.8.16",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"vite-plugin-solid": "^2.11.8",
Expand Down
Loading
Loading