Skip to content

Commit 2281311

Browse files
committed
get the test to pass
1 parent 811683f commit 2281311

File tree

1 file changed

+32
-29
lines changed

1 file changed

+32
-29
lines changed

packages/vite/src/node/ssr/ssrTransform.ts

+32-29
Original file line numberDiff line numberDiff line change
@@ -126,51 +126,54 @@ async function ssrTransformScript(
126126
) {
127127
const source = importNode.source.value as string
128128
deps.add(source)
129-
const importId = `__vite_ssr_import_${uid++}__`
130129

131130
// Reduce metadata to undefined if it's all default values
132-
if (
133-
metadata &&
134-
(metadata.importedNames == null || metadata.importedNames.length === 0)
135-
) {
136-
metadata = undefined
137-
}
138-
const metadataStr = metadata ? `, ${JSON.stringify(metadata)}` : ''
131+
const metadataArg =
132+
(metadata?.importedNames?.length ?? 0) > 0
133+
? `, ${JSON.stringify(metadata)}`
134+
: ''
139135

140-
// Track how many lines the original import statement spans, so we can preserve the line offset.
141-
let linesSpanned = 1
142-
for (let i = importNode.start; i < importNode.end; i++) {
143-
if (code[i] === '\n') {
144-
linesSpanned++
145-
}
146-
}
136+
const importId = `__vite_ssr_import_${uid++}__`
137+
const transformedImport = `const ${importId} = await ${ssrImportKey}(${JSON.stringify(
138+
source,
139+
)}${metadataArg});`
147140

148-
s.update(
149-
importNode.start,
150-
importNode.end,
151-
`const ${importId} = await ${ssrImportKey}(${JSON.stringify(
152-
source,
153-
)}${metadataStr});${'\n'.repeat(linesSpanned - 1)}`,
154-
)
141+
s.update(importNode.start, importNode.end, transformedImport)
155142

156143
// Check for non-whitespace characters between the last import and the
157-
// current one.
144+
// current one, to determine if hoisting is needed.
145+
// TODO: Account for comments between imports.
158146
const nonWhitespaceRegex = /\S/g
159147
nonWhitespaceRegex.lastIndex = index
160148
nonWhitespaceRegex.exec(code)
161-
162-
// TODO: Account for comments between imports.
163149
if (importNode.start > nonWhitespaceRegex.lastIndex) {
164-
// By moving the import to the top of the module, we ensure that it's
165-
// imported before it's used.
150+
// Imports are moved to the top of the file (AKA “hoisting”) to ensure any
151+
// non-import statements before them are executed after the import. This
152+
// aligns SSR imports with native ESM import behavior.
166153
s.move(importNode.start, importNode.end, index)
167154
} else {
168-
// Only update hoistIndex when not hoisting the current import. This
155+
// Only update hoistIndex when *not* hoisting the current import. This
169156
// ensures that once any import in this module has been hoisted, all
170-
// remaining imports will also be hoisted.
157+
// remaining imports will also be hoisted. This is inherently true because
158+
// we work from the top of the file downward.
171159
hoistIndex = importNode.end
172160
}
173161

162+
// Track how many lines the original import statement spans, so we can
163+
// preserve the line offset.
164+
let linesSpanned = 1
165+
for (let i = importNode.start; i < importNode.end; i++) {
166+
if (code[i] === '\n') {
167+
linesSpanned++
168+
}
169+
}
170+
if (linesSpanned > 1) {
171+
// This leaves behind any extra newlines that were removed during
172+
// transformation, in the position of the original import statement
173+
// (before any hoisting).
174+
s.prependRight(importNode.end, '\n'.repeat(linesSpanned - 1))
175+
}
176+
174177
return importId
175178
}
176179

0 commit comments

Comments
 (0)