From dc1c62c91f302c017e92c489ee64a3e820e53fdf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 11 Aug 2025 09:18:26 +0000
Subject: [PATCH 1/3] Initial plan
From b73e922eaad5b6d165971f424548540dbfabd0a6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 11 Aug 2025 09:27:14 +0000
Subject: [PATCH 2/3] Add test case for syntax error handling in definePage
Co-authored-by: posva <664177+posva@users.noreply.github.com>
---
src/core/definePage.spec.ts | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/src/core/definePage.spec.ts b/src/core/definePage.spec.ts
index 07d92d4f8..49ff0d437 100644
--- a/src/core/definePage.spec.ts
+++ b/src/core/definePage.spec.ts
@@ -254,4 +254,30 @@ export default {
path: '/custom',
})
})
+
+ it('handles syntax errors gracefully', async () => {
+ const invalidCode = `
+
+
+
+ hello
+
+ `
+
+ // Should not throw and return undefined for normal transform
+ const result = await definePageTransform({
+ code: invalidCode,
+ id: 'src/pages/invalid.vue',
+ })
+ expect(result).toBeUndefined()
+
+ // Should return empty object for definePage extraction
+ const extractResult = await definePageTransform({
+ code: invalidCode,
+ id: 'src/pages/invalid.vue?definePage&vue',
+ })
+ expect(extractResult).toBe('export default {}')
+ })
})
From cdb584fbb39906e0edba13865ebd88c63a08501a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 11 Aug 2025 09:34:21 +0000
Subject: [PATCH 3/3] Fix syntax error handling in definePage to prevent Vite
crashes
Co-authored-by: posva <664177+posva@users.noreply.github.com>
---
playground/typed-router.d.ts | 5 +++++
src/core/definePage.spec.ts | 42 ++++++++++++++++++++++++++++++++++++
src/core/definePage.ts | 34 +++++++++++++++++++----------
3 files changed, 70 insertions(+), 11 deletions(-)
diff --git a/playground/typed-router.d.ts b/playground/typed-router.d.ts
index c4b6e56f2..896141e31 100644
--- a/playground/typed-router.d.ts
+++ b/playground/typed-router.d.ts
@@ -63,6 +63,7 @@ declare module 'vue-router/auto-routes' {
'/nested-group/(nested-group-first-level)/nested-group-first-level-child': RouteRecordInfo<'/nested-group/(nested-group-first-level)/nested-group-first-level-child', '/nested-group/nested-group-first-level-child', Record, Record>,
'/partial-[name]': RouteRecordInfo<'/partial-[name]', '/partial-:name', { name: ParamValue }, { name: ParamValue }>,
'/custom-path': RouteRecordInfo<'/custom-path', '/surprise-:id(\d+)', Record, Record>,
+ '/syntax-error-test': RouteRecordInfo<'/syntax-error-test', '/syntax-error-test', Record, Record>,
'/test-[a-id]': RouteRecordInfo<'/test-[a-id]', '/test-:a-id', { aId: ParamValue }, { aId: ParamValue }>,
'/todos/': RouteRecordInfo<'/todos/', '/todos', Record, Record>,
'/todos/+layout': RouteRecordInfo<'/todos/+layout', '/todos/+layout', Record, Record>,
@@ -283,6 +284,10 @@ declare module 'vue-router/auto-routes' {
routes: '/custom-path'
views: never
}
+ 'src/pages/syntax-error-test.vue': {
+ routes: '/syntax-error-test'
+ views: never
+ }
'src/pages/test-[a-id].vue': {
routes: '/test-[a-id]'
views: never
diff --git a/src/core/definePage.spec.ts b/src/core/definePage.spec.ts
index 49ff0d437..0d70d0b83 100644
--- a/src/core/definePage.spec.ts
+++ b/src/core/definePage.spec.ts
@@ -279,5 +279,47 @@ definePage({ 2, 3 }) // invalid syntax
id: 'src/pages/invalid.vue?definePage&vue',
})
expect(extractResult).toBe('export default {}')
+
+ // extractDefinePageNameAndPath should also handle syntax errors gracefully
+ const nameAndPath = await extractDefinePageNameAndPath(invalidCode, 'src/pages/invalid.vue')
+ expect(nameAndPath).toBeUndefined()
+ })
+
+ it('handles various syntax errors in definePage', async () => {
+ // Test with missing closing brace
+ const invalidCode1 = `
+
+
+test
+ `
+
+ const result1 = await definePageTransform({
+ code: invalidCode1,
+ id: 'src/pages/invalid1.vue',
+ })
+ expect(result1).toBeUndefined()
+
+ // Test with invalid property syntax
+ const invalidCode2 = `
+
+
+test
+ `
+
+ const result2 = await definePageTransform({
+ code: invalidCode2,
+ id: 'src/pages/invalid2.vue',
+ })
+ expect(result2).toBeUndefined()
+
+ const extractResult2 = await definePageTransform({
+ code: invalidCode2,
+ id: 'src/pages/invalid2.vue?definePage&vue',
+ })
+ expect(extractResult2).toBe('export default {}')
})
})
diff --git a/src/core/definePage.ts b/src/core/definePage.ts
index ca420eb1e..5e8a38b98 100644
--- a/src/core/definePage.ts
+++ b/src/core/definePage.ts
@@ -35,17 +35,26 @@ function getCodeAst(code: string, id: string) {
let offset = 0
let ast: Program | undefined
const lang = getLang(id.split(MACRO_DEFINE_PAGE_QUERY)[0]!)
- if (lang === 'vue') {
- const sfc = parseSFC(code, id)
- if (sfc.scriptSetup) {
- ast = sfc.getSetupAst()
- offset = sfc.scriptSetup.loc.start.offset
- } else if (sfc.script) {
- ast = sfc.getScriptAst()
- offset = sfc.script.loc.start.offset
+
+ try {
+ if (lang === 'vue') {
+ const sfc = parseSFC(code, id)
+ if (sfc.scriptSetup) {
+ ast = sfc.getSetupAst()
+ offset = sfc.scriptSetup.loc.start.offset
+ } else if (sfc.script) {
+ ast = sfc.getScriptAst()
+ offset = sfc.script.loc.start.offset
+ }
+ } else if (/[jt]sx?$/.test(lang)) {
+ ast = babelParse(code, lang)
}
- } else if (/[jt]sx?$/.test(lang)) {
- ast = babelParse(code, lang)
+ } catch (error) {
+ // If there's a syntax error in the code, warn and return empty results
+ // This prevents crashing the dev server when there are syntax errors
+ const errorMessage = error instanceof Error ? error.message : String(error)
+ warn(`[${id}]: Failed to parse code due to syntax error: ${errorMessage}`)
+ return { ast: undefined, offset: 0, definePageNodes: [] }
}
const definePageNodes: CallExpression[] = (ast?.body || [])
@@ -78,7 +87,10 @@ export function definePageTransform({
}
const { ast, offset, definePageNodes } = getCodeAst(code, id)
- if (!ast) return
+ if (!ast) {
+ // If parsing failed but we're extracting definePage, return empty object
+ return isExtractingDefinePage ? 'export default {}' : undefined
+ }
if (!definePageNodes.length) {
return isExtractingDefinePage