Skip to content

Commit

Permalink
fix(ssr): inject identity function at the top (vitejs#18449)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red authored Oct 24, 2024
1 parent d23a493 commit 0ab20a3
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 15 deletions.
48 changes: 35 additions & 13 deletions packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ test('named import', async () => {
`import { ref } from 'vue';function foo() { return ref(0) }`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref"]});
const __vite_ssr_identity__ = v => v;
"const __vite_ssr_identity__ = v => v;
const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["ref"]});
function foo() { return __vite_ssr_identity__(__vite_ssr_import_0__.ref)(0) }"
`)
})
Expand All @@ -38,8 +38,8 @@ test('named import: arbitrary module namespace specifier', async () => {
`import { "some thing" as ref } from 'vue';function foo() { return ref(0) }`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["some thing"]});
const __vite_ssr_identity__ = v => v;
"const __vite_ssr_identity__ = v => v;
const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["some thing"]});
function foo() { return __vite_ssr_identity__(__vite_ssr_import_0__["some thing"])(0) }"
`)
})
Expand Down Expand Up @@ -223,8 +223,8 @@ test('do not rewrite method definition', async () => {
`import { fn } from 'vue';class A { fn() { fn() } }`,
)
expect(result?.code).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["fn"]});
const __vite_ssr_identity__ = v => v;
"const __vite_ssr_identity__ = v => v;
const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["fn"]});
class A { fn() { __vite_ssr_identity__(__vite_ssr_import_0__.fn)() } }"
`)
expect(result?.deps).toEqual(['vue'])
Expand Down Expand Up @@ -536,8 +536,8 @@ test('overwrite bindings', async () => {
`function g() { const f = () => { const inject = true }; console.log(inject) }\n`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["inject"]});
const __vite_ssr_identity__ = v => v;
"const __vite_ssr_identity__ = v => v;
const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["inject"]});
const a = { inject: __vite_ssr_import_0__.inject }
const b = { test: __vite_ssr_import_0__.inject }
function c() { const { test: inject } = { test: true }; console.log(inject) }
Expand Down Expand Up @@ -862,8 +862,8 @@ test('jsx', async () => {
const result = await transformWithEsbuild(code, id)
expect(await ssrTransformSimpleCode(result.code, '/foo.jsx'))
.toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__("react", {"importedNames":["default"]});
const __vite_ssr_identity__ = v => v;
"const __vite_ssr_identity__ = v => v;
const __vite_ssr_import_0__ = await __vite_ssr_import__("react", {"importedNames":["default"]});
const __vite_ssr_import_1__ = await __vite_ssr_import__("foo", {"importedNames":["Foo","Slot"]});
Expand Down Expand Up @@ -955,8 +955,8 @@ foo()`,
),
).toMatchInlineSnapshot(`
"#!/usr/bin/env node
const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
const __vite_ssr_identity__ = v => v;
const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["foo"]});
__vite_ssr_identity__(__vite_ssr_import_0__.foo)()"
`)
Expand Down Expand Up @@ -992,8 +992,8 @@ export class Test {
};`.trim()

expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]});
const __vite_ssr_identity__ = v => v;
"const __vite_ssr_identity__ = v => v;
const __vite_ssr_import_0__ = await __vite_ssr_import__("foobar", {"importedNames":["foo","bar"]});
if (false) {
const foo = 'foo'
Expand Down Expand Up @@ -1183,3 +1183,25 @@ console.log(foo + 2)
"
`)
})

test('identity function is declared before used', async () => {
expect(
await ssrTransformSimpleCode(`
import { foo } from './foo'
export default foo()
export * as bar from './bar'
console.log(bar)
`),
).toMatchInlineSnapshot(`
"const __vite_ssr_identity__ = v => v;
const __vite_ssr_import_0__ = await __vite_ssr_import__("./foo", {"importedNames":["foo"]});
__vite_ssr_exports__.default = __vite_ssr_identity__(__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)
"
`)
})
5 changes: 3 additions & 2 deletions packages/vite/src/node/ssr/ssrTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ async function ssrTransformScript(
const declaredConst = new Set<string>()

// hoist at the start of the file, after the hashbang
let hoistIndex = hashbangRE.exec(code)?.[0].length ?? 0
const fileStartIndex = hashbangRE.exec(code)?.[0].length ?? 0
let hoistIndex = fileStartIndex

function defineImport(
index: number,
Expand Down Expand Up @@ -375,7 +376,7 @@ async function ssrTransformScript(
})

if (injectIdentityFunction) {
s.prependLeft(hoistIndex, `const ${ssrIdentityFunction} = v => v;\n`)
s.prependLeft(fileStartIndex, `const ${ssrIdentityFunction} = v => v;\n`)
}

let map = s.generateMap({ hires: 'boundary' })
Expand Down

0 comments on commit 0ab20a3

Please sign in to comment.