diff --git a/packages/vite/src/node/__tests__/build.spec.ts b/packages/vite/src/node/__tests__/build.spec.ts index cd6bd6e42c4a5d..19bef57f8d374f 100644 --- a/packages/vite/src/node/__tests__/build.spec.ts +++ b/packages/vite/src/node/__tests__/build.spec.ts @@ -4,8 +4,8 @@ import colors from 'picocolors' import { describe, expect, test, vi } from 'vitest' import type { OutputChunk, OutputOptions, RollupOutput } from 'rollup' import type { LibraryFormats, LibraryOptions } from '../build' +import { build } from '..' import { - build, createBuilder, resolveBuildOutputs, resolveLibFilename, diff --git a/packages/vite/src/node/__tests__/environment.spec.ts b/packages/vite/src/node/__tests__/environment.spec.ts index 75b12136c5cd2d..735db48493786d 100644 --- a/packages/vite/src/node/__tests__/environment.spec.ts +++ b/packages/vite/src/node/__tests__/environment.spec.ts @@ -1,7 +1,7 @@ import path from 'node:path' import { describe, expect, onTestFinished, test } from 'vitest' import type { RollupOutput } from 'rollup' -import { createServer } from '../server' +import { createServer } from '..' import type { InlineConfig } from '../config' import { createBuilder } from '../build' import { createServerModuleRunner } from '../ssr/runtime/serverModuleRunner' diff --git a/packages/vite/src/node/__tests__/plugins/assetImportMetaUrl.spec.ts b/packages/vite/src/node/__tests__/plugins/assetImportMetaUrl.spec.ts index 37dc870372da0f..19a82c34e3b786 100644 --- a/packages/vite/src/node/__tests__/plugins/assetImportMetaUrl.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/assetImportMetaUrl.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from 'vitest' import { parseAst } from 'rollup/parseAst' +import { resolveConfig } from '../..' import { assetImportMetaUrlPlugin } from '../../plugins/assetImportMetaUrl' -import { resolveConfig } from '../../config' import { PartialEnvironment } from '../../baseEnvironment' async function createAssetImportMetaurlPluginTransform() { diff --git a/packages/vite/src/node/__tests__/plugins/define.spec.ts b/packages/vite/src/node/__tests__/plugins/define.spec.ts index 166cabac83376f..40b449331d0b76 100644 --- a/packages/vite/src/node/__tests__/plugins/define.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/define.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest' +import { resolveConfig } from '../..' import { definePlugin } from '../../plugins/define' -import { resolveConfig } from '../../config' import { PartialEnvironment } from '../../baseEnvironment' async function createDefinePluginTransform( diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.spec.ts b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.spec.ts index 8a67660258386a..a405765e9dbdc0 100644 --- a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.spec.ts @@ -1,8 +1,8 @@ import { resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { describe, expect, it } from 'vitest' +import { normalizePath } from '../../..' import { transformDynamicImport } from '../../../plugins/dynamicImportVars' -import { normalizePath } from '../../../utils' import { isWindows } from '../../../../shared/utils' const __dirname = resolve(fileURLToPath(import.meta.url), '..') diff --git a/packages/vite/src/node/__tests__/plugins/import.spec.ts b/packages/vite/src/node/__tests__/plugins/import.spec.ts index 89fbd80d8ecdc1..6977ece16d9205 100644 --- a/packages/vite/src/node/__tests__/plugins/import.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/import.spec.ts @@ -1,4 +1,5 @@ import { beforeEach, describe, expect, test, vi } from 'vitest' +import '../..' import { transformCjsImport } from '../../plugins/importAnalysis' describe('transformCjsImport', () => { diff --git a/packages/vite/src/node/__tests__/plugins/modulePreloadPolyfill/modulePreloadPolyfill.spec.ts b/packages/vite/src/node/__tests__/plugins/modulePreloadPolyfill/modulePreloadPolyfill.spec.ts index 3b24fbd5203baa..067892fe109f00 100644 --- a/packages/vite/src/node/__tests__/plugins/modulePreloadPolyfill/modulePreloadPolyfill.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/modulePreloadPolyfill/modulePreloadPolyfill.spec.ts @@ -1,6 +1,6 @@ import { describe, it } from 'vitest' import type { ModuleFormat, RollupOutput } from 'rollup' -import { build } from '../../../build' +import { build } from '../../..' import { modulePreloadPolyfillId } from '../../../plugins/modulePreloadPolyfill' const buildProject = ({ format = 'es' as ModuleFormat } = {}) => diff --git a/packages/vite/src/node/__tests__/resolve.spec.ts b/packages/vite/src/node/__tests__/resolve.spec.ts index 111cdb99a6b1a0..fda33ef96806c9 100644 --- a/packages/vite/src/node/__tests__/resolve.spec.ts +++ b/packages/vite/src/node/__tests__/resolve.spec.ts @@ -1,6 +1,6 @@ import { join } from 'node:path' import { describe, expect, onTestFinished, test } from 'vitest' -import { createServer } from '../server' +import { createServer } from '..' import { createServerModuleRunner } from '../ssr/runtime/serverModuleRunner' import type { InlineConfig } from '../config' import { build } from '../build' diff --git a/packages/vite/src/node/__tests__/scan.spec.ts b/packages/vite/src/node/__tests__/scan.spec.ts index 6fa9f76d1ceac4..8f9134c15ccfe5 100644 --- a/packages/vite/src/node/__tests__/scan.spec.ts +++ b/packages/vite/src/node/__tests__/scan.spec.ts @@ -1,4 +1,5 @@ import { describe, expect, test } from 'vitest' +import '..' import { commentRE, importsRE, scriptRE } from '../optimizer/scan' import { multilineCommentsRE, singlelineCommentsRE } from '../utils' diff --git a/packages/vite/src/node/server/__tests__/moduleGraph.spec.ts b/packages/vite/src/node/server/__tests__/moduleGraph.spec.ts index 6efcb02c4f8eac..5ae3d221d7951c 100644 --- a/packages/vite/src/node/server/__tests__/moduleGraph.spec.ts +++ b/packages/vite/src/node/server/__tests__/moduleGraph.spec.ts @@ -1,4 +1,5 @@ import { describe, expect, it } from 'vitest' +import '../..' import { EnvironmentModuleGraph } from '../moduleGraph' import type { ModuleNode } from '../mixedModuleGraph' import { ModuleGraph } from '../mixedModuleGraph' diff --git a/packages/vite/src/node/server/__tests__/watcher.spec.ts b/packages/vite/src/node/server/__tests__/watcher.spec.ts index 2d6998bea630f4..a97e48ccb09930 100644 --- a/packages/vite/src/node/server/__tests__/watcher.spec.ts +++ b/packages/vite/src/node/server/__tests__/watcher.spec.ts @@ -1,7 +1,7 @@ import { resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { afterEach, describe, expect, it, vi } from 'vitest' -import { type ViteDevServer, createServer } from '../index' +import { type ViteDevServer, createServer } from '../..' const stubGetWatchedCode = /\(\)\s*\{\s*return this;\s*\}/ diff --git a/packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts index a4439aa726e5d7..5f37807803efbf 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts @@ -3,7 +3,7 @@ import path from 'node:path' import fs from 'node:fs' import { stripVTControlCharacters } from 'node:util' import { expect, test } from 'vitest' -import { createServer } from '../../server' +import { createServer } from '../..' import { normalizePath } from '../../utils' const root = fileURLToPath(new URL('./', import.meta.url)) diff --git a/packages/vite/src/node/ssr/__tests__/ssrStacktrace.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrStacktrace.spec.ts index a334c5078abd79..35bf20ad16b242 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrStacktrace.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrStacktrace.spec.ts @@ -1,6 +1,6 @@ import { fileURLToPath } from 'node:url' import { test } from 'vitest' -import { createServer } from '../../server' +import { createServer } from '../..' const root = fileURLToPath(new URL('./', import.meta.url)) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index e8570c6d4afedf..e73e47200ee78f 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -56,25 +56,25 @@ test('namespace import', async () => { test('export function declaration', async () => { expect(await ssrTransformSimpleCode(`export function foo() {}`)) .toMatchInlineSnapshot(` - "function foo() {} - Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }});" + "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }}); + function foo() {}" `) }) test('export class declaration', async () => { expect(await ssrTransformSimpleCode(`export class foo {}`)) .toMatchInlineSnapshot(` - "class foo {} - Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }});" + "Object.defineProperty(__vite_ssr_exports__, "foo", { enumerable: true, configurable: true, get(){ return foo }}); + class foo {}" `) }) test('export var declaration', async () => { expect(await ssrTransformSimpleCode(`export const a = 1, b = 2`)) .toMatchInlineSnapshot(` - "const a = 1, b = 2 - 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(){ return a }}); + Object.defineProperty(__vite_ssr_exports__, "b", { enumerable: true, configurable: true, get(){ return b }}); + const a = 1, b = 2" `) }) @@ -82,9 +82,9 @@ test('export named', async () => { expect( await ssrTransformSimpleCode(`const a = 1, b = 2; export { a, b as c }`), ).toMatchInlineSnapshot(` - "const a = 1, b = 2; - 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(){ return a }}); + Object.defineProperty(__vite_ssr_exports__, "c", { enumerable: true, configurable: true, get(){ return b }}); + const a = 1, b = 2; " `) }) @@ -92,10 +92,10 @@ test('export named from', async () => { expect( await ssrTransformSimpleCode(`export { ref, computed as c } from 'vue'`), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref","computed"]}); - - 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(){ return __vite_ssr_import_0__.ref }}); + Object.defineProperty(__vite_ssr_exports__, "c", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__.computed }}); + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref","computed"]}); + " `) }) @@ -105,9 +105,9 @@ test('named exports of imported binding', async () => { `import {createApp} from 'vue';export {createApp}`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["createApp"]}); - - 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(){ return __vite_ssr_import_0__.createApp }}); + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["createApp"]}); + " `) }) @@ -129,9 +129,9 @@ test('export * from', async () => { test('export * as from', async () => { expect(await ssrTransformSimpleCode(`export * as foo from 'vue'`)) .toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue"); - - 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(){ return __vite_ssr_import_0__ }}); + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue"); + " `) }) @@ -139,9 +139,9 @@ test('export * as from arbitrary module namespace identifier', async () => { expect( await ssrTransformSimpleCode(`export * as "arbitrary string" from 'vue'`), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue"); - - 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(){ return __vite_ssr_import_0__ }}); + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue"); + " `) }) @@ -151,8 +151,8 @@ test('export as arbitrary module namespace identifier', async () => { `const something = "Something";export { something as "arbitrary string" };`, ), ).toMatchInlineSnapshot(` - "const something = "Something"; - 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(){ return something }}); + const something = "Something";" `) }) @@ -162,9 +162,9 @@ test('export as from arbitrary module namespace identifier', async () => { `export { "arbitrary string2" as "arbitrary string" } from 'vue';`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["arbitrary string2"]}); - - 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(){ return __vite_ssr_import_0__["arbitrary string2"] }}); + const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["arbitrary string2"]}); + " `) }) @@ -209,8 +209,8 @@ test('dynamic import', async () => { `export const i = () => import('./foo')`, ) expect(result?.code).toMatchInlineSnapshot(` - "const i = () => __vite_ssr_dynamic_import__('./foo') - Object.defineProperty(__vite_ssr_exports__, "i", { enumerable: true, configurable: true, get(){ return i }});" + "Object.defineProperty(__vite_ssr_exports__, "i", { enumerable: true, configurable: true, get(){ return i }}); + const i = () => __vite_ssr_dynamic_import__('./foo')" `) expect(result?.deps).toEqual([]) expect(result?.dynamicDeps).toEqual(['./foo']) @@ -382,11 +382,11 @@ test('should declare variable for imported super class', async () => { `export class B extends Foo {}`, ), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("./dependency", {"importedNames":["Foo"]}); + "Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ return B }}); + 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 {} - Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ return B }}); Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, value: A });" `) }) @@ -422,9 +422,9 @@ test('should handle default export variants', async () => { `export default class A {}\n` + `export class B extends A {}`, ), ).toMatchInlineSnapshot(` - "class A {}; + "Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ return B }}); + class A {}; class B extends A {} - Object.defineProperty(__vite_ssr_exports__, "B", { enumerable: true, configurable: true, get(){ return B }}); Object.defineProperty(__vite_ssr_exports__, "default", { enumerable: true, configurable: true, value: A });" `) }) @@ -875,12 +875,12 @@ 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 }}); + function fn1() { + };function fn2() { } - Object.defineProperty(__vite_ssr_exports__, "fn1", { enumerable: true, configurable: true, get(){ return fn1 }});;function fn2() { - } - Object.defineProperty(__vite_ssr_exports__, "fn2", { enumerable: true, configurable: true, get(){ return fn2 }}); " `) }) @@ -981,7 +981,8 @@ export class Test { };`.trim() expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); + "Object.defineProperty(__vite_ssr_exports__, "Test", { enumerable: true, configurable: true, get(){ return Test }}); + const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]}); if (false) { const foo = 'foo'; @@ -1006,8 +1007,7 @@ export class Test { console.log((0,__vite_ssr_import_0__.bar)) } } - } - Object.defineProperty(__vite_ssr_exports__, "Test", { enumerable: true, configurable: true, get(){ return Test }});;;" + };;" `) }) @@ -1180,13 +1180,13 @@ export * as bar from './bar' console.log(bar) `), ).toMatchInlineSnapshot(` - "const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]}); + "Object.defineProperty(__vite_ssr_exports__, "bar", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__ }}); + const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]}); __vite_ssr_exports__.default = (0,__vite_ssr_import_0__.foo)(); const __vite_ssr_import_1__ = await __vite_ssr_import__("./bar"); - - Object.defineProperty(__vite_ssr_exports__, "bar", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_1__ }});; + ; console.log(bar) " `) diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/README.md b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/README.md new file mode 100644 index 00000000000000..42cebdf4ea801d --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/README.md @@ -0,0 +1,9 @@ +Cyclic import example based on https://github.com/vitejs/vite/issues/14048#issuecomment-2354774156 + +```mermaid +flowchart TD + B(dep1.js) -->|dep1| A(index.js) + A -->|dep1| C(dep2.js) + C -->|dep2| A + A -->|dep1, dep2| entry.js +``` diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/package.json b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/package.json new file mode 100644 index 00000000000000..3dbc1ca591c055 --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/dep1.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/dep1.js new file mode 100644 index 00000000000000..052c10ef6e602c --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/dep1.js @@ -0,0 +1 @@ +export const dep1 = { ok: true }; diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/dep2.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/dep2.js new file mode 100644 index 00000000000000..be498e991723fb --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/dep2.js @@ -0,0 +1,2 @@ +import { dep1 } from "./index.js" +export const dep2 = { ok: dep1.ok } diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/index.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/index.js new file mode 100644 index 00000000000000..49fa0342503c71 --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/index.js @@ -0,0 +1,5 @@ +import { dep1 } from './dep1.js' +export { dep1 } + +import { dep2 } from './dep2.js' +export { dep2 } diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/dep1.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/dep1.js new file mode 100644 index 00000000000000..052c10ef6e602c --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/dep1.js @@ -0,0 +1 @@ +export const dep1 = { ok: true }; diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/dep2.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/dep2.js new file mode 100644 index 00000000000000..be498e991723fb --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/dep2.js @@ -0,0 +1,2 @@ +import { dep1 } from "./index.js" +export const dep2 = { ok: dep1.ok } diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/index.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/index.js new file mode 100644 index 00000000000000..49f8047b941b02 --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/index.js @@ -0,0 +1,2 @@ +export { dep1 } from './dep1.js' +export { dep2 } from "./dep2.js" diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/dep1.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/dep1.js new file mode 100644 index 00000000000000..052c10ef6e602c --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/dep1.js @@ -0,0 +1 @@ +export const dep1 = { ok: true }; diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/dep2.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/dep2.js new file mode 100644 index 00000000000000..be498e991723fb --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/dep2.js @@ -0,0 +1,2 @@ +import { dep1 } from "./index.js" +export const dep2 = { ok: dep1.ok } diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/index.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/index.js new file mode 100644 index 00000000000000..e032a766eab42d --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/index.js @@ -0,0 +1,4 @@ +import { dep1 } from './dep1.js' +import { dep2 } from './dep2.js' +export { dep1 } +export { dep2 } diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/dep1.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/dep1.js new file mode 100644 index 00000000000000..052c10ef6e602c --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/dep1.js @@ -0,0 +1 @@ +export const dep1 = { ok: true }; diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/dep2.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/dep2.js new file mode 100644 index 00000000000000..be498e991723fb --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/dep2.js @@ -0,0 +1,2 @@ +import { dep1 } from "./index.js" +export const dep2 = { ok: dep1.ok } diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/index.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/index.js new file mode 100644 index 00000000000000..bcbfe36b7660f7 --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/index.js @@ -0,0 +1,2 @@ +export * from './dep1.js' +export * from './dep2.js' diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/dep1.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/dep1.js new file mode 100644 index 00000000000000..052c10ef6e602c --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/dep1.js @@ -0,0 +1 @@ +export const dep1 = { ok: true }; diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/dep2.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/dep2.js new file mode 100644 index 00000000000000..be498e991723fb --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/dep2.js @@ -0,0 +1,2 @@ +import { dep1 } from "./index.js" +export const dep2 = { ok: dep1.ok } diff --git a/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/index.js b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/index.js new file mode 100644 index 00000000000000..f748a394a7eb77 --- /dev/null +++ b/packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/index.js @@ -0,0 +1,5 @@ +import { dep2 } from './dep2.js' +export { dep2 } + +import { dep1 } from './dep1.js' +export { dep1 } 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 4c47558c210517..074ed12c63cb37 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 @@ -232,6 +232,35 @@ describe('module runner initialization', async () => { const mod = await runner.import('/fixtures/no-this/importer.js') expect(mod.result).toBe(undefined) }) + + it.for([ + '/fixtures/cyclic2/test1/index.js', + '/fixtures/cyclic2/test2/index.js', + '/fixtures/cyclic2/test3/index.js', + '/fixtures/cyclic2/test4/index.js', + ] as const)(`cyclic %s`, async (entry, { runner }) => { + const mod = await runner.import(entry) + expect({ ...mod }).toEqual({ + dep1: { + ok: true, + }, + dep2: { + ok: true, + }, + }) + }) + + it(`cyclic invalid`, async ({ runner }) => { + // Node also fails but with a different message + // $ node packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/index.js + // ReferenceError: Cannot access 'dep1' before initialization + await expect(() => + runner.import('/fixtures/cyclic2/test5/index.js'), + ).rejects.toMatchObject({ + name: 'ReferenceError', + message: `Cannot access '__vite_ssr_import_1__' before initialization`, + }) + }) }) describe('optimize-deps', async () => { diff --git a/packages/vite/src/node/ssr/runtime/__tests__/utils.ts b/packages/vite/src/node/ssr/runtime/__tests__/utils.ts index 7ab3a40fbfef8e..7424c3c7616276 100644 --- a/packages/vite/src/node/ssr/runtime/__tests__/utils.ts +++ b/packages/vite/src/node/ssr/runtime/__tests__/utils.ts @@ -7,7 +7,7 @@ import type { ModuleRunner } from 'vite/module-runner' import type { ServerModuleRunnerOptions } from '../serverModuleRunner' import type { ViteDevServer } from '../../../server' import type { InlineConfig } from '../../../config' -import { createServer } from '../../../server' +import { createServer } from '../../..' import { createServerModuleRunner } from '../serverModuleRunner' import type { DevEnvironment } from '../../../server/environment' diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index c4552f73229663..9d5a1a64482107 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -157,11 +157,11 @@ async function ssrTransformScript( return importId } - function defineExport(position: number, name: string, local = name) { + function defineExport(_position: number, name: string, local = name) { s.appendLeft( - position, - `\nObject.defineProperty(${ssrModuleExportsKey}, ${JSON.stringify(name)}, ` + - `{ enumerable: true, configurable: true, get(){ return ${local} }});`, + fileStartIndex, + `Object.defineProperty(${ssrModuleExportsKey}, ${JSON.stringify(name)}, ` + + `{ enumerable: true, configurable: true, get(){ return ${local} }});\n`, ) } diff --git a/playground/hmr-ssr/__tests__/hmr-ssr.spec.ts b/playground/hmr-ssr/__tests__/hmr-ssr.spec.ts index d41ca3c196555b..3ce96393af5736 100644 --- a/playground/hmr-ssr/__tests__/hmr-ssr.spec.ts +++ b/playground/hmr-ssr/__tests__/hmr-ssr.spec.ts @@ -851,13 +851,16 @@ if (!isBuild) { editFile('self-accept-within-circular/c.js', (code) => code.replace(`export const c = 'c'`, `export const c = 'cc'`), ) + // it throws a same error as browser case, + // but it doesn't auto reload and it calls `hot.accept` called with `undefined` + await untilUpdated(() => el(), '') + + // test reloading manually for now + // TODO: why clearCache not working? + // runner.clearCache(); + // runner.import('/self-accept-within-circular/index') + await setupModuleRunner('/self-accept-within-circular/index') await untilUpdated(() => el(), 'cc') - await vi.waitFor(() => { - expect(serverLogs.length).greaterThanOrEqual(1) - // Should still keep hmr update, but it'll error on the browser-side and will refresh itself. - // Match on full log not possible because of color markers - expect(serverLogs.at(-1)!).toContain('hmr update') - }) }) test('hmr should not reload if no accepted within circular imported files', async (ctx) => { diff --git a/playground/hmr-ssr/self-accept-within-circular/c.js b/playground/hmr-ssr/self-accept-within-circular/c.js index 47b6d494969917..7fe30c447965a2 100644 --- a/playground/hmr-ssr/self-accept-within-circular/c.js +++ b/playground/hmr-ssr/self-accept-within-circular/c.js @@ -8,5 +8,5 @@ function render(content) { render(c) import.meta.hot?.accept((nextExports) => { - render(nextExports.c) + render(nextExports?.c) }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c995e2fb93a89..49db012e86e533 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -467,6 +467,8 @@ importers: packages/vite/src/node/ssr/runtime/__tests__/fixtures/cjs-external: {} + packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2: {} + packages/vite/src/node/ssr/runtime/__tests__/fixtures/esm-external: {} playground: