Repository: vitejs/vite
Pull request #19959: fix(ssr): handle uninitialized export access as undefined
Author: login: hi-ogawa
Labels: name: trigger: preview
Created: 2025-04-29T07:51:36Z | Merged: 2025-05-02T07:36:21Z

### Description

- Closes https://github.com/vitejs/vite/issues/19929
- Closes https://github.com/vitest-dev/vitest/issues/7902

Export hoisting https://github.com/vitejs/vite/pull/18983 made an cyclic import handling  to match better with esm (meaning valid cyclic imports are accepted and invalid ones are correctly rejected), but it turns out to be too strict for Vitest users which tends to import arbitrary files as first entry. The behavior change was too drastic for the patch release 6.3.3 at least, so in this PR, I added `try/catch` to make invalid exports to be fallback to `undefined`. Note that this should still make valid cyclic imports to work, which was the original motivation of https://github.com/vitejs/vite/pull/18983.

I confirmed provided reproductions are fixed with pr package (except there is a case like https://github.com/vitejs/vite/issues/19929#issuecomment-2834719080, which is due to another fix https://github.com/vitejs/vite/pull/19841, so they are still expected to be addressed on user side).

On Vitest side, there might be more complicated scenarios with mocking, so I couldn't actually tell whether it's an cyclic imports issues. We'll revisit whether we should remove `try/catch` after investigating that further.


Diff:
diff --git a/packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts
index d215fbc436747a..d878ed09a7e6a6 100644
--- a/packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts
+++ b/packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts
@@ -235,7 +235,7 @@ test('json', async () => {
     null,
     '/test.json',
   )
-  expect(json?.code.length).toMatchInlineSnapshot(`208`)
+  expect(json?.code.length).toMatchInlineSnapshot(`225`)
 })
 
 test('file url', async () => {
diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
index a791a3516268e5..08f21dff809af2 100644
--- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
+++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
@@ -55,7 +55,7 @@ test('export function declaration', async () => {
     await ssrTransformSimpleCode(`export function foo() {}`),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }});
+    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return foo } catch {} }});
     function foo() {}"
   `,
   )
@@ -66,7 +66,7 @@ test('export class declaration', async () => {
     await ssrTransformSimpleCode(`export class foo {}`),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }});
+    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return foo } catch {} }});
     class foo {}"
   `,
   )
@@ -77,8 +77,8 @@ test('export var declaration', async () => {
     await ssrTransformSimpleCode(`export const a = 1, b = 2`),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "a", { enumerable: true, configurable: true, get(){ return a }});
-    Object.defineProperty(__vite_ssr_exports__, "b", { enumerable: true, configurable: true, get(){ return b }});
+    "Object.defineProperty(__vite_ssr_exports__, "a", { enumerable: true, configurable: true, get(){ try { return a } catch {} }});
+    Object.defineProperty(__vite_ssr_exports__, "b", { enumerable: true, configurable: true, get(){ try { return b } catch {} }});
     const a = 1, b = 2"
   `,
   )
@@ -89,8 +89,8 @@ test('export named', async () => {
     await ssrTransformSimpleCode(`const a = 1, b = 2; export { a, b as c }`),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "a", { enumerable: true, configurable: true, get(){ return a }});
-    Object.defineProperty(__vite_ssr_exports__, "c", { enumerable: true, configurable: true, get(){ return b }});
+    "Object.defineProperty(__vite_ssr_exports__, "a", { enumerable: true, configurable: true, get(){ try { return a } catch {} }});
+    Object.defineProperty(__vite_ssr_exports__, "c", { enumerable: true, configurable: true, get(){ try { return b } catch {} }});
     const a = 1, b = 2; "
   `,
   )
@@ -101,8 +101,8 @@ test('export named from', async () => {
     await ssrTransformSimpleCode(`export { ref, computed as c } from 'vue'`),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "ref", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.ref }});
-    Object.defineProperty(__vite_ssr_exports__, "c", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.computed }});
+    "Object.defineProperty(__vite_ssr_exports__, "ref", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__.ref } catch {} }});
+    Object.defineProperty(__vite_ssr_exports__, "c", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__.computed } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref","computed"]});"
   `,
   )
@@ -115,7 +115,7 @@ test('named exports of imported binding', async () => {
     ),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "createApp", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.createApp }});
+    "Object.defineProperty(__vite_ssr_exports__, "createApp", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__.createApp } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["createApp"]});"
   `,
   )
@@ -139,7 +139,7 @@ test('export * as from', async () => {
     await ssrTransformSimpleCode(`export * as foo from 'vue'`),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__ }});
+    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__ } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("vue");"
   `,
   )
@@ -152,7 +152,7 @@ import * as foo from 'foo'
 export * as foo from 'foo'
 `),
   ).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__ }});
+    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__ } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("foo");
     const __vite_ssr_import_1__ = await __vite_ssr_import__("foo");
     "
@@ -164,7 +164,7 @@ import { foo } from 'foo'
 export { foo } from 'foo'
 `),
   ).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__.foo }});
+    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__.foo } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
     const __vite_ssr_import_1__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
     "
@@ -176,7 +176,7 @@ import { foo } from 'foo'
 export { foo as foo } from 'foo'
 `),
   ).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__.foo }});
+    "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__.foo } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
     const __vite_ssr_import_1__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
     "
@@ -188,7 +188,7 @@ test('export * as from arbitrary module namespace identifier', async () => {
     await ssrTransformSimpleCode(`export * as "arbitrary string" from 'vue'`),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__ }});
+    "Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__ } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("vue");"
   `,
   )
@@ -201,7 +201,7 @@ test('export as arbitrary module namespace identifier', async () => {
     ),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ return something }});
+    "Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ try { return something } catch {} }});
     const something = "Something";"
   `,
   )
@@ -214,7 +214,7 @@ test('export as from arbitrary module namespace identifier', async () => {
     ),
   ).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__["arbitrary string2"] }});
+    "Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_0__["arbitrary string2"] } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["arbitrary string2"]});"
   `,
   )
@@ -223,9 +223,9 @@ test('export as from arbitrary module namespace identifier', async () => {
 test('export default', async () => {
   expect(await ssrTransformSimpleCode(`export default {}`))
     .toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ return __vite_ssr_export_default__ }});
-    const __vite_ssr_export_default__ = {}"
-  `)
+      "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
+      const __vite_ssr_export_default__ = {}"
+    `)
 })
 
 test('export then import minified', async () => {
@@ -347,7 +347,7 @@ test('dynamic import', async () => {
   )
   expect(result?.code).toMatchInlineSnapshot(
     `
-    "Object.defineProperty(__vite_ssr_exports__, "i", { enumerable: true, configurable: true, get(){ return i }});
+    "Object.defineProperty(__vite_ssr_exports__, "i", { enumerable: true, configurable: true, get(){ try { return i } catch {} }});
     const i = () => __vite_ssr_dynamic_import__('./foo')"
   `,
   )
@@ -507,8 +507,8 @@ test('should declare variable for imported super class', async () => {
         `export class B extends Foo {}`,
     ),
   ).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ return A }});
-    Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ return B }});
+    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return A } catch {} }});
+    Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ try { return B } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("./dependency", {"importedNames":["Foo"]});const Foo = __vite_ssr_import_0__.Foo;
     class A extends Foo {};
     class B extends Foo {}"
@@ -520,14 +520,14 @@ test('should handle default export variants', async () => {
   // default anonymous functions
   expect(await ssrTransformSimpleCode(`export default function() {}\n`))
     .toMatchInlineSnapshot(`
-      "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ return __vite_ssr_export_default__ }});
+      "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
       const __vite_ssr_export_default__ = function() {}
       "
     `)
   // default anonymous class
   expect(await ssrTransformSimpleCode(`export default class {}\n`))
     .toMatchInlineSnapshot(`
-      "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ return __vite_ssr_export_default__ }});
+      "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
       const __vite_ssr_export_default__ = class {}
       "
     `)
@@ -538,7 +538,7 @@ test('should handle default export variants', async () => {
         `foo.prototype = Object.prototype;`,
     ),
   ).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ return foo }});
+    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return foo } catch {} }});
     function foo() {};
     foo.prototype = Object.prototype;"
   `)
@@ -548,8 +548,8 @@ test('should handle default export variants', async () => {
       `export default class A {}\n` + `export class B extends A {}`,
     ),
   ).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ return A }});
-    Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ return B }});
+    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return A } catch {} }});
+    Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ try { return B } catch {} }});
     class A {};
     class B extends A {}"
   `)
@@ -988,8 +988,8 @@ export function fn1() {
         `,
     ),
   ).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "fn1", { enumerable: true, configurable: true, get(){ return fn1 }});
-    Object.defineProperty(__vite_ssr_exports__, "fn2", { enumerable: true, configurable: true, get(){ return fn2 }});
+    "Object.defineProperty(__vite_ssr_exports__, "fn1", { enumerable: true, configurable: true, get(){ try { return fn1 } catch {} }});
+    Object.defineProperty(__vite_ssr_exports__, "fn2", { enumerable: true, configurable: true, get(){ try { return fn2 } catch {} }});
 
     function fn1() {
     };function fn2() {
@@ -1011,7 +1011,7 @@ export default (function getRandom() {
 `.trim()
 
   expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ return __vite_ssr_export_default__ }});
+    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
     const __vite_ssr_export_default__ = (function getRandom() {
       return Math.random();
     });"
@@ -1019,9 +1019,9 @@ export default (function getRandom() {
 
   expect(await ssrTransformSimpleCode(`export default (class A {});`))
     .toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ return __vite_ssr_export_default__ }});
-    const __vite_ssr_export_default__ = (class A {});"
-  `)
+      "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
+      const __vite_ssr_export_default__ = (class A {});"
+    `)
 })
 
 // #8002
@@ -1095,7 +1095,7 @@ export class Test {
 };`.trim()
 
   expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "Test", { enumerable: true, configurable: true, get(){ return Test }});
+    "Object.defineProperty(__vite_ssr_exports__, "Test", { enumerable: true, configurable: true, get(){ try { return Test } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]});
     if (false) {
       const foo = 'foo';
@@ -1285,8 +1285,8 @@ export * as bar from './bar'
 console.log(bar)
   `),
   ).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ return __vite_ssr_export_default__ }});
-    Object.defineProperty(__vite_ssr_exports__, "bar", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__ }});
+    "Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_export_default__ } catch {} }});
+    Object.defineProperty(__vite_ssr_exports__, "bar", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__ } catch {} }});
 
     const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]});const __vite_ssr_import_1__ = await __vite_ssr_import__("./bar");;
     const __vite_ssr_export_default__ = (0,__vite_ssr_import_0__.foo)();
@@ -1542,9 +1542,9 @@ import("e")
 export * as A from "a";
 `)
   expect(result?.code).toMatchInlineSnapshot(`
-    "Object.defineProperty(__vite_ssr_exports__, "b", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__.b }});
-    Object.defineProperty(__vite_ssr_exports__, "d", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_3__ }});
-    Object.defineProperty(__vite_ssr_exports__, "A", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_4__ }});
+    "Object.defineProperty(__vite_ssr_exports__, "b", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_1__.b } catch {} }});
+    Object.defineProperty(__vite_ssr_exports__, "d", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_3__ } catch {} }});
+    Object.defineProperty(__vite_ssr_exports__, "A", { enumerable: true, configurable: true, get(){ try { return __vite_ssr_import_4__ } catch {} }});
     const __vite_ssr_import_0__ = await __vite_ssr_import__("a", {"importedNames":["default"]});
     const __vite_ssr_import_1__ = await __vite_ssr_import__("b", {"importedNames":["b"]});
     const __vite_ssr_import_2__ = await __vite_ssr_import__("c");__vite_ssr_exportAll__(__vite_ssr_import_2__);
diff --git a/packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts b/packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts
index ec9b5c110b0076..2942856f780ea8 100644
--- a/packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts
+++ b/packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts
@@ -290,15 +290,20 @@ describe('module runner initialization', async () => {
     await expect(() =>
       runner.import('/fixtures/cyclic2/test5/index.js'),
     ).rejects.toMatchInlineSnapshot(
-      `[ReferenceError: Cannot access '__vite_ssr_import_1__' before initialization]`,
+      `[TypeError: Cannot read properties of undefined (reading 'ok')]`,
     )
   })
 
   it(`cyclic invalid 2`, async ({ runner }) => {
-    await expect(() =>
-      runner.import('/fixtures/cyclic2/test6/index.js'),
-    ).rejects.toMatchInlineSnapshot(
-      `[ReferenceError: Cannot access 'dep1' before initialization]`,
+    // It should be an error but currently `undefined` fallback.
+    expect(
+      await runner.import('/fixtures/cyclic2/test6/index.js'),
+    ).toMatchInlineSnapshot(
+      `
+      {
+        "dep1": "dep1: dep2: undefined",
+      }
+    `,
     )
   })
 
@@ -374,10 +379,15 @@ describe('module runner initialization', async () => {
 
   it(`export default getter is hoisted`, async ({ runner }) => {
     // Node error is `ReferenceError: Cannot access 'dep' before initialization`
-    await expect(() =>
-      runner.import('/fixtures/cyclic2/test9/index.js'),
-    ).rejects.toMatchInlineSnapshot(
-      `[ReferenceError: Cannot access '__vite_ssr_export_default__' before initialization]`,
+    // It should be an error but currently `undefined` fallback.
+    expect(
+      await runner.import('/fixtures/cyclic2/test9/index.js'),
+    ).toMatchInlineSnapshot(
+      `
+      {
+        "default": undefined,
+      }
+    `,
     )
   })
 })
diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts
index bae60244d50272..8d68110e489a97 100644
--- a/packages/vite/src/node/ssr/ssrTransform.ts
+++ b/packages/vite/src/node/ssr/ssrTransform.ts
@@ -179,10 +179,11 @@ async function ssrTransformScript(
   }
 
   function defineExport(name: string, local = name) {
+    // wrap with try/catch to fallback to `undefined` for backward compat.
     s.appendLeft(
       fileStartIndex,
       `Object.defineProperty(${ssrModuleExportsKey}, ${JSON.stringify(name)}, ` +
-        `{ enumerable: true, configurable: true, get(){ return ${local} }});\n`,
+        `{ enumerable: true, configurable: true, get(){ try { return ${local} } catch {} }});\n`,
     )
   }
 
diff --git a/vitest.config.ts b/vitest.config.ts
index 2913b941653a06..919e0a30d650bd 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -19,10 +19,6 @@ export default defineConfig({
     },
     testTimeout: 20000,
     isolate: false,
-    // importing non-entry files (e.g. config.ts, build.ts, server/index.ts) is broken due to cyclic import
-    // as it can be seen from tsx (try pnpm exec tsx packages/vite/src/node/server/index.ts).
-    // we can use `setupFiles` to ensure the modules are evaluated via main node entry.
-    setupFiles: ['./packages/vite/src/node/index.ts'],
   },
   esbuild: {
     target: 'node18',


Reviews:
user: login: sheremet-va
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-05-01T08:32:12Z
user: login: patak-cat
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-02T07:04:20Z
user: login: patak-cat
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-02T07:04:34Z
user: login: patak-cat
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-02T07:36:11Z

Review comments:
diff_hunk: @@ -374,10 +379,15 @@ describe('module runner initialization', async () => {
 
   it(`export default getter is hoisted`, async ({ runner }) => {
     // Node error is `ReferenceError: Cannot access 'dep' before initialization`
-    await expect(() =>
-      runner.import('/fixtures/cyclic2/test9/index.js'),
-    ).rejects.toMatchInlineSnapshot(
-      `[ReferenceError: Cannot access '__vite_ssr_export_default__' before initialization]`,
+    // It should be an error but currently `undefiend` fallback.
path: packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts
user: login: patak-cat
body: ```suggestion
    // It should be an error but currently `undefined` fallback.
```
created_at: 2025-05-02T07:04:19Z
author_association: MEMBER
diff_hunk: @@ -290,15 +290,20 @@ describe('module runner initialization', async () => {
     await expect(() =>
       runner.import('/fixtures/cyclic2/test5/index.js'),
     ).rejects.toMatchInlineSnapshot(
-      `[ReferenceError: Cannot access '__vite_ssr_import_1__' before initialization]`,
+      `[TypeError: Cannot read properties of undefined (reading 'ok')]`,
     )
   })
 
   it(`cyclic invalid 2`, async ({ runner }) => {
-    await expect(() =>
-      runner.import('/fixtures/cyclic2/test6/index.js'),
-    ).rejects.toMatchInlineSnapshot(
-      `[ReferenceError: Cannot access 'dep1' before initialization]`,
+    // It should be an error but currently `undefiend` fallback.
path: packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts
user: login: patak-cat
body: ```suggestion
    // It should be an error but currently `undefined` fallback.
```
created_at: 2025-05-02T07:04:34Z
author_association: MEMBER

PR comments:
user: login: pkg-pr-new[bot]
created_at: 2025-05-01T09:23:19Z
body: 
[Open in StackBlitz](https://pkg.pr.new/template/72bab5a9-85e8-461f-b09a-a5451d12253e)


```
npm i https://pkg.pr.new/vite@19959
```


_commit: <a href="https://github.com/vitejs/vite/runs/41527206453"><code>adbfb90</code></a>_

author_association: NONE
user: login: hi-ogawa
created_at: 2025-05-02T02:41:10Z
body: /ecosystem-ci run
author_association: CONTRIBUTOR
user: login: vite-ecosystem-ci[bot]
created_at: 2025-05-02T03:00:42Z
body: 
📝 Ran ecosystem CI on [`0eb9080`](https://github.com/vitejs/vite/pull/19959/commits/0eb90805c965df44143586b878938c27e1180910): [Open](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201)

| suite | result | [latest scheduled](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14747054139) |
|-------|--------|----------------|
| previewjs | :white_check_mark: [success](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726129) | :x: [failure](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14747054139/job/41396293241) |
| laravel | :x: [failure](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726137) | :x: [failure](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14747054139/job/41396293240) |
| vike | :white_check_mark: [success](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726145) | :x: [failure](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14747054139/job/41396293253) |
| vitest | :x: [failure](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726162) | :x: [failure](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14747054139/job/41396293300) |

:white_check_mark: [analogjs](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726111), [astro](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726113), [ladle](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726120), [histoire](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726122), [qwik](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726132), [quasar](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726133), [react-router](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726139), [marko](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726140), [nuxt](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726141), [vite-environment-examples](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726142), [rakkas](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726143), [unocss](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726144), [sveltekit](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726146), [vite-plugin-react-swc](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726147), [vite-plugin-pwa](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726148), [vite-plugin-react](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726151), [vite-setup-catalogue](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726156), [vite-plugin-cloudflare](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726158), [vite-plugin-svelte](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726163), [storybook](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726167), [waku](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726168), [vuepress](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726169), [vitepress](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726172), [vite-plugin-vue](https://github.com/vitejs/vite-ecosystem-ci/actions/runs/14787597201/job/41518726225)

author_association: NONE